From 4871f12645ce9ebbbc13c6fb1d8b6eb46f8604bf Mon Sep 17 00:00:00 2001 From: Krzysztof Taborowski <52448413+ktaborowski@users.noreply.github.com> Date: Wed, 23 Oct 2019 21:31:02 +0200 Subject: [PATCH] [third-party] change end of line character from CRLF do LF (#4250) Also remove .gitattibutes from third-party --- third_party/.gitattributes | 4 - .../NordicSemiconductor/cmsis/arm_math.h | 14060 ++++++++-------- .../NordicSemiconductor/cmsis/cmsis_armcc.h | 1468 +- .../cmsis/cmsis_armcc_V6.h | 3600 ++-- .../NordicSemiconductor/cmsis/cmsis_gcc.h | 2746 +-- .../NordicSemiconductor/cmsis/core_cm4.h | 3874 ++--- .../NordicSemiconductor/cmsis/core_cmFunc.h | 172 +- .../NordicSemiconductor/cmsis/core_cmInstr.h | 174 +- .../NordicSemiconductor/cmsis/core_cmSimd.h | 192 +- .../dependencies/app_util.h | 2620 +-- .../dependencies/app_util_platform.c | 258 +- .../dependencies/app_util_platform.h | 558 +- .../dependencies/nordic_common.h | 430 +- .../dependencies/nrf_assert.h | 244 +- .../dependencies/nrf_error.h | 190 +- .../dependencies/nrf_log.h | 582 +- .../dependencies/nrf_log_internal.h | 1056 +- .../dependencies/sdk_common.h | 154 +- .../dependencies/sdk_config.h | 1562 +- .../dependencies/sdk_errors.h | 334 +- .../dependencies/sdk_macros.h | 430 +- .../NordicSemiconductor/dependencies/sdk_os.h | 152 +- .../dependencies/sdk_resources.h | 172 +- .../drivers/clock/nrf_drv_clock.c | 1202 +- .../drivers/clock/nrf_drv_clock.h | 594 +- .../drivers/common/nrf_drv_common.h | 126 +- .../drivers/power/nrf_drv_power.c | 832 +- .../drivers/power/nrf_drv_power.h | 464 +- .../drivers/radio/README.md | 4 +- .../drivers/radio/nrf_802154.h | 2358 +-- .../drivers/systick/nrf_drv_systick.h | 160 +- .../libraries/app_error/app_error.c | 278 +- .../libraries/app_error/app_error.h | 384 +- .../libraries/app_error/app_error_weak.c | 120 +- .../libraries/app_error/app_error_weak.h | 174 +- .../libraries/atfifo/nrf_atfifo.c | 378 +- .../libraries/atfifo/nrf_atfifo.h | 848 +- .../libraries/atfifo/nrf_atfifo_internal.h | 1154 +- .../libraries/atomic/nrf_atomic.c | 898 +- .../libraries/atomic/nrf_atomic.h | 548 +- .../libraries/atomic/nrf_atomic_internal.h | 686 +- .../libraries/delay/nrf_delay.h | 160 +- .../libraries/usb/app_usbd.c | 3838 ++--- .../libraries/usb/app_usbd.h | 1632 +- .../libraries/usb/app_usbd_class_base.h | 2206 +-- .../libraries/usb/app_usbd_core.c | 2470 +-- .../libraries/usb/app_usbd_core.h | 444 +- .../libraries/usb/app_usbd_descriptor.h | 674 +- .../libraries/usb/app_usbd_langid.h | 600 +- .../libraries/usb/app_usbd_request.h | 712 +- .../libraries/usb/app_usbd_serial_num.c | 168 +- .../libraries/usb/app_usbd_serial_num.h | 150 +- .../libraries/usb/app_usbd_string_desc.c | 590 +- .../libraries/usb/app_usbd_string_desc.h | 358 +- .../libraries/usb/app_usbd_types.h | 556 +- .../usb/class/cdc/acm/app_usbd_cdc_acm.c | 2398 +-- .../usb/class/cdc/acm/app_usbd_cdc_acm.h | 724 +- .../class/cdc/acm/app_usbd_cdc_acm_internal.h | 574 +- .../usb/class/cdc/app_usbd_cdc_desc.h | 416 +- .../usb/class/cdc/app_usbd_cdc_types.h | 720 +- .../usb/config/app_usbd_string_config.h | 260 +- .../libraries/utf_converter/LICENSE | 18 +- .../libraries/utf_converter/utf.c | 700 +- .../libraries/utf_converter/utf.h | 122 +- .../s140_nrf52_6.1.1_license-agreement.txt | 70 +- .../softdevice/s140/headers/nrf52/nrf_mbr.h | 536 +- .../Examples/Main_RTT_InputEchoApp.c | 86 +- .../Examples/Main_RTT_MenuApp.c | 140 +- .../Examples/Main_RTT_PrintfTest.c | 236 +- .../Examples/Main_RTT_SpeedTestApp.c | 138 +- third_party/jlink/SEGGER_RTT_V640/License.txt | 88 +- third_party/jlink/SEGGER_RTT_V640/README.txt | 40 +- .../jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.c | 3522 ++-- .../jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.h | 520 +- .../SEGGER_RTT_V640/RTT/SEGGER_RTT_Conf.h | 680 +- .../SEGGER_RTT_V640/RTT/SEGGER_RTT_printf.c | 1020 +- .../Syscalls/SEGGER_RTT_Syscalls_GCC.c | 260 +- .../Syscalls/SEGGER_RTT_Syscalls_IAR.c | 248 +- .../Syscalls/SEGGER_RTT_Syscalls_KEIL.c | 748 +- .../Syscalls/SEGGER_RTT_Syscalls_SES.c | 514 +- 80 files changed, 37786 insertions(+), 37790 deletions(-) delete mode 100644 third_party/.gitattributes diff --git a/third_party/.gitattributes b/third_party/.gitattributes deleted file mode 100644 index 0dc02e6dd..000000000 --- a/third_party/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -# Disable automatic text file line-ending -# normalization for third-party code. -* !text - diff --git a/third_party/NordicSemiconductor/cmsis/arm_math.h b/third_party/NordicSemiconductor/cmsis/arm_math.h index 0be65d335..e21a3cc37 100644 --- a/third_party/NordicSemiconductor/cmsis/arm_math.h +++ b/third_party/NordicSemiconductor/cmsis/arm_math.h @@ -1,7030 +1,7030 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2015 ARM Limited. All rights reserved. -* -* $Date: 20. October 2015 -* $Revision: V1.4.5 b -* -* Project: CMSIS DSP Library -* Title: arm_math.h -* -* Description: Public header file for CMSIS DSP Library -* -* Target Processor: Cortex-M7/Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. - * -------------------------------------------------------------------- */ - -/** - * @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 - -/* ignore some GCC warnings */ -#if defined ( __GNUC__ ) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -#define __CMSIS_GENERIC /* disable NVIC and Systick functions */ - -#if defined(ARM_MATH_CM7) - #include "core_cm7.h" -#elif defined (ARM_MATH_CM4) - #include "core_cm4.h" -#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 -#else - #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS or ARM_MATH_CM0" -#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_SIZE 256 -#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)) - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #define __SIMD32_TYPE int32_t - #define CMSIS_UNUSED __attribute__((unused)) - -#elif defined __GNUC__ - #define __SIMD32_TYPE int32_t - #define CMSIS_UNUSED __attribute__((unused)) - -#elif defined __ICCARM__ - #define __SIMD32_TYPE int32_t __packed - #define CMSIS_UNUSED - -#elif defined __CSMC__ - #define __SIMD32_TYPE int32_t - #define CMSIS_UNUSED - -#elif defined __TASKING__ - #define __SIMD32_TYPE __unaligned int32_t - #define CMSIS_UNUSED - -#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) - /** - * @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 - - - /** - * @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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - - 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__)) ) - static __INLINE uint32_t __CLZ( - q31_t data); - - 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. - */ - - 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. - */ - 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) - 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) - - /* - * @brief C custom defined QADD8 for M3 and M0 processors - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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 - */ - 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) )); - } - -#endif /* defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ - - - /** - * @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 . */ -#ifdef ARM_MATH_CM0_FAMILY - 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. - */ - 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. - */ - 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. - */ - static __INLINE q15_t arm_pid_q15( - arm_pid_instance_q15 * S, - q15_t in) - { - q63_t acc; - q15_t out; - -#ifndef ARM_MATH_CM0_FAMILY - __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 - */ - 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. - */ - 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 - */ - 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. - */ - 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. - * - */ - 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. - */ - 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 - */ - 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. - */ - 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. - * - */ - 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. - * - */ - 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. - * - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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(__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 - - -#if defined ( __GNUC__ ) -#pragma GCC diagnostic pop -#endif - -#endif /* _ARM_MATH_H */ - -/** - * - * End of file. - */ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2015 ARM Limited. All rights reserved. +* +* $Date: 20. October 2015 +* $Revision: V1.4.5 b +* +* Project: CMSIS DSP Library +* Title: arm_math.h +* +* Description: Public header file for CMSIS DSP Library +* +* Target Processor: Cortex-M7/Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. + * -------------------------------------------------------------------- */ + +/** + * @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 + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#define __CMSIS_GENERIC /* disable NVIC and Systick functions */ + +#if defined(ARM_MATH_CM7) + #include "core_cm7.h" +#elif defined (ARM_MATH_CM4) + #include "core_cm4.h" +#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 +#else + #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS or ARM_MATH_CM0" +#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_SIZE 256 +#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)) + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __GNUC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __ICCARM__ + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED + +#elif defined __CSMC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED + +#elif defined __TASKING__ + #define __SIMD32_TYPE __unaligned int32_t + #define CMSIS_UNUSED + +#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) + /** + * @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 + + + /** + * @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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + + 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__)) ) + static __INLINE uint32_t __CLZ( + q31_t data); + + 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. + */ + + 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. + */ + 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) + 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) + + /* + * @brief C custom defined QADD8 for M3 and M0 processors + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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) )); + } + +#endif /* defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ + + + /** + * @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 . */ +#ifdef ARM_MATH_CM0_FAMILY + 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. + */ + 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. + */ + 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. + */ + static __INLINE q15_t arm_pid_q15( + arm_pid_instance_q15 * S, + q15_t in) + { + q63_t acc; + q15_t out; + +#ifndef ARM_MATH_CM0_FAMILY + __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 + */ + 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. + */ + 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 + */ + 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. + */ + 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. + * + */ + 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. + */ + 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 + */ + 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. + */ + 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. + * + */ + 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. + * + */ + 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. + * + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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(__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 + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* _ARM_MATH_H */ + +/** + * + * End of file. + */ diff --git a/third_party/NordicSemiconductor/cmsis/cmsis_armcc.h b/third_party/NordicSemiconductor/cmsis/cmsis_armcc.h index f2bb66a09..74c49c67d 100644 --- a/third_party/NordicSemiconductor/cmsis/cmsis_armcc.h +++ b/third_party/NordicSemiconductor/cmsis/cmsis_armcc.h @@ -1,734 +1,734 @@ -/**************************************************************************//** - * @file cmsis_armcc.h - * @brief CMSIS Cortex-M Core Function/Instruction Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#ifndef __CMSIS_ARMCC_H -#define __CMSIS_ARMCC_H - - -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) - #error "Please use ARM Compiler Toolchain V4.0.677 or later!" -#endif - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ - -/* intrinsic void __enable_irq(); */ -/* intrinsic void __disable_irq(); */ - -/** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value - */ -__STATIC_INLINE uint32_t __get_CONTROL(void) -{ - register uint32_t __regControl __ASM("control"); - return(__regControl); -} - - -/** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set - */ -__STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - register uint32_t __regControl __ASM("control"); - __regControl = control; -} - - -/** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value - */ -__STATIC_INLINE uint32_t __get_IPSR(void) -{ - register uint32_t __regIPSR __ASM("ipsr"); - return(__regIPSR); -} - - -/** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value - */ -__STATIC_INLINE uint32_t __get_APSR(void) -{ - register uint32_t __regAPSR __ASM("apsr"); - return(__regAPSR); -} - - -/** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - \return xPSR Register value - */ -__STATIC_INLINE uint32_t __get_xPSR(void) -{ - register uint32_t __regXPSR __ASM("xpsr"); - return(__regXPSR); -} - - -/** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value - */ -__STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - return(__regProcessStackPointer); -} - - -/** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - __regProcessStackPointer = topOfProcStack; -} - - -/** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value - */ -__STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - return(__regMainStackPointer); -} - - -/** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - __regMainStackPointer = topOfMainStack; -} - - -/** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value - */ -__STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - register uint32_t __regPriMask __ASM("primask"); - return(__regPriMask); -} - - -/** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask - */ -__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - register uint32_t __regPriMask __ASM("primask"); - __regPriMask = (priMask); -} - - -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) - -/** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __enable_fault_irq __enable_fiq - - -/** - \brief Disable FIQ - \details Disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __disable_fault_irq __disable_fiq - - -/** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value - */ -__STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - register uint32_t __regBasePri __ASM("basepri"); - return(__regBasePri); -} - - -/** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) -{ - register uint32_t __regBasePri __ASM("basepri"); - __regBasePri = (basePri & 0xFFU); -} - - -/** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) -{ - register uint32_t __regBasePriMax __ASM("basepri_max"); - __regBasePriMax = (basePri & 0xFFU); -} - - -/** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value - */ -__STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - return(__regFaultMask); -} - - -/** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set - */ -__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - __regFaultMask = (faultMask & (uint32_t)1); -} - -#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ - - -#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) - -/** - \brief Get FPSCR - \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value - */ -__STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - register uint32_t __regfpscr __ASM("fpscr"); - return(__regfpscr); -#else - return(0U); -#endif -} - - -/** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set - */ -__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - register uint32_t __regfpscr __ASM("fpscr"); - __regfpscr = (fpscr); -#endif -} - -#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ - - - -/*@} end of CMSIS_Core_RegAccFunctions */ - - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -/** - \brief No Operation - \details No Operation does nothing. This instruction can be used for code alignment purposes. - */ -#define __NOP __nop - - -/** - \brief Wait For Interrupt - \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. - */ -#define __WFI __wfi - - -/** - \brief Wait For Event - \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -#define __WFE __wfe - - -/** - \brief Send Event - \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -#define __SEV __sev - - -/** - \brief Instruction Synchronization Barrier - \details Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or memory, - after the instruction has been completed. - */ -#define __ISB() do {\ - __schedule_barrier();\ - __isb(0xF);\ - __schedule_barrier();\ - } while (0U) - -/** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -#define __DSB() do {\ - __schedule_barrier();\ - __dsb(0xF);\ - __schedule_barrier();\ - } while (0U) - -/** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -#define __DMB() do {\ - __schedule_barrier();\ - __dmb(0xF);\ - __schedule_barrier();\ - } while (0U) - -/** - \brief Reverse byte order (32 bit) - \details Reverses the byte order in integer value. - \param [in] value Value to reverse - \return Reversed value - */ -#define __REV __rev - - -/** - \brief Reverse byte order (16 bit) - \details Reverses the byte order in two unsigned short values. - \param [in] value Value to reverse - \return Reversed value - */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) -{ - rev16 r0, r0 - bx lr -} -#endif - -/** - \brief Reverse byte order in signed short value - \details Reverses the byte order in a signed short value with sign extension to integer. - \param [in] value Value to reverse - \return Reversed value - */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) -{ - revsh r0, r0 - bx lr -} -#endif - - -/** - \brief Rotate Right in unsigned value (32 bit) - \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] value Value to rotate - \param [in] value Number of Bits to rotate - \return Rotated value - */ -#define __ROR __ror - - -/** - \brief Breakpoint - \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. - */ -#define __BKPT(value) __breakpoint(value) - - -/** - \brief Reverse bit order of value - \details Reverses the bit order of the given value. - \param [in] value Value to reverse - \return Reversed value - */ -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) - #define __RBIT __rbit -#else -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) -{ - uint32_t result; - int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ - - result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value; value >>= 1U) - { - result <<= 1U; - result |= value & 1U; - s--; - } - result <<= s; /* shift when v's highest bits are zero */ - return(result); -} -#endif - - -/** - \brief Count leading zeros - \details Counts the number of leading zeros of a data value. - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ -#define __CLZ __clz - - -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) - -/** - \brief LDR Exclusive (8 bit) - \details Executes a exclusive LDR instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) -#else - #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") -#endif - - -/** - \brief LDR Exclusive (16 bit) - \details Executes a exclusive LDR instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) -#else - #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") -#endif - - -/** - \brief LDR Exclusive (32 bit) - \details Executes a exclusive LDR instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) -#else - #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") -#endif - - -/** - \brief STR Exclusive (8 bit) - \details Executes a exclusive STR instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXB(value, ptr) __strex(value, ptr) -#else - #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif - - -/** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXH(value, ptr) __strex(value, ptr) -#else - #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif - - -/** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXW(value, ptr) __strex(value, ptr) -#else - #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif - - -/** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. - */ -#define __CLREX __clrex - - -/** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -#define __SSAT __ssat - - -/** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -#define __USAT __usat - - -/** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value - */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) -{ - rrx r0, r0 - bx lr -} -#endif - - -/** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) - - -/** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) - - -/** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) - - -/** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -#define __STRBT(value, ptr) __strt(value, ptr) - - -/** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -#define __STRHT(value, ptr) __strt(value, ptr) - - -/** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -#define __STRT(value, ptr) __strt(value, ptr) - -#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - - -/* ################### Compiler specific Intrinsics ########################### */ -/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics - Access to dedicated SIMD instructions - @{ -*/ - -#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ - -#define __SADD8 __sadd8 -#define __QADD8 __qadd8 -#define __SHADD8 __shadd8 -#define __UADD8 __uadd8 -#define __UQADD8 __uqadd8 -#define __UHADD8 __uhadd8 -#define __SSUB8 __ssub8 -#define __QSUB8 __qsub8 -#define __SHSUB8 __shsub8 -#define __USUB8 __usub8 -#define __UQSUB8 __uqsub8 -#define __UHSUB8 __uhsub8 -#define __SADD16 __sadd16 -#define __QADD16 __qadd16 -#define __SHADD16 __shadd16 -#define __UADD16 __uadd16 -#define __UQADD16 __uqadd16 -#define __UHADD16 __uhadd16 -#define __SSUB16 __ssub16 -#define __QSUB16 __qsub16 -#define __SHSUB16 __shsub16 -#define __USUB16 __usub16 -#define __UQSUB16 __uqsub16 -#define __UHSUB16 __uhsub16 -#define __SASX __sasx -#define __QASX __qasx -#define __SHASX __shasx -#define __UASX __uasx -#define __UQASX __uqasx -#define __UHASX __uhasx -#define __SSAX __ssax -#define __QSAX __qsax -#define __SHSAX __shsax -#define __USAX __usax -#define __UQSAX __uqsax -#define __UHSAX __uhsax -#define __USAD8 __usad8 -#define __USADA8 __usada8 -#define __SSAT16 __ssat16 -#define __USAT16 __usat16 -#define __UXTB16 __uxtb16 -#define __UXTAB16 __uxtab16 -#define __SXTB16 __sxtb16 -#define __SXTAB16 __sxtab16 -#define __SMUAD __smuad -#define __SMUADX __smuadx -#define __SMLAD __smlad -#define __SMLADX __smladx -#define __SMLALD __smlald -#define __SMLALDX __smlaldx -#define __SMUSD __smusd -#define __SMUSDX __smusdx -#define __SMLSD __smlsd -#define __SMLSDX __smlsdx -#define __SMLSLD __smlsld -#define __SMLSLDX __smlsldx -#define __SEL __sel -#define __QADD __qadd -#define __QSUB __qsub - -#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ - ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) - -#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ - ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) - -#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ - ((int64_t)(ARG3) << 32U) ) >> 32U)) - -#endif /* (__CORTEX_M >= 0x04) */ -/*@} end of group CMSIS_SIMD_intrinsics */ - - -#endif /* __CMSIS_ARMCC_H */ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() do {\ + __schedule_barrier();\ + __isb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() do {\ + __schedule_barrier();\ + __dsb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() do {\ + __schedule_barrier();\ + __dmb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return(result); +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/third_party/NordicSemiconductor/cmsis/cmsis_armcc_V6.h b/third_party/NordicSemiconductor/cmsis/cmsis_armcc_V6.h index d714e9b05..cd13240ce 100644 --- a/third_party/NordicSemiconductor/cmsis/cmsis_armcc_V6.h +++ b/third_party/NordicSemiconductor/cmsis/cmsis_armcc_V6.h @@ -1,1800 +1,1800 @@ -/**************************************************************************//** - * @file cmsis_armcc_V6.h - * @brief CMSIS Cortex-M Core Function/Instruction Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#ifndef __CMSIS_ARMCC_V6_H -#define __CMSIS_ARMCC_V6_H - - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ - -/** - \brief Enable IRQ Interrupts - \details Enables IRQ interrupts by clearing the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) -{ - __ASM volatile ("cpsie i" : : : "memory"); -} - - -/** - \brief Disable IRQ Interrupts - \details Disables IRQ interrupts by setting the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) -{ - __ASM volatile ("cpsid i" : : : "memory"); -} - - -/** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, control" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get Control Register (non-secure) - \details Returns the content of the non-secure Control Register when in secure mode. - \return non-secure Control Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set Control Register (non-secure) - \details Writes the given value to the non-secure Control Register when in secure state. - \param [in] control Control Register value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t control) -{ - __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); -} -#endif - - -/** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get IPSR Register (non-secure) - \details Returns the content of the non-secure IPSR Register when in secure state. - \return IPSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, ipsr_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, apsr" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get APSR Register (non-secure) - \details Returns the content of the non-secure APSR Register when in secure state. - \return APSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, apsr_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - \return xPSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get xPSR Register (non-secure) - \details Returns the content of the non-secure xPSR Register when in secure state. - \return xPSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, xpsr_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, psp" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get Process Stack Pointer (non-secure) - \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. - \return PSP Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : "sp"); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set Process Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : "sp"); -} -#endif - - -/** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, msp" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get Main Stack Pointer (non-secure) - \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. - \return MSP Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : "sp"); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set Main Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : "sp"); -} -#endif - - -/** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, primask" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get Priority Mask (non-secure) - \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. - \return Priority Mask value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set Priority Mask (non-secure) - \details Assigns the given value to the non-secure Priority Mask Register when in secure state. - \param [in] priMask Priority Mask - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) -{ - __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); -} -#endif - - -#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ - -/** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) -{ - __ASM volatile ("cpsie f" : : : "memory"); -} - - -/** - \brief Disable FIQ - \details Disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) -{ - __ASM volatile ("cpsid f" : : : "memory"); -} - - -/** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, basepri" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get Base Priority (non-secure) - \details Returns the current value of the non-secure Base Priority register when in secure state. - \return Base Priority register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) -{ - __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set Base Priority (non-secure) - \details Assigns the given value to the non-secure Base Priority register when in secure state. - \param [in] basePri Base Priority value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t value) -{ - __ASM volatile ("MSR basepri_ns, %0" : : "r" (value) : "memory"); -} -#endif - - -/** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) -{ - __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set Base Priority with condition (non_secure) - \details Assigns the given value to the non-secure Base Priority register when in secure state only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint32_t value) -{ - __ASM volatile ("MSR basepri_max_ns, %0" : : "r" (value) : "memory"); -} -#endif - - -/** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get Fault Mask (non-secure) - \details Returns the current value of the non-secure Fault Mask register when in secure state. - \return Fault Mask register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); -} - - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set Fault Mask (non-secure) - \details Assigns the given value to the non-secure Fault Mask register when in secure state. - \param [in] faultMask Fault Mask value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) -{ - __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); -} -#endif - - -#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ - - -#if (__ARM_ARCH_8M__ == 1U) - -/** - \brief Get Process Stack Pointer Limit - \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). - \return PSPLIM Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, psplim" : "=r" (result) ); - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ -/** - \brief Get Process Stack Pointer Limit (non-secure) - \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \return PSPLIM Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Process Stack Pointer Limit - \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) -{ - __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); -} - - -#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ -/** - \brief Set Process Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) -{ - __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); -} -#endif - - -/** - \brief Get Main Stack Pointer Limit - \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). - \return MSPLIM Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, msplim" : "=r" (result) ); - - return(result); -} - - -#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ -/** - \brief Get Main Stack Pointer Limit (non-secure) - \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. - \return MSPLIM Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Main Stack Pointer Limit - \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). - \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) -{ - __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); -} - - -#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ -/** - \brief Set Main Stack Pointer Limit (non-secure) - \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. - \param [in] MainStackPtrLimit Main Stack Pointer value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) -{ - __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); -} -#endif - -#endif /* (__ARM_ARCH_8M__ == 1U) */ - - -#if ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=4 */ - -/** - \brief Get FPSCR - \details eturns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value - */ -#define __get_FPSCR __builtin_arm_get_fpscr -#if 0 -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - uint32_t result; - - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); - __ASM volatile (""); - return(result); -#else - return(0); -#endif -} -#endif - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get FPSCR (non-secure) - \details Returns the current value of the non-secure Floating Point Status/Control register when in secure state. - \return Floating Point Status/Control register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - uint32_t result; - - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMRS %0, fpscr_ns" : "=r" (result) ); - __ASM volatile (""); - return(result); -#else - return(0); -#endif -} -#endif - - -/** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set - */ -#define __set_FPSCR __builtin_arm_set_fpscr -#if 0 -__attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); - __ASM volatile (""); -#endif -} -#endif - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set FPSCR (non-secure) - \details Assigns the given value to the non-secure Floating Point Status/Control register when in secure state. - \param [in] fpscr Floating Point Status/Control value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMSR fpscr_ns, %0" : : "r" (fpscr) : "vfpcc"); - __ASM volatile (""); -#endif -} -#endif - -#endif /* ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ - - - -/*@} end of CMSIS_Core_RegAccFunctions */ - - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -/* Define macros for porting to both thumb1 and thumb2. - * For thumb1, use low register (r0-r7), specified by constraint "l" - * Otherwise, use general registers, specified by constraint "r" */ -#if defined (__thumb__) && !defined (__thumb2__) -#define __CMSIS_GCC_OUT_REG(r) "=l" (r) -#define __CMSIS_GCC_USE_REG(r) "l" (r) -#else -#define __CMSIS_GCC_OUT_REG(r) "=r" (r) -#define __CMSIS_GCC_USE_REG(r) "r" (r) -#endif - -/** - \brief No Operation - \details No Operation does nothing. This instruction can be used for code alignment purposes. - */ -#define __NOP __builtin_arm_nop - -/** - \brief Wait For Interrupt - \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. - */ -#define __WFI __builtin_arm_wfi - - -/** - \brief Wait For Event - \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -#define __WFE __builtin_arm_wfe - - -/** - \brief Send Event - \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -#define __SEV __builtin_arm_sev - - -/** - \brief Instruction Synchronization Barrier - \details Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or memory, - after the instruction has been completed. - */ -#define __ISB() __builtin_arm_isb(0xF); - -/** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -#define __DSB() __builtin_arm_dsb(0xF); - - -/** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -#define __DMB() __builtin_arm_dmb(0xF); - - -/** - \brief Reverse byte order (32 bit) - \details Reverses the byte order in integer value. - \param [in] value Value to reverse - \return Reversed value - */ -#define __REV __builtin_bswap32 - - -/** - \brief Reverse byte order (16 bit) - \details Reverses the byte order in two unsigned short values. - \param [in] value Value to reverse - \return Reversed value - */ -#define __REV16 __builtin_bswap16 /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ -#if 0 -__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) -{ - uint32_t result; - - __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -} -#endif - - -/** - \brief Reverse byte order in signed short value - \details Reverses the byte order in a signed short value with sign extension to integer. - \param [in] value Value to reverse - \return Reversed value - */ - /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ -__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) -{ - int32_t result; - - __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -} - - -/** - \brief Rotate Right in unsigned value (32 bit) - \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] op1 Value to rotate - \param [in] op2 Number of Bits to rotate - \return Rotated value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) -{ - return (op1 >> op2) | (op1 << (32U - op2)); -} - - -/** - \brief Breakpoint - \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. - */ -#define __BKPT(value) __ASM volatile ("bkpt "#value) - - -/** - \brief Reverse bit order of value - \details Reverses the bit order of the given value. - \param [in] value Value to reverse - \return Reversed value - */ - /* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) -{ - uint32_t result; - -#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ - __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); -#else - int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ - - result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value; value >>= 1U) - { - result <<= 1U; - result |= value & 1U; - s--; - } - result <<= s; /* shift when v's highest bits are zero */ -#endif - return(result); -} - - -/** - \brief Count leading zeros - \details Counts the number of leading zeros of a data value. - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ -#define __CLZ __builtin_clz - - -#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ - -/** - \brief LDR Exclusive (8 bit) - \details Executes a exclusive LDR instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDREXB (uint8_t)__builtin_arm_ldrex - - -/** - \brief LDR Exclusive (16 bit) - \details Executes a exclusive LDR instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#define __LDREXH (uint16_t)__builtin_arm_ldrex - - -/** - \brief LDR Exclusive (32 bit) - \details Executes a exclusive LDR instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDREXW (uint32_t)__builtin_arm_ldrex - - -/** - \brief STR Exclusive (8 bit) - \details Executes a exclusive STR instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STREXB (uint32_t)__builtin_arm_strex - - -/** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STREXH (uint32_t)__builtin_arm_strex - - -/** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STREXW (uint32_t)__builtin_arm_strex - - -/** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. - */ -#define __CLREX __builtin_arm_clrex - - -/** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -/*#define __SSAT __builtin_arm_ssat*/ -#define __SSAT(ARG1,ARG2) \ -({ \ - int32_t __RES, __ARG1 = (ARG1); \ - __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - - -/** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -#define __USAT __builtin_arm_usat -#if 0 -#define __USAT(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) -#endif - - -/** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) -{ - uint32_t result; - - __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -} - - -/** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint8_t) result); /* Add explicit type cast here */ -} - - -/** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint16_t) result); /* Add explicit type cast here */ -} - - -/** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); -} - - -/** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) -{ - __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); -} - - -/** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) -{ - __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); -} - - -/** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *ptr) -{ - __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); -} - -#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ - - -#if (__ARM_ARCH_8M__ == 1U) - -/** - \brief Load-Acquire (8 bit) - \details Executes a LDAB instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDAB(volatile uint8_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint8_t) result); -} - - -/** - \brief Load-Acquire (16 bit) - \details Executes a LDAH instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDAH(volatile uint16_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint16_t) result); -} - - -/** - \brief Load-Acquire (32 bit) - \details Executes a LDA instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t *ptr) -{ - uint32_t result; - - __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); -} - - -/** - \brief Store-Release (8 bit) - \details Executes a STLB instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volatile uint8_t *ptr) -{ - __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); -} - - -/** - \brief Store-Release (16 bit) - \details Executes a STLH instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volatile uint16_t *ptr) -{ - __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); -} - - -/** - \brief Store-Release (32 bit) - \details Executes a STL instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volatile uint32_t *ptr) -{ - __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); -} - - -/** - \brief Load-Acquire Exclusive (8 bit) - \details Executes a LDAB exclusive instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDAEXB (uint8_t)__builtin_arm_ldaex - - -/** - \brief Load-Acquire Exclusive (16 bit) - \details Executes a LDAH exclusive instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#define __LDAEXH (uint16_t)__builtin_arm_ldaex - - -/** - \brief Load-Acquire Exclusive (32 bit) - \details Executes a LDA exclusive instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDAEX (uint32_t)__builtin_arm_ldaex - - -/** - \brief Store-Release Exclusive (8 bit) - \details Executes a STLB exclusive instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STLEXB (uint32_t)__builtin_arm_stlex - - -/** - \brief Store-Release Exclusive (16 bit) - \details Executes a STLH exclusive instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STLEXH (uint32_t)__builtin_arm_stlex - - -/** - \brief Store-Release Exclusive (32 bit) - \details Executes a STL exclusive instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STLEX (uint32_t)__builtin_arm_stlex - -#endif /* (__ARM_ARCH_8M__ == 1U) */ - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - - -/* ################### Compiler specific Intrinsics ########################### */ -/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics - Access to dedicated SIMD instructions - @{ -*/ - -#if (__ARM_FEATURE_DSP == 1U) /* ToDo: ARMCC_V6: This should be ARCH >= ARMv7-M + SIMD */ - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -#define __SSAT16(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - -#define __USAT16(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) -{ - uint32_t result; - - __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) -{ - uint32_t result; - - __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) -{ - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; - -#ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); -#else /* Big endian */ - __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); -#endif - - return(llr.w64); -} - -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) -{ - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; - -#ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); -#else /* Big endian */ - __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); -#endif - - return(llr.w64); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) -{ - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; - -#ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); -#else /* Big endian */ - __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); -#endif - - return(llr.w64); -} - -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) -{ - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; - -#ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); -#else /* Big endian */ - __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); -#endif - - return(llr.w64); -} - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) -{ - int32_t result; - - __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) -{ - int32_t result; - - __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -#define __PKHBT(ARG1,ARG2,ARG3) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ - __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ - __RES; \ - }) - -#define __PKHTB(ARG1,ARG2,ARG3) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ - if (ARG3 == 0) \ - __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ - else \ - __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ - __RES; \ - }) - -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) -{ - int32_t result; - - __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -#endif /* (__ARM_FEATURE_DSP == 1U) */ -/*@} end of group CMSIS_SIMD_intrinsics */ - - -#endif /* __CMSIS_ARMCC_V6_H */ +/**************************************************************************//** + * @file cmsis_armcc_V6.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CMSIS_ARMCC_V6_H +#define __CMSIS_ARMCC_V6_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get IPSR Register (non-secure) + \details Returns the content of the non-secure IPSR Register when in secure state. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get APSR Register (non-secure) + \details Returns the content of the non-secure APSR Register when in secure state. + \return APSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get xPSR Register (non-secure) + \details Returns the content of the non-secure xPSR Register when in secure state. + \return xPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : "sp"); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : "sp"); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t value) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (value) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority with condition (non_secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint32_t value) +{ + __ASM volatile ("MSR basepri_max_ns, %0" : : "r" (value) : "memory"); +} +#endif + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \brief Get Process Stack Pointer Limit + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Process Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Main Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Main Stack Pointer Limit (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +} +#endif + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + + +#if ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=4 */ + +/** + \brief Get FPSCR + \details eturns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#define __get_FPSCR __builtin_arm_get_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get FPSCR (non-secure) + \details Returns the current value of the non-secure Floating Point Status/Control register when in secure state. + \return Floating Point Status/Control register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMRS %0, fpscr_ns" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} +#endif + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#define __set_FPSCR __builtin_arm_set_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set FPSCR (non-secure) + \details Assigns the given value to the non-secure Floating Point Status/Control register when in secure state. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMSR fpscr_ns, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} +#endif + +#endif /* ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF); + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF); + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF); + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __builtin_bswap32 + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16 __builtin_bswap16 /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +#if 0 +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} +#endif + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ + /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + int32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ + /* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return(result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +/*#define __SSAT __builtin_arm_ssat*/ +#define __SSAT(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat +#if 0 +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) +#endif + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__ARM_FEATURE_DSP == 1U) /* ToDo: ARMCC_V6: This should be ARCH >= ARMv7-M + SIMD */ + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1U) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_V6_H */ diff --git a/third_party/NordicSemiconductor/cmsis/cmsis_gcc.h b/third_party/NordicSemiconductor/cmsis/cmsis_gcc.h index d868f2e64..bb89fbba9 100644 --- a/third_party/NordicSemiconductor/cmsis/cmsis_gcc.h +++ b/third_party/NordicSemiconductor/cmsis/cmsis_gcc.h @@ -1,1373 +1,1373 @@ -/**************************************************************************//** - * @file cmsis_gcc.h - * @brief CMSIS Cortex-M Core Function/Instruction Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#ifndef __CMSIS_GCC_H -#define __CMSIS_GCC_H - -/* ignore some GCC warnings */ -#if defined ( __GNUC__ ) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ - -/** - \brief Enable IRQ Interrupts - \details Enables IRQ interrupts by clearing the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) -{ - __ASM volatile ("cpsie i" : : : "memory"); -} - - -/** - \brief Disable IRQ Interrupts - \details Disables IRQ interrupts by setting the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) -{ - __ASM volatile ("cpsid i" : : : "memory"); -} - - -/** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, control" : "=r" (result) ); - return(result); -} - - -/** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); -} - - -/** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); - return(result); -} - - -/** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, apsr" : "=r" (result) ); - return(result); -} - - -/** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - - \return xPSR Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); - return(result); -} - - -/** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); - return(result); -} - - -/** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); -} - - -/** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); - return(result); -} - - -/** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); -} - - -/** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, primask" : "=r" (result) ); - return(result); -} - - -/** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); -} - - -#if (__CORTEX_M >= 0x03U) - -/** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) -{ - __ASM volatile ("cpsie f" : : : "memory"); -} - - -/** - \brief Disable FIQ - \details Disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) -{ - __ASM volatile ("cpsid f" : : : "memory"); -} - - -/** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, basepri" : "=r" (result) ); - return(result); -} - - -/** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) -{ - __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); -} - - -/** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) -{ - __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); -} - - -/** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); - return(result); -} - - -/** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); -} - -#endif /* (__CORTEX_M >= 0x03U) */ - - -#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) - -/** - \brief Get FPSCR - \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - uint32_t result; - - /* Empty asm statement works as a scheduling barrier */ - __ASM volatile (""); - __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); - __ASM volatile (""); - return(result); -#else - return(0); -#endif -} - - -/** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - /* Empty asm statement works as a scheduling barrier */ - __ASM volatile (""); - __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); - __ASM volatile (""); -#endif -} - -#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ - - - -/*@} end of CMSIS_Core_RegAccFunctions */ - - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -/* Define macros for porting to both thumb1 and thumb2. - * For thumb1, use low register (r0-r7), specified by constraint "l" - * Otherwise, use general registers, specified by constraint "r" */ -#if defined (__thumb__) && !defined (__thumb2__) -#define __CMSIS_GCC_OUT_REG(r) "=l" (r) -#define __CMSIS_GCC_USE_REG(r) "l" (r) -#else -#define __CMSIS_GCC_OUT_REG(r) "=r" (r) -#define __CMSIS_GCC_USE_REG(r) "r" (r) -#endif - -/** - \brief No Operation - \details No Operation does nothing. This instruction can be used for code alignment purposes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) -{ - __ASM volatile ("nop"); -} - - -/** - \brief Wait For Interrupt - \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. - */ -__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) -{ - __ASM volatile ("wfi"); -} - - -/** - \brief Wait For Event - \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -__attribute__((always_inline)) __STATIC_INLINE void __WFE(void) -{ - __ASM volatile ("wfe"); -} - - -/** - \brief Send Event - \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -__attribute__((always_inline)) __STATIC_INLINE void __SEV(void) -{ - __ASM volatile ("sev"); -} - - -/** - \brief Instruction Synchronization Barrier - \details Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or memory, - after the instruction has been completed. - */ -__attribute__((always_inline)) __STATIC_INLINE void __ISB(void) -{ - __ASM volatile ("isb 0xF":::"memory"); -} - - -/** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -__attribute__((always_inline)) __STATIC_INLINE void __DSB(void) -{ - __ASM volatile ("dsb 0xF":::"memory"); -} - - -/** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -__attribute__((always_inline)) __STATIC_INLINE void __DMB(void) -{ - __ASM volatile ("dmb 0xF":::"memory"); -} - - -/** - \brief Reverse byte order (32 bit) - \details Reverses the byte order in integer value. - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) -{ -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) - return __builtin_bswap32(value); -#else - uint32_t result; - - __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -#endif -} - - -/** - \brief Reverse byte order (16 bit) - \details Reverses the byte order in two unsigned short values. - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) -{ - uint32_t result; - - __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -} - - -/** - \brief Reverse byte order in signed short value - \details Reverses the byte order in a signed short value with sign extension to integer. - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) -{ -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - return (short)__builtin_bswap16(value); -#else - int32_t result; - - __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -#endif -} - - -/** - \brief Rotate Right in unsigned value (32 bit) - \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] value Value to rotate - \param [in] value Number of Bits to rotate - \return Rotated value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) -{ - return (op1 >> op2) | (op1 << (32U - op2)); -} - - -/** - \brief Breakpoint - \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. - */ -#define __BKPT(value) __ASM volatile ("bkpt "#value) - - -/** - \brief Reverse bit order of value - \details Reverses the bit order of the given value. - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) -{ - uint32_t result; - -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) - __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); -#else - int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ - - result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value; value >>= 1U) - { - result <<= 1U; - result |= value & 1U; - s--; - } - result <<= s; /* shift when v's highest bits are zero */ -#endif - return(result); -} - - -/** - \brief Count leading zeros - \details Counts the number of leading zeros of a data value. - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ -#define __CLZ __builtin_clz - - -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) - -/** - \brief LDR Exclusive (8 bit) - \details Executes a exclusive LDR instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) -{ - uint32_t result; - -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); -#else - /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not - accepted by assembler. So has to use following less efficient pattern. - */ - __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); -#endif - return ((uint8_t) result); /* Add explicit type cast here */ -} - - -/** - \brief LDR Exclusive (16 bit) - \details Executes a exclusive LDR instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) -{ - uint32_t result; - -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); -#else - /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not - accepted by assembler. So has to use following less efficient pattern. - */ - __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); -#endif - return ((uint16_t) result); /* Add explicit type cast here */ -} - - -/** - \brief LDR Exclusive (32 bit) - \details Executes a exclusive LDR instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) -{ - uint32_t result; - - __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); - return(result); -} - - -/** - \brief STR Exclusive (8 bit) - \details Executes a exclusive STR instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) -{ - uint32_t result; - - __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); - return(result); -} - - -/** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) -{ - uint32_t result; - - __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); - return(result); -} - - -/** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) -{ - uint32_t result; - - __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); - return(result); -} - - -/** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. - */ -__attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) -{ - __ASM volatile ("clrex" ::: "memory"); -} - - -/** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -#define __SSAT(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - - -/** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -#define __USAT(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - - -/** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) -{ - uint32_t result; - - __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -} - - -/** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) -{ - uint32_t result; - -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) ); -#else - /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not - accepted by assembler. So has to use following less efficient pattern. - */ - __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); -#endif - return ((uint8_t) result); /* Add explicit type cast here */ -} - - -/** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) -{ - uint32_t result; - -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) ); -#else - /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not - accepted by assembler. So has to use following less efficient pattern. - */ - __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); -#endif - return ((uint16_t) result); /* Add explicit type cast here */ -} - - -/** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) -{ - uint32_t result; - - __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) ); - return(result); -} - - -/** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) -{ - __ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); -} - - -/** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) -{ - __ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); -} - - -/** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) -{ - __ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) ); -} - -#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - - -/* ################### Compiler specific Intrinsics ########################### */ -/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics - Access to dedicated SIMD instructions - @{ -*/ - -#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -#define __SSAT16(ARG1,ARG2) \ -({ \ - int32_t __RES, __ARG1 = (ARG1); \ - __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - -#define __USAT16(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) -{ - uint32_t result; - - __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) -{ - uint32_t result; - - __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) -{ - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; - -#ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); -#else /* Big endian */ - __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); -#endif - - return(llr.w64); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) -{ - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; - -#ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); -#else /* Big endian */ - __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); -#endif - - return(llr.w64); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) -{ - uint32_t result; - - __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) -{ - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; - -#ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); -#else /* Big endian */ - __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); -#endif - - return(llr.w64); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) -{ - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; - -#ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); -#else /* Big endian */ - __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); -#endif - - return(llr.w64); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) -{ - uint32_t result; - - __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) -{ - int32_t result; - - __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) -{ - int32_t result; - - __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); -} - -#define __PKHBT(ARG1,ARG2,ARG3) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ - __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ - __RES; \ - }) - -#define __PKHTB(ARG1,ARG2,ARG3) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ - if (ARG3 == 0) \ - __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ - else \ - __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ - __RES; \ - }) - -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) -{ - int32_t result; - - __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -#endif /* (__CORTEX_M >= 0x04) */ -/*@} end of group CMSIS_SIMD_intrinsics */ - - -#if defined ( __GNUC__ ) -#pragma GCC diagnostic pop -#endif - -#endif /* __CMSIS_GCC_H */ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__((always_inline)) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__attribute__((always_inline)) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + int32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return(result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) ); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* __CMSIS_GCC_H */ diff --git a/third_party/NordicSemiconductor/cmsis/core_cm4.h b/third_party/NordicSemiconductor/cmsis/core_cm4.h index 7002e4e52..d02b11136 100644 --- a/third_party/NordicSemiconductor/cmsis/core_cm4.h +++ b/third_party/NordicSemiconductor/cmsis/core_cm4.h @@ -1,1937 +1,1937 @@ -/**************************************************************************//** - * @file core_cm4.h - * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#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 __CORE_CM4_H_GENERIC -#define __CORE_CM4_H_GENERIC - -#include - -#ifdef __cplusplus - extern "C" { -#endif - -/** - \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions - CMSIS violates the following MISRA-C:2004 rules: - - \li Required Rule 8.5, object/function definition in header file.
- Function definitions in header files are used to allow 'inlining'. - - \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
- Unions are used for effective representation of core registers. - - \li Advisory Rule 19.7, Function-like macro defined.
- Function-like macros are used to allow more efficient code. - */ - - -/******************************************************************************* - * CMSIS definitions - ******************************************************************************/ -/** - \ingroup Cortex_M4 - @{ - */ - -/* CMSIS CM4 definitions */ -#define __CM4_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ -#define __CM4_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ -#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ - __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x04U) /*!< Cortex-M Core */ - - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __CSMC__ ) - #define __packed - #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ - #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ - #define __STATIC_INLINE static inline - -#else - #error Unknown compiler -#endif - -/** __FPU_USED indicates whether an FPU is used or not. - For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. -*/ -#if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #if (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #if (__FPU_PRESENT == 1) - #define __FPU_USED 1U - #else - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #if (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #if (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __TMS470__ ) - #if defined __TI_VFP_SUPPORT__ - #if (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #if (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #if (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#endif - -#include "core_cmInstr.h" /* Core Instruction Access */ -#include "core_cmFunc.h" /* Core Function Access */ -#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ - -#ifdef __cplusplus -} -#endif - -#endif /* __CORE_CM4_H_GENERIC */ - -#ifndef __CMSIS_GENERIC - -#ifndef __CORE_CM4_H_DEPENDANT -#define __CORE_CM4_H_DEPENDANT - -#ifdef __cplusplus - extern "C" { -#endif - -/* check device defines and use defaults */ -#if defined __CHECK_DEVICE_DEFINES - #ifndef __CM4_REV - #define __CM4_REV 0x0000U - #warning "__CM4_REV not defined in device header file; using default!" - #endif - - #ifndef __FPU_PRESENT - #define __FPU_PRESENT 0U - #warning "__FPU_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0U - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 4U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif - - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif -#endif - -/* IO definitions (access restrictions to peripheral registers) */ -/** - \defgroup CMSIS_glob_defs CMSIS Global Defines - - IO Type Qualifiers are used - \li to specify the access to peripheral variables. - \li for automatic generation of peripheral register debug information. -*/ -#ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ -#else - #define __I volatile const /*!< Defines 'read only' permissions */ -#endif -#define __O volatile /*!< Defines 'write only' permissions */ -#define __IO volatile /*!< Defines 'read / write' permissions */ - -/* following defines should be used for structure members */ -#define __IM volatile const /*! Defines 'read only' structure member permissions */ -#define __OM volatile /*! Defines 'write only' structure member permissions */ -#define __IOM volatile /*! Defines 'read / write' structure member permissions */ - -/*@} end of group Cortex_M4 */ - - - -/******************************************************************************* - * Register Abstraction - Core Register contain: - - Core Register - - Core NVIC Register - - Core SCB Register - - Core SysTick Register - - Core Debug Register - - Core MPU Register - - Core FPU Register - ******************************************************************************/ -/** - \defgroup CMSIS_core_register Defines and Type Definitions - \brief Type definitions and defines for Cortex-M processor based devices. -*/ - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_CORE Status and Control Registers - \brief Core Register type definitions. - @{ - */ - -/** - \brief Union type to access the Application Program Status Register (APSR). - */ -typedef union -{ - struct - { - uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} APSR_Type; - -/* APSR Register Definitions */ -#define APSR_N_Pos 31U /*!< APSR: N Position */ -#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ - -#define APSR_Z_Pos 30U /*!< APSR: Z Position */ -#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ - -#define APSR_C_Pos 29U /*!< APSR: C Position */ -#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ - -#define APSR_V_Pos 28U /*!< APSR: V Position */ -#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ - -#define APSR_Q_Pos 27U /*!< APSR: Q Position */ -#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ - -#define APSR_GE_Pos 16U /*!< APSR: GE Position */ -#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ - - -/** - \brief Union type to access the Interrupt Program Status Register (IPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} IPSR_Type; - -/* IPSR Register Definitions */ -#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ -#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ - - -/** - \brief Union type to access the Special-Purpose Program Status Registers (xPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} xPSR_Type; - -/* xPSR Register Definitions */ -#define xPSR_N_Pos 31U /*!< xPSR: N Position */ -#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ - -#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ -#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ - -#define xPSR_C_Pos 29U /*!< xPSR: C Position */ -#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ - -#define xPSR_V_Pos 28U /*!< xPSR: V Position */ -#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ - -#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ -#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ - -#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ -#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ - -#define xPSR_T_Pos 24U /*!< xPSR: T Position */ -#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ - -#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ -#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ - -#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ -#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ - - -/** - \brief Union type to access the Control Registers (CONTROL). - */ -typedef union -{ - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ - uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ - uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} CONTROL_Type; - -/* CONTROL Register Definitions */ -#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ -#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ - -#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ -#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ - -#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ -#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ - -/*@} end of group CMSIS_CORE */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) - \brief Type definitions for the NVIC Registers - @{ - */ - -/** - \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). - */ -typedef struct -{ - __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[24U]; - __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24U]; - __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[24U]; - __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[24U]; - __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[56U]; - __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED5[644U]; - __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ -} NVIC_Type; - -/* Software Triggered Interrupt Register Definitions */ -#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ -#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ - -/*@} end of group CMSIS_NVIC */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_SCB System Control Block (SCB) - \brief Type definitions for the System Control Block Registers - @{ - */ - -/** - \brief Structure type to access the System Control Block (SCB). - */ -typedef struct -{ - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - uint32_t RESERVED0[5U]; - __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ -} SCB_Type; - -/* SCB CPUID Register Definitions */ -#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ -#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ - -#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ -#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ - -#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ -#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ - -#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ -#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ - -#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ -#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ - -/* SCB Interrupt Control State Register Definitions */ -#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ -#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ - -#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ -#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ - -#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ -#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ - -#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ -#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ - -#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ -#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ - -#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ -#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ - -#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ -#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ - -#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ -#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ - -#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ -#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ - -#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ -#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ - -/* SCB Vector Table Offset Register Definitions */ -#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ - -/* SCB Application Interrupt and Reset Control Register Definitions */ -#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ -#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ - -#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ -#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ - -#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ -#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ - -#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ -#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ - -#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ -#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ - -#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ -#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ - -#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ -#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ - -/* SCB System Control Register Definitions */ -#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ -#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ - -#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ -#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ - -#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ -#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ - -/* SCB Configuration Control Register Definitions */ -#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ -#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ - -#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ -#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ - -#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ -#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ - -#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ -#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ - -#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ -#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ - -#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ -#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ - -/* SCB System Handler Control and State Register Definitions */ -#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ -#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ - -#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ -#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ - -#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ -#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ - -#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ -#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ - -#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ -#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ - -#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ -#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ - -#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ -#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ - -#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ -#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ - -#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ -#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ - -#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ -#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ - -#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ -#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ - -#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ -#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ - -#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ -#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ - -#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ -#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ - -/* SCB Configurable Fault Status Register Definitions */ -#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ -#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ - -#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ -#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ - -#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ -#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ - -/* SCB Hard Fault Status Register Definitions */ -#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ -#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ - -#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ -#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ - -#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ -#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ - -/* SCB Debug Fault Status Register Definitions */ -#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ -#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ - -#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ -#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ - -#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ -#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ - -#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ -#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ - -#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ -#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ - -/*@} end of group CMSIS_SCB */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) - \brief Type definitions for the System Control and ID Register not in the SCB - @{ - */ - -/** - \brief Structure type to access the System Control and ID Register not in the SCB. - */ -typedef struct -{ - uint32_t RESERVED0[1U]; - __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ - __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ -} SCnSCB_Type; - -/* Interrupt Controller Type Register Definitions */ -#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ -#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ - -/* Auxiliary Control Register Definitions */ -#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ -#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ - -#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ -#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ - -#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ -#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ - -#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ -#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ - -#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ -#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ - -/*@} end of group CMSIS_SCnotSCB */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_SysTick System Tick Timer (SysTick) - \brief Type definitions for the System Timer Registers. - @{ - */ - -/** - \brief Structure type to access the System Timer (SysTick). - */ -typedef struct -{ - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ -} SysTick_Type; - -/* SysTick Control / Status Register Definitions */ -#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ -#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ - -#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ -#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ - -#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ -#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ - -#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ -#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ - -/* SysTick Reload Register Definitions */ -#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ -#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ - -/* SysTick Current Register Definitions */ -#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ -#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ - -/* SysTick Calibration Register Definitions */ -#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ -#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ - -#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ -#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ - -#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ -#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ - -/*@} end of group CMSIS_SysTick */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) - \brief Type definitions for the Instrumentation Trace Macrocell (ITM) - @{ - */ - -/** - \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). - */ -typedef struct -{ - __OM union - { - __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864U]; - __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15U]; - __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15U]; - __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29U]; - __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ - uint32_t RESERVED4[43U]; - __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[6U]; - __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ -} ITM_Type; - -/* ITM Trace Privilege Register Definitions */ -#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ - -/* ITM Trace Control Register Definitions */ -#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ -#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ - -#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ -#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ - -#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ -#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ - -#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ -#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ - -#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ -#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ - -#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ -#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ - -#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ -#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ - -#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ -#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ - -#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ -#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ - -/* ITM Integration Write Register Definitions */ -#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ -#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ - -/* ITM Integration Read Register Definitions */ -#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ -#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ - -/* ITM Integration Mode Control Register Definitions */ -#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ -#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ - -/* ITM Lock Status Register Definitions */ -#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ -#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ - -#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ -#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ - -#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ -#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ - -/*@}*/ /* end of group CMSIS_ITM */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) - \brief Type definitions for the Data Watchpoint and Trace (DWT) - @{ - */ - -/** - \brief Structure type to access the Data Watchpoint and Trace Register (DWT). - */ -typedef struct -{ - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ - __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED0[1U]; - __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ - __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED1[1U]; - __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ - __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED2[1U]; - __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ - __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ -} DWT_Type; - -/* DWT Control Register Definitions */ -#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ -#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ - -#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ -#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ - -#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ -#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ - -#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ -#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ - -#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ -#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ - -#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ -#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ - -#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ -#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ - -#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ -#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ - -#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ -#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ - -#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ -#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ - -#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ -#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ - -#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ -#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ - -#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ -#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ - -#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ -#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ - -#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ -#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ - -#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ -#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ - -#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ -#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ - -#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ -#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ - -/* DWT CPI Count Register Definitions */ -#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ -#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ - -/* DWT Exception Overhead Count Register Definitions */ -#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ -#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ - -/* DWT Sleep Count Register Definitions */ -#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ -#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ - -/* DWT LSU Count Register Definitions */ -#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ -#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ - -/* DWT Folded-instruction Count Register Definitions */ -#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ -#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ - -/* DWT Comparator Mask Register Definitions */ -#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ -#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ - -/* DWT Comparator Function Register Definitions */ -#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ -#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ - -#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ -#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ - -#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ -#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ - -#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ -#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ - -#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ -#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ - -#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ -#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ - -#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ -#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ - -#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ -#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ - -#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ -#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ - -/*@}*/ /* end of group CMSIS_DWT */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_TPI Trace Port Interface (TPI) - \brief Type definitions for the Trace Port Interface (TPI) - @{ - */ - -/** - \brief Structure type to access the Trace Port Interface Register (TPI). - */ -typedef struct -{ - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2U]; - __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55U]; - __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131U]; - __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ - __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1U]; - __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39U]; - __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8U]; - __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ -} TPI_Type; - -/* TPI Asynchronous Clock Prescaler Register Definitions */ -#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ -#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ - -/* TPI Selected Pin Protocol Register Definitions */ -#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ -#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ - -/* TPI Formatter and Flush Status Register Definitions */ -#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ -#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ - -#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ -#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ - -#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ -#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ - -#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ -#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ - -/* TPI Formatter and Flush Control Register Definitions */ -#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ -#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ - -#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ -#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ - -/* TPI TRIGGER Register Definitions */ -#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ -#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ - -/* TPI Integration ETM Data Register Definitions (FIFO0) */ -#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ -#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ - -#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ -#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ - -#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ -#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ - -#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ -#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ - -#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ -#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ - -#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ -#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ - -#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ -#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ - -/* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ -#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ - -/* TPI Integration ITM Data Register Definitions (FIFO1) */ -#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ -#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ - -#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ -#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ - -#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ -#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ - -#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ -#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ - -#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ -#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ - -#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ -#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ - -#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ -#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ - -/* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ -#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ - -/* TPI Integration Mode Control Register Definitions */ -#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ - -/* TPI DEVID Register Definitions */ -#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ -#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ - -#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ -#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ - -#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ -#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ - -#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ -#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ - -#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ -#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ - -#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ -#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ - -/* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ -#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ - -/*@}*/ /* end of group CMSIS_TPI */ - - -#if (__MPU_PRESENT == 1U) -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_MPU Memory Protection Unit (MPU) - \brief Type definitions for the Memory Protection Unit (MPU) - @{ - */ - -/** - \brief Structure type to access the Memory Protection Unit (MPU). - */ -typedef struct -{ - __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ - __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ - __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ - __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ - __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ -} MPU_Type; - -/* MPU Type Register Definitions */ -#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ -#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ - -#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ -#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ - -#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ -#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ - -/* MPU Control Register Definitions */ -#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ -#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ - -#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ -#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ - -#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ -#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ - -/* MPU Region Number Register Definitions */ -#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ -#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ - -/* MPU Region Base Address Register Definitions */ -#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ -#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ - -#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ -#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ - -#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ -#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ - -/* MPU Region Attribute and Size Register Definitions */ -#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ -#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ - -#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ -#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ - -#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ -#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ - -#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ -#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ - -#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ -#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ - -#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ -#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ - -#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ -#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ - -#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ -#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ - -#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ -#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ - -#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ -#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ - -/*@} end of group CMSIS_MPU */ -#endif - - -#if (__FPU_PRESENT == 1U) -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_FPU Floating Point Unit (FPU) - \brief Type definitions for the Floating Point Unit (FPU) - @{ - */ - -/** - \brief Structure type to access the Floating Point Unit (FPU). - */ -typedef struct -{ - uint32_t RESERVED0[1U]; - __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ - __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ - __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ - __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ - __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ -} FPU_Type; - -/* Floating-Point Context Control Register Definitions */ -#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ -#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ - -#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ -#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ - -#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ -#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ - -#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ -#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ - -#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ -#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ - -#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ -#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ - -#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ -#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ - -#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ -#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ - -#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ -#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ - -/* Floating-Point Context Address Register Definitions */ -#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ -#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ - -/* Floating-Point Default Status Control Register Definitions */ -#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ -#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ - -#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ -#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ - -#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ -#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ - -#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ -#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ - -/* Media and FP Feature Register 0 Definitions */ -#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ -#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ - -#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ -#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ - -#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ -#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ - -#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ -#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ - -#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ -#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ - -#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ -#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ - -#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ -#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ - -#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ -#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ - -/* Media and FP Feature Register 1 Definitions */ -#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ -#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ - -#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ -#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ - -#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ -#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ - -#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ -#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ - -/*@} end of group CMSIS_FPU */ -#endif - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) - \brief Type definitions for the Core Debug Registers - @{ - */ - -/** - \brief Structure type to access the Core Debug Register (CoreDebug). - */ -typedef struct -{ - __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ -} CoreDebug_Type; - -/* Debug Halting Control and Status Register Definitions */ -#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ -#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ - -#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ -#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ - -#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ -#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ - -#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ -#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ - -#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ -#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ - -#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ -#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ - -#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ -#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ - -#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ -#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ - -#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ -#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ - -#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ -#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ - -#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ -#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ - -#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ -#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ - -/* Debug Core Register Selector Register Definitions */ -#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ -#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ - -#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ -#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ - -/* Debug Exception and Monitor Control Register Definitions */ -#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ -#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ - -#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ -#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ - -#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ -#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ - -#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ -#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ - -#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ -#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ - -#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ -#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ - -#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ -#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ - -#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ -#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ - -#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ -#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ - -#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ -#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ - -#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ -#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ - -#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ -#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ - -#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ -#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ - -/*@} end of group CMSIS_CoreDebug */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_core_bitfield Core register bit field macros - \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). - @{ - */ - -/** - \brief Mask and shift a bit field value for use in a register bit range. - \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. - \return Masked and shifted value. -*/ -#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) - -/** - \brief Mask and shift a register value to extract a bit filed value. - \param[in] field Name of the register bit field. - \param[in] value Value of register. - \return Masked and shifted bit field value. -*/ -#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) - -/*@} end of group CMSIS_core_bitfield */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_core_base Core Definitions - \brief Definitions for base addresses, unions, and structures. - @{ - */ - -/* Memory mapping of Cortex-M4 Hardware */ -#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ -#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ -#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ -#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ -#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ -#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ -#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ -#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ - -#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ -#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ -#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ -#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ -#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ -#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ -#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ -#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ - -#if (__MPU_PRESENT == 1U) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ -#endif - -#if (__FPU_PRESENT == 1U) - #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ - #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ -#endif - -/*@} */ - - - -/******************************************************************************* - * Hardware Abstraction Layer - Core Function Interface contains: - - Core NVIC Functions - - Core SysTick Functions - - Core Debug Functions - - Core Register Access Functions - ******************************************************************************/ -/** - \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference -*/ - - - -/* ########################## NVIC functions #################################### */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_NVICFunctions NVIC Functions - \brief Functions that manage interrupts and exceptions via the NVIC. - @{ - */ - -/** - \brief Set Priority Grouping - \details Sets the priority grouping field using the required unlock sequence. - The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. - Only values from 0..7 are used. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. - \param [in] PriorityGroup Priority grouping field. - */ -__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) -{ - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ - SCB->AIRCR = reg_value; -} - - -/** - \brief Get Priority Grouping - \details Reads the priority grouping field from the NVIC Interrupt Controller. - \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). - */ -__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) -{ - return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); -} - - -/** - \brief Enable External Interrupt - \details Enables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) -{ - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); -} - - -/** - \brief Disable External Interrupt - \details Disables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) -{ - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); -} - - -/** - \brief Get Pending Interrupt - \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. - \param [in] IRQn Interrupt number. - \return 0 Interrupt status is not pending. - \return 1 Interrupt status is pending. - */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) -{ - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); -} - - -/** - \brief Set Pending Interrupt - \details Sets the pending bit of an external interrupt. - \param [in] IRQn Interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); -} - - -/** - \brief Clear Pending Interrupt - \details Clears the pending bit of an external interrupt. - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); -} - - -/** - \brief Get Active Interrupt - \details Reads the active register in NVIC and returns the active bit. - \param [in] IRQn Interrupt number. - \return 0 Interrupt status is not active. - \return 1 Interrupt status is active. - */ -__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) -{ - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); -} - - -/** - \brief Set Interrupt Priority - \details Sets the priority of an interrupt. - \note The priority cannot be set for every core interrupt. - \param [in] IRQn Interrupt number. - \param [in] priority Priority to set. - */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) -{ - if ((int32_t)(IRQn) < 0) - { - SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } - else - { - NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } -} - - -/** - \brief Get Interrupt Priority - \details Reads the priority of an interrupt. - The interrupt number can be positive to specify an external (device specific) interrupt, - or negative to specify an internal (core) interrupt. - \param [in] IRQn Interrupt number. - \return Interrupt Priority. - Value is aligned automatically to the implemented priority bits of the microcontroller. - */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) -{ - - if ((int32_t)(IRQn) < 0) - { - return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); - } -} - - -/** - \brief Encode Priority - \details Encodes the priority for an interrupt with the given priority group, - preemptive priority value, and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. - \param [in] PriorityGroup Used priority group. - \param [in] PreemptPriority Preemptive priority value (starting from 0). - \param [in] SubPriority Subpriority value (starting from 0). - \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). - */ -__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - - return ( - ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | - ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) - ); -} - - -/** - \brief Decode Priority - \details Decodes an interrupt priority value with a given priority group to - preemptive priority value and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. - \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). - \param [in] PriorityGroup Used priority group. - \param [out] pPreemptPriority Preemptive priority value (starting from 0). - \param [out] pSubPriority Subpriority value (starting from 0). - */ -__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - - *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); - *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); -} - - -/** - \brief System Reset - \details Initiates a system reset request to reset the MCU. - */ -__STATIC_INLINE void NVIC_SystemReset(void) -{ - __DSB(); /* Ensure all outstanding memory accesses included - buffered write are completed before reset */ - SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ - - for (;;) /* wait until reset */ - { - __NOP(); - } -} - -/*@} end of CMSIS_Core_NVICFunctions */ - - - -/* ################################## SysTick function ############################################ */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_SysTickFunctions SysTick Functions - \brief Functions that configure the System. - @{ - */ - -#if (__Vendor_SysTickConfig == 0U) - -/** - \brief System Tick Configuration - \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. - Counter is in free running mode to generate periodic interrupts. - \param [in] ticks Number of ticks between two interrupts. - \return 0 Function succeeded. - \return 1 Function failed. - \note When the variable __Vendor_SysTickConfig is set to 1, then the - function SysTick_Config is not included. In this case, the file device.h - must contain a vendor-specific implementation of this function. - */ -__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) -{ - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } - - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ -} - -#endif - -/*@} end of CMSIS_Core_SysTickFunctions */ - - - -/* ##################################### Debug In/Output function ########################################### */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_core_DebugFunctions ITM Functions - \brief Functions that access the ITM debug interface. - @{ - */ - -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ - - -/** - \brief ITM Send Character - \details Transmits a character via the ITM channel 0, and - \li Just returns when no debugger is connected that has booked the output. - \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. - \param [in] ch Character to transmit. - \returns Character to transmit. - */ -__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) -{ - if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ - ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0U].u32 == 0UL) - { - __NOP(); - } - ITM->PORT[0U].u8 = (uint8_t)ch; - } - return (ch); -} - - -/** - \brief ITM Receive Character - \details Inputs a character via the external variable \ref ITM_RxBuffer. - \return Received character. - \return -1 No character pending. - */ -__STATIC_INLINE int32_t ITM_ReceiveChar (void) -{ - int32_t ch = -1; /* no character available */ - - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) - { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } - - return (ch); -} - - -/** - \brief ITM Check Character - \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. - \return 0 No character available. - \return 1 Character available. - */ -__STATIC_INLINE int32_t ITM_CheckChar (void) -{ - - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) - { - return (0); /* no character available */ - } - else - { - return (1); /* character available */ - } -} - -/*@} end of CMSIS_core_DebugFunctions */ - - - - -#ifdef __cplusplus -} -#endif - -#endif /* __CORE_CM4_H_DEPENDANT */ - -#endif /* __CMSIS_GENERIC */ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#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 __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M4 + @{ + */ + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x04U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ +#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000U + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1U) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for (;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/third_party/NordicSemiconductor/cmsis/core_cmFunc.h b/third_party/NordicSemiconductor/cmsis/core_cmFunc.h index cb1ebf89a..979696f50 100644 --- a/third_party/NordicSemiconductor/cmsis/core_cmFunc.h +++ b/third_party/NordicSemiconductor/cmsis/core_cmFunc.h @@ -1,86 +1,86 @@ -/**************************************************************************//** - * @file core_cmFunc.h - * @brief CMSIS Cortex-M Core Function Access Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - -#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 __CORE_CMFUNC_H -#define __CORE_CMFUNC_H - - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ -*/ - -/*------------------ RealView Compiler -----------------*/ -#if defined ( __CC_ARM ) - #include "cmsis_armcc.h" - -/*------------------ ARM Compiler V6 -------------------*/ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #include "cmsis_armcc_V6.h" - -/*------------------ GNU Compiler ----------------------*/ -#elif defined ( __GNUC__ ) - #include "cmsis_gcc.h" - -/*------------------ ICC Compiler ----------------------*/ -#elif defined ( __ICCARM__ ) - #include - -/*------------------ TI CCS Compiler -------------------*/ -#elif defined ( __TMS470__ ) - #include - -/*------------------ TASKING Compiler ------------------*/ -#elif defined ( __TASKING__ ) - /* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ - -/*------------------ COSMIC Compiler -------------------*/ -#elif defined ( __CSMC__ ) - #include - -#endif - -/*@} end of CMSIS_Core_RegAccFunctions */ - -#endif /* __CORE_CMFUNC_H */ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + +#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 __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + +#endif /* __CORE_CMFUNC_H */ diff --git a/third_party/NordicSemiconductor/cmsis/core_cmInstr.h b/third_party/NordicSemiconductor/cmsis/core_cmInstr.h index a0a506458..f474b0e6f 100644 --- a/third_party/NordicSemiconductor/cmsis/core_cmInstr.h +++ b/third_party/NordicSemiconductor/cmsis/core_cmInstr.h @@ -1,87 +1,87 @@ -/**************************************************************************//** - * @file core_cmInstr.h - * @brief CMSIS Cortex-M Core Instruction Access Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#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 __CORE_CMINSTR_H -#define __CORE_CMINSTR_H - - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -/*------------------ RealView Compiler -----------------*/ -#if defined ( __CC_ARM ) - #include "cmsis_armcc.h" - -/*------------------ ARM Compiler V6 -------------------*/ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #include "cmsis_armcc_V6.h" - -/*------------------ GNU Compiler ----------------------*/ -#elif defined ( __GNUC__ ) - #include "cmsis_gcc.h" - -/*------------------ ICC Compiler ----------------------*/ -#elif defined ( __ICCARM__ ) - #include - -/*------------------ TI CCS Compiler -------------------*/ -#elif defined ( __TMS470__ ) - #include - -/*------------------ TASKING Compiler ------------------*/ -#elif defined ( __TASKING__ ) - /* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ - -/*------------------ COSMIC Compiler -------------------*/ -#elif defined ( __CSMC__ ) - #include - -#endif - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - -#endif /* __CORE_CMINSTR_H */ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#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 __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/third_party/NordicSemiconductor/cmsis/core_cmSimd.h b/third_party/NordicSemiconductor/cmsis/core_cmSimd.h index 4d76bf901..66bf5c2a7 100644 --- a/third_party/NordicSemiconductor/cmsis/core_cmSimd.h +++ b/third_party/NordicSemiconductor/cmsis/core_cmSimd.h @@ -1,96 +1,96 @@ -/**************************************************************************//** - * @file core_cmSimd.h - * @brief CMSIS Cortex-M SIMD Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#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 __CORE_CMSIMD_H -#define __CORE_CMSIMD_H - -#ifdef __cplusplus - extern "C" { -#endif - - -/* ################### Compiler specific Intrinsics ########################### */ -/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics - Access to dedicated SIMD instructions - @{ -*/ - -/*------------------ RealView Compiler -----------------*/ -#if defined ( __CC_ARM ) - #include "cmsis_armcc.h" - -/*------------------ ARM Compiler V6 -------------------*/ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #include "cmsis_armcc_V6.h" - -/*------------------ GNU Compiler ----------------------*/ -#elif defined ( __GNUC__ ) - #include "cmsis_gcc.h" - -/*------------------ ICC Compiler ----------------------*/ -#elif defined ( __ICCARM__ ) - #include - -/*------------------ TI CCS Compiler -------------------*/ -#elif defined ( __TMS470__ ) - #include - -/*------------------ TASKING Compiler ------------------*/ -#elif defined ( __TASKING__ ) - /* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ - -/*------------------ COSMIC Compiler -------------------*/ -#elif defined ( __CSMC__ ) - #include - -#endif - -/*@} end of group CMSIS_SIMD_intrinsics */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __CORE_CMSIMD_H */ +/**************************************************************************//** + * @file core_cmSimd.h + * @brief CMSIS Cortex-M SIMD Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#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 __CORE_CMSIMD_H +#define __CORE_CMSIMD_H + +#ifdef __cplusplus + extern "C" { +#endif + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CMSIMD_H */ diff --git a/third_party/NordicSemiconductor/dependencies/app_util.h b/third_party/NordicSemiconductor/dependencies/app_util.h index 364ece910..7fd701291 100644 --- a/third_party/NordicSemiconductor/dependencies/app_util.h +++ b/third_party/NordicSemiconductor/dependencies/app_util.h @@ -1,1310 +1,1310 @@ -/** - * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup app_util Utility Functions and Definitions - * @{ - * @ingroup app_common - * - * @brief Various types and definitions available to all applications. - */ - -#ifndef APP_UTIL_H__ -#define APP_UTIL_H__ - -#include -#include -#include -#include "compiler_abstraction.h" -#include "nordic_common.h" -#include "nrf.h" - -#ifdef __cplusplus -extern "C" { -#endif -/** - * @cond (NODOX) - */ -/*lint -save -e27 -e10 -e19 */ -#if defined (__LINT__) -#define STACK_BASE 0x1F000 // Arbitrary value. -#define STACK_TOP 0x20000 // Arbitrary value. - -#elif defined ( __CC_ARM ) -extern char STACK$$Base; -extern char STACK$$Length; -#define STACK_BASE &STACK$$Base -#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&STACK$$Length)) - -#elif defined ( __ICCARM__ ) -extern char CSTACK$$Base; -extern char CSTACK$$Length; -#define STACK_BASE &CSTACK$$Base -#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&CSTACK$$Length)) - -#elif defined ( __GNUC__ ) -extern uint32_t __StackTop; -extern uint32_t __StackLimit; -#define STACK_BASE &__StackLimit -#define STACK_TOP &__StackTop -#endif - -/* These macros are valid only when absolute placement is used for the application - * image. The macros are not compile time symbols. They cannot be used as a - * constant expression, for example, inside a static assert or linker script - * at-placement. */ -#if defined (__LINT__) -#define CODE_START (0) // Arbitrary value. -#define CODE_END (0x1000) // Arbitrary value. -#define CODE_SIZE (0x1000) // Arbitrary value. - -#elif defined ( __CC_ARM ) -extern char Load$$LR$$LR_IROM1$$Base; -extern char Load$$LR$$LR_IROM1$$Length; -extern char Load$$LR$$LR_IROM1$$Limit; -#define CODE_START ((uint32_t)&Load$$LR$$LR_IROM1$$Base) -#define CODE_END ((uint32_t)&Load$$LR$$LR_IROM1$$Limit) -#define CODE_SIZE ((uint32_t)&Load$$LR$$LR_IROM1$$Length) - -#elif defined ( __ICCARM__ ) -extern void * __vector_table; -extern char RO_END$$Base; -#define CODE_START ((uint32_t)&__vector_table) -#define CODE_END ((uint32_t)&RO_END$$Base) -#define CODE_SIZE (CODE_END - CODE_START) - -#elif defined(__SES_ARM) -extern uint32_t * _vectors; -extern uint32_t __FLASH_segment_used_end__; -#define CODE_START ((uint32_t)&_vectors) -#define CODE_END ((uint32_t)&__FLASH_segment_used_end__) -#define CODE_SIZE (CODE_END - CODE_START) - -#elif defined ( __GNUC__ ) -extern uint32_t __isr_vector; -extern uint32_t __etext; -#define CODE_START ((uint32_t)&__isr_vector) -#define CODE_END ((uint32_t)&__etext) -#define CODE_SIZE (CODE_END - CODE_START) -#endif -/** @} - * @endcond - */ -/* lint -restore */ - -enum -{ - UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ - UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ - UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ -}; - -/** - * @brief Counts number of bits required for the given value - * - * The macro technically searches for the highest bit set. - * For value 0 it returns 0. - * - * @param val Value to be processed - * - * @return Number of bits required for the given value - */ -//lint -emacro(572,VBITS) -#define VBITS(val) VBITS_32(val) - -/** - * @def VBITS_1 - * @brief Internal macro used by @ref VBITS */ -/** - * @def VBITS_2 - * @brief Internal macro used by @ref VBITS */ -/** - * @def VBITS_4 - * @brief Internal macro used by @ref VBITS */ -/** - * @def VBITS_8 - * @brief Internal macro used by @ref VBITS */ -/** - * @def VBITS_16 - * @brief Internal macro used by @ref VBITS */ -/** - * @def VBITS_32 - * @brief Internal macro used by @ref VBITS */ -#define VBITS_1( v) ((((v) & (0x0001U << 0)) != 0) ? 1U : 0U) -#define VBITS_2( v) ((((v) & (0x0001U << 1)) != 0) ? VBITS_1 ((v) >> 1) + 1 : VBITS_1 (v)) -#define VBITS_4( v) ((((v) & (0x0003U << 2)) != 0) ? VBITS_2 ((v) >> 2) + 2 : VBITS_2 (v)) -#define VBITS_8( v) ((((v) & (0x000fU << 4)) != 0) ? VBITS_4 ((v) >> 4) + 4 : VBITS_4 (v)) -#define VBITS_16(v) ((((v) & (0x00ffU << 8)) != 0) ? VBITS_8 ((v) >> 8) + 8 : VBITS_8 (v)) -#define VBITS_32(v) ((((v) & (0xffffU << 16)) != 0) ? VBITS_16((v) >> 16) + 16 : VBITS_16(v)) - - -/*Segger embedded studio originally has offsetof macro which cannot be used in macros (like STATIC_ASSERT). - This redefinition is to allow using that. */ -#if defined(__SES_ARM) && defined(__GNUC__) -#undef offsetof -#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) -#endif - -/**@brief Implementation specific macro for delayed macro expansion used in string concatenation -* -* @param[in] lhs Left hand side in concatenation -* @param[in] rhs Right hand side in concatenation -*/ -#define STRING_CONCATENATE_IMPL(lhs, rhs) lhs ## rhs - - -/**@brief Macro used to concatenate string using delayed macro expansion -* -* @note This macro will delay concatenation until the expressions have been resolved -* -* @param[in] lhs Left hand side in concatenation -* @param[in] rhs Right hand side in concatenation -*/ -#define STRING_CONCATENATE(lhs, rhs) STRING_CONCATENATE_IMPL(lhs, rhs) - - -#ifndef __LINT__ - -#ifdef __GNUC__ -#define STATIC_ASSERT_SIMPLE(EXPR) _Static_assert(EXPR, "unspecified message") -#define STATIC_ASSERT_MSG(EXPR, MSG) _Static_assert(EXPR, MSG) -#endif - -#ifdef __CC_ARM -#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] -#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] -#endif - -#ifdef __ICCARM__ -#define STATIC_ASSERT_SIMPLE(EXPR) static_assert(EXPR, "unspecified message") -#define STATIC_ASSERT_MSG(EXPR, MSG) static_assert(EXPR, MSG) -#endif - -#else // __LINT__ - -#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_ignore(void)) -#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_ignore(void)) - -#endif - - -#define _SELECT_ASSERT_FUNC(x, EXPR, MSG, ASSERT_MACRO, ...) ASSERT_MACRO - -/** - * @brief Static (i.e. compile time) assert macro. - * - * @note The output of STATIC_ASSERT can be different across compilers. - * - * Usage: - * STATIC_ASSERT(expression); - * STATIC_ASSERT(expression, message); - * - * @hideinitializer - */ -//lint -save -esym(???, STATIC_ASSERT) -#define STATIC_ASSERT(...) \ - _SELECT_ASSERT_FUNC(x, ##__VA_ARGS__, \ - STATIC_ASSERT_MSG(__VA_ARGS__), \ - STATIC_ASSERT_SIMPLE(__VA_ARGS__)) -//lint -restore - - -/**@brief Implementation details for NUM_VAR_ARGS */ -#define NUM_VA_ARGS_IMPL( \ - _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ - _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ - _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ - _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ - _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ - _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ - _61, _62, N, ...) N - - -/**@brief Macro to get the number of arguments in a call variadic macro call - * - * param[in] ... List of arguments - * - * @retval Number of variadic arguments in the argument list - */ -#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__, 63, 62, 61, \ - 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ - 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ - 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ - 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ - 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ - 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) - -/**@brief Implementation details for NUM_VAR_ARGS */ -#define NUM_VA_ARGS_LESS_1_IMPL( \ - _ignored, \ - _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ - _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ - _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ - _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ - _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ - _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ - _61, _62, N, ...) N - -/**@brief Macro to get the number of arguments in a call variadic macro call. - * First argument is not counted. - * - * param[in] ... List of arguments - * - * @retval Number of variadic arguments in the argument list - */ -#define NUM_VA_ARGS_LESS_1(...) NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 63, 62, 61, \ - 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ - 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ - 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ - 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ - 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ - 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) - - -/**@brief type for holding an encoded (i.e. little endian) 16 bit unsigned integer. */ -typedef uint8_t uint16_le_t[2]; - -/**@brief Type for holding an encoded (i.e. little endian) 32 bit unsigned integer. */ -typedef uint8_t uint32_le_t[4]; - -/**@brief Byte array type. */ -typedef struct -{ - uint16_t size; /**< Number of array entries. */ - uint8_t * p_data; /**< Pointer to array entries. */ -} uint8_array_t; - - -/**@brief Macro for performing rounded integer division (as opposed to truncating the result). - * - * @param[in] A Numerator. - * @param[in] B Denominator. - * - * @return Rounded (integer) result of dividing A by B. - */ -#define ROUNDED_DIV(A, B) (((A) + ((B) / 2)) / (B)) - - -/**@brief Macro for checking if an integer is a power of two. - * - * @param[in] A Number to be tested. - * - * @return true if value is power of two. - * @return false if value not power of two. - */ -#define IS_POWER_OF_TWO(A) ( ((A) != 0) && ((((A) - 1) & (A)) == 0) ) - - -/**@brief Macro for converting milliseconds to ticks. - * - * @param[in] TIME Number of milliseconds to convert. - * @param[in] RESOLUTION Unit to be converted to in [us/ticks]. - */ -#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) - - -/**@brief Macro for performing integer division, making sure the result is rounded up. - * - * @details One typical use for this is to compute the number of objects with size B is needed to - * hold A number of bytes. - * - * @param[in] A Numerator. - * @param[in] B Denominator. - * - * @return Integer result of dividing A by B, rounded up. - */ -#define CEIL_DIV(A, B) \ - (((A) + (B) - 1) / (B)) - - -/**@brief Macro for creating a buffer aligned to 4 bytes. - * - * @param[in] NAME Name of the buffor. - * @param[in] MIN_SIZE Size of this buffor (it will be rounded up to multiples of 4 bytes). - */ -#define WORD_ALIGNED_MEM_BUFF(NAME, MIN_SIZE) static uint32_t NAME[CEIL_DIV(MIN_SIZE, sizeof(uint32_t))] - - -/**@brief Macro for calculating the number of words that are needed to hold a number of bytes. - * - * @details Adds 3 and divides by 4. - * - * @param[in] n_bytes The number of bytes. - * - * @return The number of words that @p n_bytes take up (rounded up). - */ -#define BYTES_TO_WORDS(n_bytes) (((n_bytes) + 3) >> 2) - - -/**@brief The number of bytes in a word. - */ -#define BYTES_PER_WORD (4) - - -/**@brief Macro for increasing a number to the nearest (larger) multiple of another number. - * - * @param[in] alignment The number to align to. - * @param[in] number The number to align (increase). - * - * @return The aligned (increased) @p number. - */ -#define ALIGN_NUM(alignment, number) (((number) - 1) + (alignment) - (((number) - 1) % (alignment))) - -/**@brief Macro for getting first of 2 parameters. - * - * @param[in] a1 First parameter. - * @param[in] a2 Second parameter. - */ -#define GET_ARG_1(a1, a2) a1 - -/**@brief Macro for getting second of 2 parameters. - * - * @param[in] a1 First parameter. - * @param[in] a2 Second parameter. - */ -#define GET_ARG_2(a1, a2) a2 - - -/**@brief Container of macro (borrowed from Linux kernel). - * - * This macro returns parent structure address basing on child member address. - * - * @param ptr Address of child type. - * @param type Type of parent structure. - * @param member Name of child field in parent structure. - * - * @return Parent structure address. - * */ -#define CONTAINER_OF(ptr, type, member) \ - (type *)((char *)ptr - offsetof(type, member)) - - -/** - * @brief Define Bit-field mask - * - * Macro that defined the mask with selected number of bits set, starting from - * provided bit number. - * - * @param[in] bcnt Number of bits in the bit-field - * @param[in] boff Lowest bit number - */ -#define BF_MASK(bcnt, boff) ( ((1U << (bcnt)) - 1U) << (boff) ) - -/** - * @brief Get bit-field - * - * Macro that extracts selected bit-field from provided value - * - * @param[in] val Value from which selected bit-field would be extracted - * @param[in] bcnt Number of bits in the bit-field - * @param[in] boff Lowest bit number - * - * @return Value of the selected bits - */ -#define BF_GET(val, bcnt, boff) ( ( (val) & BF_MASK((bcnt), (boff)) ) >> (boff) ) - -/** - * @brief Create bit-field value - * - * Value is masked and shifted to match given bit-field - * - * @param[in] val Value to set on bit-field - * @param[in] bcnt Number of bits for bit-field - * @param[in] boff Offset of bit-field - * - * @return Value positioned of given bit-field. - */ -#define BF_VAL(val, bcnt, boff) ( (((uint32_t)(val)) << (boff)) & BF_MASK(bcnt, boff) ) - -/** - * @name Configuration of complex bit-field - * - * @sa BF_CX - * @{ - */ -/** @brief Position of bit count in complex bit-field value */ -#define BF_CX_BCNT_POS 0U -/** @brief Mask of bit count in complex bit-field value */ -#define BF_CX_BCNT_MASK (0xffU << BF_CX_BCNT_POS) -/** @brief Position of bit position in complex bit-field value */ -#define BF_CX_BOFF_POS 8U -/** @brief Mask of bit position in complex bit-field value */ -#define BF_CX_BOFF_MASK (0xffU << BF_CX_BOFF_POS) -/** @} */ - -/** - * @brief Define complex bit-field - * - * Complex bit-field would contain its position and size in one number. - * @sa BF_CX_MASK - * @sa BF_CX_POS - * @sa BF_CX_GET - * - * @param[in] bcnt Number of bits in the bit-field - * @param[in] boff Lowest bit number - * - * @return The single number that describes the bit-field completely. - */ -#define BF_CX(bcnt, boff) ( ((((uint32_t)(bcnt)) << BF_CX_BCNT_POS) & BF_CX_BCNT_MASK) | ((((uint32_t)(boff)) << BF_CX_BOFF_POS) & BF_CX_BOFF_MASK) ) - -/** - * @brief Get number of bits in bit-field - * - * @sa BF_CX - * - * @param bf_cx Complex bit-field - * - * @return Number of bits in given bit-field - */ -#define BF_CX_BCNT(bf_cx) ( ((bf_cx) & BF_CX_BCNT_MASK) >> BF_CX_BCNT_POS ) - -/** - * @brief Get lowest bit number in the field - * - * @sa BF_CX - * - * @param[in] bf_cx Complex bit-field - * - * @return Lowest bit number in given bit-field - */ -#define BF_CX_BOFF(bf_cx) ( ((bf_cx) & BF_CX_BOFF_MASK) >> BF_CX_BOFF_POS ) - -/** - * @brief Get bit mask of the selected field - * - * @sa BF_CX - * - * @param[in] bf_cx Complex bit-field - * - * @return Mask of given bit-field - */ -#define BF_CX_MASK(bf_cx) BF_MASK(BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) - -/** - * @brief Get bit-field - * - * Macro that extracts selected bit-field from provided value. - * Bit-field is given as a complex value. - * - * @sa BF_CX - * @sa BF_GET - * - * @param[in] val Value from which selected bit-field would be extracted - * @param[in] bf_cx Complex bit-field - * - * @return Value of the selected bits. - */ -#define BF_CX_GET(val, bf_cx) BF_GET(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) - -/** - * @brief Create bit-field value - * - * Value is masked and shifted to match given bit-field. - * - * @param[in] val Value to set on bit-field - * @param[in] bf_cx Complex bit-field - * - * @return Value positioned of given bit-field. - */ -#define BF_CX_VAL(val, bf_cx) BF_VAL(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) - -/** - * @brief Extracting data from the brackets - * - * This macro get rid of brackets around the argument. - * It can be used to pass multiple arguments in logical one argument to a macro. - * Call it with arguments inside brackets: - * @code - * #define ARGUMENTS (a, b, c) - * BRACKET_EXTRACT(ARGUMENTS) - * @endcode - * It would produce: - * @code - * a, b, c - * @endcode - * - * @param a Argument with anything inside brackets - * @return Anything that appears inside the brackets of the argument - * - * @note - * The argument of the macro have to be inside brackets. - * In other case the compilation would fail. - */ -#define BRACKET_EXTRACT(a) BRACKET_EXTRACT_(a) -#define BRACKET_EXTRACT_(a) BRACKET_EXTRACT__ a -#define BRACKET_EXTRACT__(...) __VA_ARGS__ - - -/** - * @brief Check if number of parameters is more than 1 - * - * @param ... Arguments to count - * - * @return 0 If argument count is <= 1 - * @return 1 If argument count is > 1 - * - * @sa NUM_VA_ARGS - * @sa NUM_IS_MORE_THAN_1 - */ -#define NUM_VA_ARGS_IS_MORE_THAN_1(...) NUM_IS_MORE_THAN_1(NUM_VA_ARGS(__VA_ARGS__)) - -/** - * @brief Check if given numeric value is bigger than 1 - * - * This macro accepts numeric value, that may be the result of argument expansion. - * This numeric value is then converted to 0 if it is lover than 1 or to 1 if - * its value is higher than 1. - * The generated result can be used to glue it into other macro mnemonic name. - * - * @param N Numeric value to check - * - * @return 0 If argument is <= 1 - * @return 1 If argument is > 1 - * - * @note Any existing definition of a form NUM_IS_MORE_THAN_1_PROBE_[N] can - * broke the result of this macro - */ -#define NUM_IS_MORE_THAN_1(N) NUM_IS_MORE_THAN_1_(N) -#define NUM_IS_MORE_THAN_1_(N) NUM_IS_MORE_THAN_1_PROBE_(NUM_IS_MORE_THAN_1_PROBE_ ## N, 1) -#define NUM_IS_MORE_THAN_1_PROBE_(...) GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__)) -#define NUM_IS_MORE_THAN_1_PROBE_0 ~, 0 -#define NUM_IS_MORE_THAN_1_PROBE_1 ~, 0 - -/** - * @brief Get the first argument - * - * @param ... Arguments to select - * - * @return First argument or empty if no arguments are provided - */ -#define GET_VA_ARG_1(...) GET_VA_ARG_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works -#define GET_VA_ARG_1_(a1, ...) a1 - -/** - * @brief Get all the arguments but the first one - * - * @param ... Arguments to select - * - * @return All arguments after the first one or empty if less than 2 arguments are provided - */ -#define GET_ARGS_AFTER_1(...) GET_ARGS_AFTER_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works -#define GET_ARGS_AFTER_1_(a1, ...) __VA_ARGS__ - -/** - * @brief Size of a field in declared structure - * - * Macro that returns the size of the structure field. - * @param struct_type Variable type to get the field size from - * @param field Field name to analyze. It can be even field inside field (field.somethingelse.and_another). - * - * @return Size of the field - */ -#define FIELD_SIZE(struct_type, field) sizeof(((struct struct_type*)NULL)->field) - -/** - * @brief Number of elements in field array in declared structure - * - * Macro that returns number of elementy in structure field. - * @param struct_type Variable type to get the field size from - * @param field Field name to analyze. - * - * @return Number of elements in field array - * - * @sa FIELD_SIZE - */ -#define FIELD_ARRAY_SIZE(struct_type, field) (FIELD_SIZE(struct_type, field) / FIELD_SIZE(struct_type, field[0])) - -/** - * @brief Mapping macro - * - * Macro that process all arguments using given macro - * - * @param ... Macro name to be used for argument processing followed by arguments to process. - * Macro should have following form: MACRO(argument) - * - * @return All arguments processed by given macro - */ -#define MACRO_MAP(...) MACRO_MAP_(__VA_ARGS__) -#define MACRO_MAP_(...) MACRO_MAP_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total - -/** - * @brief Mapping macro, recursive version - * - * Can be used in @ref MACRO_MAP macro - */ -#define MACRO_MAP_REC(...) MACRO_MAP_REC_(__VA_ARGS__) -#define MACRO_MAP_REC_(...) MACRO_MAP_REC_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total -/** - * @brief Mapping N arguments macro - * - * Macro similar to @ref MACRO_MAP but maps exact number of arguments. - * If there is more arguments given, the rest would be ignored. - * - * @param N Number of arguments to map - * @param ... Macro name to be used for argument processing followed by arguments to process. - * Macro should have following form: MACRO(argument) - * - * @return Selected number of arguments processed by given macro - */ -#define MACRO_MAP_N(N, ...) MACRO_MAP_N_(N, __VA_ARGS__) -#define MACRO_MAP_N_(N, ...) CONCAT_2(MACRO_MAP_, N)(__VA_ARGS__, ) - -/** - * @brief Mapping N arguments macro, recursive version - * - * Can be used in @ref MACRO_MAP_N macro - */ -#define MACRO_MAP_REC_N(N, ...) MACRO_MAP_REC_N_(N, __VA_ARGS__) -#define MACRO_MAP_REC_N_(N, ...) CONCAT_2(MACRO_MAP_REC_, N)(__VA_ARGS__, ) - -#define MACRO_MAP_0( ...) -#define MACRO_MAP_1( macro, a, ...) macro(a) -#define MACRO_MAP_2( macro, a, ...) macro(a) MACRO_MAP_1 (macro, __VA_ARGS__, ) -#define MACRO_MAP_3( macro, a, ...) macro(a) MACRO_MAP_2 (macro, __VA_ARGS__, ) -#define MACRO_MAP_4( macro, a, ...) macro(a) MACRO_MAP_3 (macro, __VA_ARGS__, ) -#define MACRO_MAP_5( macro, a, ...) macro(a) MACRO_MAP_4 (macro, __VA_ARGS__, ) -#define MACRO_MAP_6( macro, a, ...) macro(a) MACRO_MAP_5 (macro, __VA_ARGS__, ) -#define MACRO_MAP_7( macro, a, ...) macro(a) MACRO_MAP_6 (macro, __VA_ARGS__, ) -#define MACRO_MAP_8( macro, a, ...) macro(a) MACRO_MAP_7 (macro, __VA_ARGS__, ) -#define MACRO_MAP_9( macro, a, ...) macro(a) MACRO_MAP_8 (macro, __VA_ARGS__, ) -#define MACRO_MAP_10(macro, a, ...) macro(a) MACRO_MAP_9 (macro, __VA_ARGS__, ) -#define MACRO_MAP_11(macro, a, ...) macro(a) MACRO_MAP_10(macro, __VA_ARGS__, ) -#define MACRO_MAP_12(macro, a, ...) macro(a) MACRO_MAP_11(macro, __VA_ARGS__, ) -#define MACRO_MAP_13(macro, a, ...) macro(a) MACRO_MAP_12(macro, __VA_ARGS__, ) -#define MACRO_MAP_14(macro, a, ...) macro(a) MACRO_MAP_13(macro, __VA_ARGS__, ) -#define MACRO_MAP_15(macro, a, ...) macro(a) MACRO_MAP_14(macro, __VA_ARGS__, ) -#define MACRO_MAP_16(macro, a, ...) macro(a) MACRO_MAP_15(macro, __VA_ARGS__, ) -#define MACRO_MAP_17(macro, a, ...) macro(a) MACRO_MAP_16(macro, __VA_ARGS__, ) -#define MACRO_MAP_18(macro, a, ...) macro(a) MACRO_MAP_17(macro, __VA_ARGS__, ) -#define MACRO_MAP_19(macro, a, ...) macro(a) MACRO_MAP_18(macro, __VA_ARGS__, ) -#define MACRO_MAP_20(macro, a, ...) macro(a) MACRO_MAP_19(macro, __VA_ARGS__, ) -#define MACRO_MAP_21(macro, a, ...) macro(a) MACRO_MAP_20(macro, __VA_ARGS__, ) -#define MACRO_MAP_22(macro, a, ...) macro(a) MACRO_MAP_21(macro, __VA_ARGS__, ) -#define MACRO_MAP_23(macro, a, ...) macro(a) MACRO_MAP_22(macro, __VA_ARGS__, ) -#define MACRO_MAP_24(macro, a, ...) macro(a) MACRO_MAP_23(macro, __VA_ARGS__, ) -#define MACRO_MAP_25(macro, a, ...) macro(a) MACRO_MAP_24(macro, __VA_ARGS__, ) -#define MACRO_MAP_26(macro, a, ...) macro(a) MACRO_MAP_25(macro, __VA_ARGS__, ) -#define MACRO_MAP_27(macro, a, ...) macro(a) MACRO_MAP_26(macro, __VA_ARGS__, ) -#define MACRO_MAP_28(macro, a, ...) macro(a) MACRO_MAP_27(macro, __VA_ARGS__, ) -#define MACRO_MAP_29(macro, a, ...) macro(a) MACRO_MAP_28(macro, __VA_ARGS__, ) -#define MACRO_MAP_30(macro, a, ...) macro(a) MACRO_MAP_29(macro, __VA_ARGS__, ) -#define MACRO_MAP_31(macro, a, ...) macro(a) MACRO_MAP_30(macro, __VA_ARGS__, ) -#define MACRO_MAP_32(macro, a, ...) macro(a) MACRO_MAP_31(macro, __VA_ARGS__, ) - - -#define MACRO_MAP_REC_0( ...) -#define MACRO_MAP_REC_1( macro, a, ...) macro(a) -#define MACRO_MAP_REC_2( macro, a, ...) macro(a) MACRO_MAP_REC_1 (macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_3( macro, a, ...) macro(a) MACRO_MAP_REC_2 (macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_4( macro, a, ...) macro(a) MACRO_MAP_REC_3 (macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_5( macro, a, ...) macro(a) MACRO_MAP_REC_4 (macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_6( macro, a, ...) macro(a) MACRO_MAP_REC_5 (macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_7( macro, a, ...) macro(a) MACRO_MAP_REC_6 (macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_8( macro, a, ...) macro(a) MACRO_MAP_REC_7 (macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_9( macro, a, ...) macro(a) MACRO_MAP_REC_8 (macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_10(macro, a, ...) macro(a) MACRO_MAP_REC_9 (macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_11(macro, a, ...) macro(a) MACRO_MAP_REC_10(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_12(macro, a, ...) macro(a) MACRO_MAP_REC_11(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_13(macro, a, ...) macro(a) MACRO_MAP_REC_12(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_14(macro, a, ...) macro(a) MACRO_MAP_REC_13(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_15(macro, a, ...) macro(a) MACRO_MAP_REC_14(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_16(macro, a, ...) macro(a) MACRO_MAP_REC_15(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_17(macro, a, ...) macro(a) MACRO_MAP_REC_16(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_18(macro, a, ...) macro(a) MACRO_MAP_REC_17(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_19(macro, a, ...) macro(a) MACRO_MAP_REC_18(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_20(macro, a, ...) macro(a) MACRO_MAP_REC_19(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_21(macro, a, ...) macro(a) MACRO_MAP_REC_20(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_22(macro, a, ...) macro(a) MACRO_MAP_REC_21(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_23(macro, a, ...) macro(a) MACRO_MAP_REC_22(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_24(macro, a, ...) macro(a) MACRO_MAP_REC_23(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_25(macro, a, ...) macro(a) MACRO_MAP_REC_24(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_26(macro, a, ...) macro(a) MACRO_MAP_REC_25(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_27(macro, a, ...) macro(a) MACRO_MAP_REC_26(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_28(macro, a, ...) macro(a) MACRO_MAP_REC_27(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_29(macro, a, ...) macro(a) MACRO_MAP_REC_28(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_30(macro, a, ...) macro(a) MACRO_MAP_REC_29(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_31(macro, a, ...) macro(a) MACRO_MAP_REC_30(macro, __VA_ARGS__, ) -#define MACRO_MAP_REC_32(macro, a, ...) macro(a) MACRO_MAP_REC_31(macro, __VA_ARGS__, ) - - -/** - * @brief Mapping macro with current index - * - * Basically macro similar to @ref MACRO_MAP, but the processing function would get an argument - * and current argument index (beginning from 0). - * - * @param ... Macro name to be used for argument processing followed by arguments to process. - * Macro should have following form: MACRO(argument, index) - * @return All arguments processed by given macro - */ -#define MACRO_MAP_FOR(...) MACRO_MAP_FOR_(__VA_ARGS__) -#define MACRO_MAP_FOR_N_LIST 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 -#define MACRO_MAP_FOR_(...) MACRO_MAP_FOR_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) - -/** - * @brief Mapping N arguments macro with current index - * - * Macro is similar to @ref MACRO_MAP_FOR but maps exact number of arguments. - * If there is more arguments given, the rest would be ignored. - * - * @param N Number of arguments to map - * @param ... Macro name to be used for argument processing followed by arguments to process. - * Macro should have following form: MACRO(argument, index) - * - * @return Selected number of arguments processed by given macro - */ -#define MACRO_MAP_FOR_N(N, ...) MACRO_MAP_FOR_N_(N, __VA_ARGS__) -#define MACRO_MAP_FOR_N_(N, ...) CONCAT_2(MACRO_MAP_FOR_, N)((MACRO_MAP_FOR_N_LIST), __VA_ARGS__, ) - -#define MACRO_MAP_FOR_0( n_list, ...) -#define MACRO_MAP_FOR_1( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) -#define MACRO_MAP_FOR_2( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_3( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_4( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_5( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_6( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_7( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_8( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_9( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_10(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_11(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_12(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_13(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_14(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_15(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_16(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_17(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_18(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_19(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_20(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_21(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_22(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_23(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_24(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_25(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_26(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_27(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_28(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_29(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_30(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_31(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_32(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) - - -/** - * @brief Mapping macro with current index and parameter - * - * Version of @ref MACRO_MAP_FOR that passes also the same parameter to all macros. - * - * @param param Parameter that would be passed to each macro call during mapping. - * @param ... Macro name to be used for argument processing followed by arguments to process. - * Macro should have following form: MACRO(argument, index, param) - * - * @return All arguments processed by given macro - */ -#define MACRO_MAP_FOR_PARAM(param, ...) MACRO_MAP_FOR_PARAM_(param, __VA_ARGS__) -#define MACRO_MAP_FOR_PARAM_(param, ...) MACRO_MAP_FOR_PARAM_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), param, __VA_ARGS__) - -/** - * @brief Mapping N arguments macro with with current index and parameter - * - * @param N Number of arguments to map - * @param param Parameter that would be passed to each macro call during mapping. - * @param ... Macro name to be used for argument processing followed by arguments to process. - * Macro should have following form: MACRO(argument, index, param) - * - * @return All arguments processed by given macro - */ -#define MACRO_MAP_FOR_PARAM_N(N, param, ...) MACRO_MAP_FOR_PARAM_N_(N, param, __VA_ARGS__) -#define MACRO_MAP_FOR_PARAM_N_(N, param, ...) CONCAT_2(MACRO_MAP_FOR_PARAM_, N)((MACRO_MAP_FOR_N_LIST), param, __VA_ARGS__, ) - - -#define MACRO_MAP_FOR_PARAM_0( n_list, param, ...) -#define MACRO_MAP_FOR_PARAM_1( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) -#define MACRO_MAP_FOR_PARAM_2( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_3( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_4( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_5( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_6( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_7( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_8( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_9( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_10(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_11(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_12(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_13(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_14(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_15(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_16(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_17(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_18(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_19(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_20(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_21(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_22(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_23(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_24(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_25(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_26(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_27(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_28(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_29(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_30(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_31(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) -#define MACRO_MAP_FOR_PARAM_32(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) - - - -/** - * @brief Repeating macro. - * - * @param count Count of repeats. - * @param macro Macro must have the following form: MACRO(arguments). - * @param ... Arguments passed to the macro. - * - * @return All arguments processed by the given macro. - */ -#define MACRO_REPEAT(count, macro, ...) MACRO_REPEAT_(count, macro, __VA_ARGS__) -#define MACRO_REPEAT_(count, macro, ...) CONCAT_2(MACRO_REPEAT_, count)(macro, __VA_ARGS__) - -#define MACRO_REPEAT_0(macro, ...) -#define MACRO_REPEAT_1(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_0(macro, __VA_ARGS__) -#define MACRO_REPEAT_2(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_1(macro, __VA_ARGS__) -#define MACRO_REPEAT_3(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_2(macro, __VA_ARGS__) -#define MACRO_REPEAT_4(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_3(macro, __VA_ARGS__) -#define MACRO_REPEAT_5(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_4(macro, __VA_ARGS__) -#define MACRO_REPEAT_6(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_5(macro, __VA_ARGS__) -#define MACRO_REPEAT_7(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_6(macro, __VA_ARGS__) -#define MACRO_REPEAT_8(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_7(macro, __VA_ARGS__) -#define MACRO_REPEAT_9(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_8(macro, __VA_ARGS__) -#define MACRO_REPEAT_10(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_9(macro, __VA_ARGS__) -#define MACRO_REPEAT_11(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_10(macro, __VA_ARGS__) -#define MACRO_REPEAT_12(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_11(macro, __VA_ARGS__) -#define MACRO_REPEAT_13(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_12(macro, __VA_ARGS__) -#define MACRO_REPEAT_14(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_13(macro, __VA_ARGS__) -#define MACRO_REPEAT_15(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_14(macro, __VA_ARGS__) -#define MACRO_REPEAT_16(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_15(macro, __VA_ARGS__) -#define MACRO_REPEAT_17(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_16(macro, __VA_ARGS__) -#define MACRO_REPEAT_18(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_17(macro, __VA_ARGS__) -#define MACRO_REPEAT_19(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_18(macro, __VA_ARGS__) -#define MACRO_REPEAT_20(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_19(macro, __VA_ARGS__) -#define MACRO_REPEAT_21(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_20(macro, __VA_ARGS__) -#define MACRO_REPEAT_22(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_21(macro, __VA_ARGS__) -#define MACRO_REPEAT_23(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_22(macro, __VA_ARGS__) -#define MACRO_REPEAT_24(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_23(macro, __VA_ARGS__) -#define MACRO_REPEAT_25(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_24(macro, __VA_ARGS__) -#define MACRO_REPEAT_26(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_25(macro, __VA_ARGS__) -#define MACRO_REPEAT_27(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_26(macro, __VA_ARGS__) -#define MACRO_REPEAT_28(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_27(macro, __VA_ARGS__) -#define MACRO_REPEAT_29(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_28(macro, __VA_ARGS__) -#define MACRO_REPEAT_30(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_29(macro, __VA_ARGS__) -#define MACRO_REPEAT_31(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_30(macro, __VA_ARGS__) -#define MACRO_REPEAT_32(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_31(macro, __VA_ARGS__) - - -/** - * @brief Repeating macro with current index. - * - * Macro similar to @ref MACRO_REPEAT but the processing function gets the arguments - * and the current argument index (beginning from 0). - - * @param count Count of repeats. - * @param macro Macro must have the following form: MACRO(index, arguments). - * @param ... Arguments passed to the macro. - * - * @return All arguments processed by the given macro. - */ -#define MACRO_REPEAT_FOR(count, macro, ...) MACRO_REPEAT_FOR_(count, macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_(count, macro, ...) CONCAT_2(MACRO_REPEAT_FOR_, count)((MACRO_MAP_FOR_N_LIST), macro, __VA_ARGS__) - -#define MACRO_REPEAT_FOR_0(n_list, macro, ...) -#define MACRO_REPEAT_FOR_1(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_0((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_2(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_1((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_3(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_2((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_4(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_3((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_5(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_4((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_6(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_5((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_7(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_6((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_8(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_7((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_9(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_8((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_10(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_9((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_11(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_12(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_13(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_14(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_15(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_16(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_17(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_18(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_19(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_20(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_21(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_22(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_23(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_24(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_25(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_26(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_27(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_28(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_29(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_30(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_31(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) -#define MACRO_REPEAT_FOR_32(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) - - -/**@brief Adding curly brace to the macro parameter. - * - * Useful in array of structures initialization. - * - * @param p Parameter to put into the curly brace. */ -#define PARAM_CBRACE(p) { p }, - - -/**@brief Function for changing the value unit. - * - * @param[in] value Value to be rescaled. - * @param[in] old_unit_reversal Reversal of the incoming unit. - * @param[in] new_unit_reversal Reversal of the desired unit. - * - * @return Number of bytes written. - */ -static __INLINE uint64_t value_rescale(uint32_t value, uint32_t old_unit_reversal, uint16_t new_unit_reversal) -{ - return (uint64_t)ROUNDED_DIV((uint64_t)value * new_unit_reversal, old_unit_reversal); -} - -/**@brief Function for encoding a uint16 value. - * - * @param[in] value Value to be encoded. - * @param[out] p_encoded_data Buffer where the encoded data is to be written. - * - * @return Number of bytes written. - */ -static __INLINE uint8_t uint16_encode(uint16_t value, uint8_t * p_encoded_data) -{ - p_encoded_data[0] = (uint8_t) ((value & 0x00FF) >> 0); - p_encoded_data[1] = (uint8_t) ((value & 0xFF00) >> 8); - return sizeof(uint16_t); -} - -/**@brief Function for encoding a three-byte value. - * - * @param[in] value Value to be encoded. - * @param[out] p_encoded_data Buffer where the encoded data is to be written. - * - * @return Number of bytes written. - */ -static __INLINE uint8_t uint24_encode(uint32_t value, uint8_t * p_encoded_data) -{ - p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); - p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); - p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); - return 3; -} - -/**@brief Function for encoding a uint32 value. - * - * @param[in] value Value to be encoded. - * @param[out] p_encoded_data Buffer where the encoded data is to be written. - * - * @return Number of bytes written. - */ -static __INLINE uint8_t uint32_encode(uint32_t value, uint8_t * p_encoded_data) -{ - p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); - p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); - p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); - p_encoded_data[3] = (uint8_t) ((value & 0xFF000000) >> 24); - return sizeof(uint32_t); -} - -/**@brief Function for encoding a uint40 value. - * - * @param[in] value Value to be encoded. - * @param[out] p_encoded_data Buffer where the encoded data is to be written. - * - * @return Number of bytes written. - */ -static __INLINE uint8_t uint40_encode(uint64_t value, uint8_t * p_encoded_data) -{ - p_encoded_data[0] = (uint8_t) ((value & 0x00000000FF) >> 0); - p_encoded_data[1] = (uint8_t) ((value & 0x000000FF00) >> 8); - p_encoded_data[2] = (uint8_t) ((value & 0x0000FF0000) >> 16); - p_encoded_data[3] = (uint8_t) ((value & 0x00FF000000) >> 24); - p_encoded_data[4] = (uint8_t) ((value & 0xFF00000000) >> 32); - return 5; -} - -/**@brief Function for encoding a uint48 value. - * - * @param[in] value Value to be encoded. - * @param[out] p_encoded_data Buffer where the encoded data is to be written. - * - * @return Number of bytes written. - */ -static __INLINE uint8_t uint48_encode(uint64_t value, uint8_t * p_encoded_data) -{ - p_encoded_data[0] = (uint8_t) ((value & 0x0000000000FF) >> 0); - p_encoded_data[1] = (uint8_t) ((value & 0x00000000FF00) >> 8); - p_encoded_data[2] = (uint8_t) ((value & 0x000000FF0000) >> 16); - p_encoded_data[3] = (uint8_t) ((value & 0x0000FF000000) >> 24); - p_encoded_data[4] = (uint8_t) ((value & 0x00FF00000000) >> 32); - p_encoded_data[5] = (uint8_t) ((value & 0xFF0000000000) >> 40); - return 6; -} - -/**@brief Function for decoding a uint16 value. - * - * @param[in] p_encoded_data Buffer where the encoded data is stored. - * - * @return Decoded value. - */ -static __INLINE uint16_t uint16_decode(const uint8_t * p_encoded_data) -{ - return ( (((uint16_t)((uint8_t *)p_encoded_data)[0])) | - (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 )); -} - -/**@brief Function for decoding a uint16 value in big-endian format. - * - * @param[in] p_encoded_data Buffer where the encoded data is stored. - * - * @return Decoded value. - */ -static __INLINE uint16_t uint16_big_decode(const uint8_t * p_encoded_data) -{ - return ( (((uint16_t)((uint8_t *)p_encoded_data)[0]) << 8 ) | - (((uint16_t)((uint8_t *)p_encoded_data)[1])) ); -} - -/**@brief Function for decoding a three-byte value. - * - * @param[in] p_encoded_data Buffer where the encoded data is stored. - * - * @return Decoded value (uint32_t). - */ -static __INLINE uint32_t uint24_decode(const uint8_t * p_encoded_data) -{ - return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | - (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | - (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16)); -} - -/**@brief Function for decoding a uint32 value. - * - * @param[in] p_encoded_data Buffer where the encoded data is stored. - * - * @return Decoded value. - */ -static __INLINE uint32_t uint32_decode(const uint8_t * p_encoded_data) -{ - return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | - (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | - (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | - (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 )); -} - -/**@brief Function for decoding a uint32 value in big-endian format. - * - * @param[in] p_encoded_data Buffer where the encoded data is stored. - * - * @return Decoded value. - */ -static __INLINE uint32_t uint32_big_decode(const uint8_t * p_encoded_data) -{ - return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 24) | - (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 16) | - (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 8) | - (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 0) ); -} - -/** - * @brief Function for encoding an uint16 value in big-endian format. - * - * @param[in] value Value to be encoded. - * @param[out] p_encoded_data Buffer where the encoded data will be written. - * - * @return Number of bytes written. - */ -static __INLINE uint8_t uint16_big_encode(uint16_t value, uint8_t * p_encoded_data) -{ - p_encoded_data[0] = (uint8_t) (value >> 8); - p_encoded_data[1] = (uint8_t) (value & 0xFF); - - return sizeof(uint16_t); -} - -/*lint -esym(526, __rev) */ -/*lint -esym(628, __rev) */ -/**@brief Function for encoding a uint32 value in big-endian format. - * - * @param[in] value Value to be encoded. - * @param[out] p_encoded_data Buffer where the encoded data will be written. - * - * @return Number of bytes written. - */ -static __INLINE uint8_t uint32_big_encode(uint32_t value, uint8_t * p_encoded_data) -{ - *(uint32_t *)p_encoded_data = __REV(value); - return sizeof(uint32_t); -} - -/**@brief Function for decoding a uint40 value. - * - * @param[in] p_encoded_data Buffer where the encoded data is stored. - * - * @return Decoded value. (uint64_t) - */ -static __INLINE uint64_t uint40_decode(const uint8_t * p_encoded_data) -{ - return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | - (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | - (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | - (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | - (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32 )); -} - -/**@brief Function for decoding a uint48 value. - * - * @param[in] p_encoded_data Buffer where the encoded data is stored. - * - * @return Decoded value. (uint64_t) - */ -static __INLINE uint64_t uint48_decode(const uint8_t * p_encoded_data) -{ - return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | - (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | - (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | - (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | - (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32) | - (((uint64_t)((uint8_t *)p_encoded_data)[5]) << 40 )); -} - -/** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts. - * - * @details The calculation is based on a linearized version of the battery's discharge - * curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and - * is considered to be the lower boundary. - * - * The discharge curve for CR2032 is non-linear. In this model it is split into - * 4 linear sections: - * - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV) - * - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV) - * - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV) - * - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV) - * - * These numbers are by no means accurate. Temperature and - * load in the actual application is not accounted for! - * - * @param[in] mvolts The voltage in mV - * - * @return Battery level in percent. -*/ -static __INLINE uint8_t battery_level_in_percent(const uint16_t mvolts) -{ - uint8_t battery_level; - - if (mvolts >= 3000) - { - battery_level = 100; - } - else if (mvolts > 2900) - { - battery_level = 100 - ((3000 - mvolts) * 58) / 100; - } - else if (mvolts > 2740) - { - battery_level = 42 - ((2900 - mvolts) * 24) / 160; - } - else if (mvolts > 2440) - { - battery_level = 18 - ((2740 - mvolts) * 12) / 300; - } - else if (mvolts > 2100) - { - battery_level = 6 - ((2440 - mvolts) * 6) / 340; - } - else - { - battery_level = 0; - } - - return battery_level; -} - -/**@brief Function for checking if a pointer value is aligned to a 4 byte boundary. - * - * @param[in] p Pointer value to be checked. - * - * @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise. - */ -static __INLINE bool is_word_aligned(void const* p) -{ - return (((uintptr_t)p & 0x03) == 0); -} - -/*lint -e{568, 685} */ -/** - * @brief Function for checking if provided address is located in stack space. - * - * @param[in] ptr Pointer to be checked. - * - * @return true if address is in stack space, false otherwise. - */ -static __INLINE bool is_address_from_stack(void * ptr) -{ - if (((uint32_t)ptr >= (uint32_t)STACK_BASE) && - ((uint32_t)ptr < (uint32_t)STACK_TOP) ) - { - return true; - } - else - { - return false; - } -} - -#ifdef __cplusplus -} -#endif - -#endif // APP_UTIL_H__ - -/** @} */ +/** + * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_util Utility Functions and Definitions + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications. + */ + +#ifndef APP_UTIL_H__ +#define APP_UTIL_H__ + +#include +#include +#include +#include "compiler_abstraction.h" +#include "nordic_common.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @cond (NODOX) + */ +/*lint -save -e27 -e10 -e19 */ +#if defined (__LINT__) +#define STACK_BASE 0x1F000 // Arbitrary value. +#define STACK_TOP 0x20000 // Arbitrary value. + +#elif defined ( __CC_ARM ) +extern char STACK$$Base; +extern char STACK$$Length; +#define STACK_BASE &STACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&STACK$$Length)) + +#elif defined ( __ICCARM__ ) +extern char CSTACK$$Base; +extern char CSTACK$$Length; +#define STACK_BASE &CSTACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&CSTACK$$Length)) + +#elif defined ( __GNUC__ ) +extern uint32_t __StackTop; +extern uint32_t __StackLimit; +#define STACK_BASE &__StackLimit +#define STACK_TOP &__StackTop +#endif + +/* These macros are valid only when absolute placement is used for the application + * image. The macros are not compile time symbols. They cannot be used as a + * constant expression, for example, inside a static assert or linker script + * at-placement. */ +#if defined (__LINT__) +#define CODE_START (0) // Arbitrary value. +#define CODE_END (0x1000) // Arbitrary value. +#define CODE_SIZE (0x1000) // Arbitrary value. + +#elif defined ( __CC_ARM ) +extern char Load$$LR$$LR_IROM1$$Base; +extern char Load$$LR$$LR_IROM1$$Length; +extern char Load$$LR$$LR_IROM1$$Limit; +#define CODE_START ((uint32_t)&Load$$LR$$LR_IROM1$$Base) +#define CODE_END ((uint32_t)&Load$$LR$$LR_IROM1$$Limit) +#define CODE_SIZE ((uint32_t)&Load$$LR$$LR_IROM1$$Length) + +#elif defined ( __ICCARM__ ) +extern void * __vector_table; +extern char RO_END$$Base; +#define CODE_START ((uint32_t)&__vector_table) +#define CODE_END ((uint32_t)&RO_END$$Base) +#define CODE_SIZE (CODE_END - CODE_START) + +#elif defined(__SES_ARM) +extern uint32_t * _vectors; +extern uint32_t __FLASH_segment_used_end__; +#define CODE_START ((uint32_t)&_vectors) +#define CODE_END ((uint32_t)&__FLASH_segment_used_end__) +#define CODE_SIZE (CODE_END - CODE_START) + +#elif defined ( __GNUC__ ) +extern uint32_t __isr_vector; +extern uint32_t __etext; +#define CODE_START ((uint32_t)&__isr_vector) +#define CODE_END ((uint32_t)&__etext) +#define CODE_SIZE (CODE_END - CODE_START) +#endif +/** @} + * @endcond + */ +/* lint -restore */ + +enum +{ + UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ + UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ + UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ +}; + +/** + * @brief Counts number of bits required for the given value + * + * The macro technically searches for the highest bit set. + * For value 0 it returns 0. + * + * @param val Value to be processed + * + * @return Number of bits required for the given value + */ +//lint -emacro(572,VBITS) +#define VBITS(val) VBITS_32(val) + +/** + * @def VBITS_1 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_2 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_4 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_8 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_16 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_32 + * @brief Internal macro used by @ref VBITS */ +#define VBITS_1( v) ((((v) & (0x0001U << 0)) != 0) ? 1U : 0U) +#define VBITS_2( v) ((((v) & (0x0001U << 1)) != 0) ? VBITS_1 ((v) >> 1) + 1 : VBITS_1 (v)) +#define VBITS_4( v) ((((v) & (0x0003U << 2)) != 0) ? VBITS_2 ((v) >> 2) + 2 : VBITS_2 (v)) +#define VBITS_8( v) ((((v) & (0x000fU << 4)) != 0) ? VBITS_4 ((v) >> 4) + 4 : VBITS_4 (v)) +#define VBITS_16(v) ((((v) & (0x00ffU << 8)) != 0) ? VBITS_8 ((v) >> 8) + 8 : VBITS_8 (v)) +#define VBITS_32(v) ((((v) & (0xffffU << 16)) != 0) ? VBITS_16((v) >> 16) + 16 : VBITS_16(v)) + + +/*Segger embedded studio originally has offsetof macro which cannot be used in macros (like STATIC_ASSERT). + This redefinition is to allow using that. */ +#if defined(__SES_ARM) && defined(__GNUC__) +#undef offsetof +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) +#endif + +/**@brief Implementation specific macro for delayed macro expansion used in string concatenation +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE_IMPL(lhs, rhs) lhs ## rhs + + +/**@brief Macro used to concatenate string using delayed macro expansion +* +* @note This macro will delay concatenation until the expressions have been resolved +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE(lhs, rhs) STRING_CONCATENATE_IMPL(lhs, rhs) + + +#ifndef __LINT__ + +#ifdef __GNUC__ +#define STATIC_ASSERT_SIMPLE(EXPR) _Static_assert(EXPR, "unspecified message") +#define STATIC_ASSERT_MSG(EXPR, MSG) _Static_assert(EXPR, MSG) +#endif + +#ifdef __CC_ARM +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#endif + +#ifdef __ICCARM__ +#define STATIC_ASSERT_SIMPLE(EXPR) static_assert(EXPR, "unspecified message") +#define STATIC_ASSERT_MSG(EXPR, MSG) static_assert(EXPR, MSG) +#endif + +#else // __LINT__ + +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_ignore(void)) +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_ignore(void)) + +#endif + + +#define _SELECT_ASSERT_FUNC(x, EXPR, MSG, ASSERT_MACRO, ...) ASSERT_MACRO + +/** + * @brief Static (i.e. compile time) assert macro. + * + * @note The output of STATIC_ASSERT can be different across compilers. + * + * Usage: + * STATIC_ASSERT(expression); + * STATIC_ASSERT(expression, message); + * + * @hideinitializer + */ +//lint -save -esym(???, STATIC_ASSERT) +#define STATIC_ASSERT(...) \ + _SELECT_ASSERT_FUNC(x, ##__VA_ARGS__, \ + STATIC_ASSERT_MSG(__VA_ARGS__), \ + STATIC_ASSERT_SIMPLE(__VA_ARGS__)) +//lint -restore + + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_IMPL( \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + + +/**@brief Macro to get the number of arguments in a call variadic macro call + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_LESS_1_IMPL( \ + _ignored, \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + +/**@brief Macro to get the number of arguments in a call variadic macro call. + * First argument is not counted. + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS_LESS_1(...) NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) + + +/**@brief type for holding an encoded (i.e. little endian) 16 bit unsigned integer. */ +typedef uint8_t uint16_le_t[2]; + +/**@brief Type for holding an encoded (i.e. little endian) 32 bit unsigned integer. */ +typedef uint8_t uint32_le_t[4]; + +/**@brief Byte array type. */ +typedef struct +{ + uint16_t size; /**< Number of array entries. */ + uint8_t * p_data; /**< Pointer to array entries. */ +} uint8_array_t; + + +/**@brief Macro for performing rounded integer division (as opposed to truncating the result). + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Rounded (integer) result of dividing A by B. + */ +#define ROUNDED_DIV(A, B) (((A) + ((B) / 2)) / (B)) + + +/**@brief Macro for checking if an integer is a power of two. + * + * @param[in] A Number to be tested. + * + * @return true if value is power of two. + * @return false if value not power of two. + */ +#define IS_POWER_OF_TWO(A) ( ((A) != 0) && ((((A) - 1) & (A)) == 0) ) + + +/**@brief Macro for converting milliseconds to ticks. + * + * @param[in] TIME Number of milliseconds to convert. + * @param[in] RESOLUTION Unit to be converted to in [us/ticks]. + */ +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) + + +/**@brief Macro for performing integer division, making sure the result is rounded up. + * + * @details One typical use for this is to compute the number of objects with size B is needed to + * hold A number of bytes. + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Integer result of dividing A by B, rounded up. + */ +#define CEIL_DIV(A, B) \ + (((A) + (B) - 1) / (B)) + + +/**@brief Macro for creating a buffer aligned to 4 bytes. + * + * @param[in] NAME Name of the buffor. + * @param[in] MIN_SIZE Size of this buffor (it will be rounded up to multiples of 4 bytes). + */ +#define WORD_ALIGNED_MEM_BUFF(NAME, MIN_SIZE) static uint32_t NAME[CEIL_DIV(MIN_SIZE, sizeof(uint32_t))] + + +/**@brief Macro for calculating the number of words that are needed to hold a number of bytes. + * + * @details Adds 3 and divides by 4. + * + * @param[in] n_bytes The number of bytes. + * + * @return The number of words that @p n_bytes take up (rounded up). + */ +#define BYTES_TO_WORDS(n_bytes) (((n_bytes) + 3) >> 2) + + +/**@brief The number of bytes in a word. + */ +#define BYTES_PER_WORD (4) + + +/**@brief Macro for increasing a number to the nearest (larger) multiple of another number. + * + * @param[in] alignment The number to align to. + * @param[in] number The number to align (increase). + * + * @return The aligned (increased) @p number. + */ +#define ALIGN_NUM(alignment, number) (((number) - 1) + (alignment) - (((number) - 1) % (alignment))) + +/**@brief Macro for getting first of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_1(a1, a2) a1 + +/**@brief Macro for getting second of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_2(a1, a2) a2 + + +/**@brief Container of macro (borrowed from Linux kernel). + * + * This macro returns parent structure address basing on child member address. + * + * @param ptr Address of child type. + * @param type Type of parent structure. + * @param member Name of child field in parent structure. + * + * @return Parent structure address. + * */ +#define CONTAINER_OF(ptr, type, member) \ + (type *)((char *)ptr - offsetof(type, member)) + + +/** + * @brief Define Bit-field mask + * + * Macro that defined the mask with selected number of bits set, starting from + * provided bit number. + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + */ +#define BF_MASK(bcnt, boff) ( ((1U << (bcnt)) - 1U) << (boff) ) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value + * + * @param[in] val Value from which selected bit-field would be extracted + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return Value of the selected bits + */ +#define BF_GET(val, bcnt, boff) ( ( (val) & BF_MASK((bcnt), (boff)) ) >> (boff) ) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field + * + * @param[in] val Value to set on bit-field + * @param[in] bcnt Number of bits for bit-field + * @param[in] boff Offset of bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_VAL(val, bcnt, boff) ( (((uint32_t)(val)) << (boff)) & BF_MASK(bcnt, boff) ) + +/** + * @name Configuration of complex bit-field + * + * @sa BF_CX + * @{ + */ +/** @brief Position of bit count in complex bit-field value */ +#define BF_CX_BCNT_POS 0U +/** @brief Mask of bit count in complex bit-field value */ +#define BF_CX_BCNT_MASK (0xffU << BF_CX_BCNT_POS) +/** @brief Position of bit position in complex bit-field value */ +#define BF_CX_BOFF_POS 8U +/** @brief Mask of bit position in complex bit-field value */ +#define BF_CX_BOFF_MASK (0xffU << BF_CX_BOFF_POS) +/** @} */ + +/** + * @brief Define complex bit-field + * + * Complex bit-field would contain its position and size in one number. + * @sa BF_CX_MASK + * @sa BF_CX_POS + * @sa BF_CX_GET + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return The single number that describes the bit-field completely. + */ +#define BF_CX(bcnt, boff) ( ((((uint32_t)(bcnt)) << BF_CX_BCNT_POS) & BF_CX_BCNT_MASK) | ((((uint32_t)(boff)) << BF_CX_BOFF_POS) & BF_CX_BOFF_MASK) ) + +/** + * @brief Get number of bits in bit-field + * + * @sa BF_CX + * + * @param bf_cx Complex bit-field + * + * @return Number of bits in given bit-field + */ +#define BF_CX_BCNT(bf_cx) ( ((bf_cx) & BF_CX_BCNT_MASK) >> BF_CX_BCNT_POS ) + +/** + * @brief Get lowest bit number in the field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Lowest bit number in given bit-field + */ +#define BF_CX_BOFF(bf_cx) ( ((bf_cx) & BF_CX_BOFF_MASK) >> BF_CX_BOFF_POS ) + +/** + * @brief Get bit mask of the selected field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Mask of given bit-field + */ +#define BF_CX_MASK(bf_cx) BF_MASK(BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value. + * Bit-field is given as a complex value. + * + * @sa BF_CX + * @sa BF_GET + * + * @param[in] val Value from which selected bit-field would be extracted + * @param[in] bf_cx Complex bit-field + * + * @return Value of the selected bits. + */ +#define BF_CX_GET(val, bf_cx) BF_GET(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field. + * + * @param[in] val Value to set on bit-field + * @param[in] bf_cx Complex bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_CX_VAL(val, bf_cx) BF_VAL(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Extracting data from the brackets + * + * This macro get rid of brackets around the argument. + * It can be used to pass multiple arguments in logical one argument to a macro. + * Call it with arguments inside brackets: + * @code + * #define ARGUMENTS (a, b, c) + * BRACKET_EXTRACT(ARGUMENTS) + * @endcode + * It would produce: + * @code + * a, b, c + * @endcode + * + * @param a Argument with anything inside brackets + * @return Anything that appears inside the brackets of the argument + * + * @note + * The argument of the macro have to be inside brackets. + * In other case the compilation would fail. + */ +#define BRACKET_EXTRACT(a) BRACKET_EXTRACT_(a) +#define BRACKET_EXTRACT_(a) BRACKET_EXTRACT__ a +#define BRACKET_EXTRACT__(...) __VA_ARGS__ + + +/** + * @brief Check if number of parameters is more than 1 + * + * @param ... Arguments to count + * + * @return 0 If argument count is <= 1 + * @return 1 If argument count is > 1 + * + * @sa NUM_VA_ARGS + * @sa NUM_IS_MORE_THAN_1 + */ +#define NUM_VA_ARGS_IS_MORE_THAN_1(...) NUM_IS_MORE_THAN_1(NUM_VA_ARGS(__VA_ARGS__)) + +/** + * @brief Check if given numeric value is bigger than 1 + * + * This macro accepts numeric value, that may be the result of argument expansion. + * This numeric value is then converted to 0 if it is lover than 1 or to 1 if + * its value is higher than 1. + * The generated result can be used to glue it into other macro mnemonic name. + * + * @param N Numeric value to check + * + * @return 0 If argument is <= 1 + * @return 1 If argument is > 1 + * + * @note Any existing definition of a form NUM_IS_MORE_THAN_1_PROBE_[N] can + * broke the result of this macro + */ +#define NUM_IS_MORE_THAN_1(N) NUM_IS_MORE_THAN_1_(N) +#define NUM_IS_MORE_THAN_1_(N) NUM_IS_MORE_THAN_1_PROBE_(NUM_IS_MORE_THAN_1_PROBE_ ## N, 1) +#define NUM_IS_MORE_THAN_1_PROBE_(...) GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__)) +#define NUM_IS_MORE_THAN_1_PROBE_0 ~, 0 +#define NUM_IS_MORE_THAN_1_PROBE_1 ~, 0 + +/** + * @brief Get the first argument + * + * @param ... Arguments to select + * + * @return First argument or empty if no arguments are provided + */ +#define GET_VA_ARG_1(...) GET_VA_ARG_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_VA_ARG_1_(a1, ...) a1 + +/** + * @brief Get all the arguments but the first one + * + * @param ... Arguments to select + * + * @return All arguments after the first one or empty if less than 2 arguments are provided + */ +#define GET_ARGS_AFTER_1(...) GET_ARGS_AFTER_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_ARGS_AFTER_1_(a1, ...) __VA_ARGS__ + +/** + * @brief Size of a field in declared structure + * + * Macro that returns the size of the structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. It can be even field inside field (field.somethingelse.and_another). + * + * @return Size of the field + */ +#define FIELD_SIZE(struct_type, field) sizeof(((struct struct_type*)NULL)->field) + +/** + * @brief Number of elements in field array in declared structure + * + * Macro that returns number of elementy in structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. + * + * @return Number of elements in field array + * + * @sa FIELD_SIZE + */ +#define FIELD_ARRAY_SIZE(struct_type, field) (FIELD_SIZE(struct_type, field) / FIELD_SIZE(struct_type, field[0])) + +/** + * @brief Mapping macro + * + * Macro that process all arguments using given macro + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP(...) MACRO_MAP_(__VA_ARGS__) +#define MACRO_MAP_(...) MACRO_MAP_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total + +/** + * @brief Mapping macro, recursive version + * + * Can be used in @ref MACRO_MAP macro + */ +#define MACRO_MAP_REC(...) MACRO_MAP_REC_(__VA_ARGS__) +#define MACRO_MAP_REC_(...) MACRO_MAP_REC_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total +/** + * @brief Mapping N arguments macro + * + * Macro similar to @ref MACRO_MAP but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_N(N, ...) MACRO_MAP_N_(N, __VA_ARGS__) +#define MACRO_MAP_N_(N, ...) CONCAT_2(MACRO_MAP_, N)(__VA_ARGS__, ) + +/** + * @brief Mapping N arguments macro, recursive version + * + * Can be used in @ref MACRO_MAP_N macro + */ +#define MACRO_MAP_REC_N(N, ...) MACRO_MAP_REC_N_(N, __VA_ARGS__) +#define MACRO_MAP_REC_N_(N, ...) CONCAT_2(MACRO_MAP_REC_, N)(__VA_ARGS__, ) + +#define MACRO_MAP_0( ...) +#define MACRO_MAP_1( macro, a, ...) macro(a) +#define MACRO_MAP_2( macro, a, ...) macro(a) MACRO_MAP_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_3( macro, a, ...) macro(a) MACRO_MAP_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_4( macro, a, ...) macro(a) MACRO_MAP_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_5( macro, a, ...) macro(a) MACRO_MAP_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_6( macro, a, ...) macro(a) MACRO_MAP_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_7( macro, a, ...) macro(a) MACRO_MAP_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_8( macro, a, ...) macro(a) MACRO_MAP_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_9( macro, a, ...) macro(a) MACRO_MAP_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_10(macro, a, ...) macro(a) MACRO_MAP_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_11(macro, a, ...) macro(a) MACRO_MAP_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_12(macro, a, ...) macro(a) MACRO_MAP_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_13(macro, a, ...) macro(a) MACRO_MAP_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_14(macro, a, ...) macro(a) MACRO_MAP_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_15(macro, a, ...) macro(a) MACRO_MAP_14(macro, __VA_ARGS__, ) +#define MACRO_MAP_16(macro, a, ...) macro(a) MACRO_MAP_15(macro, __VA_ARGS__, ) +#define MACRO_MAP_17(macro, a, ...) macro(a) MACRO_MAP_16(macro, __VA_ARGS__, ) +#define MACRO_MAP_18(macro, a, ...) macro(a) MACRO_MAP_17(macro, __VA_ARGS__, ) +#define MACRO_MAP_19(macro, a, ...) macro(a) MACRO_MAP_18(macro, __VA_ARGS__, ) +#define MACRO_MAP_20(macro, a, ...) macro(a) MACRO_MAP_19(macro, __VA_ARGS__, ) +#define MACRO_MAP_21(macro, a, ...) macro(a) MACRO_MAP_20(macro, __VA_ARGS__, ) +#define MACRO_MAP_22(macro, a, ...) macro(a) MACRO_MAP_21(macro, __VA_ARGS__, ) +#define MACRO_MAP_23(macro, a, ...) macro(a) MACRO_MAP_22(macro, __VA_ARGS__, ) +#define MACRO_MAP_24(macro, a, ...) macro(a) MACRO_MAP_23(macro, __VA_ARGS__, ) +#define MACRO_MAP_25(macro, a, ...) macro(a) MACRO_MAP_24(macro, __VA_ARGS__, ) +#define MACRO_MAP_26(macro, a, ...) macro(a) MACRO_MAP_25(macro, __VA_ARGS__, ) +#define MACRO_MAP_27(macro, a, ...) macro(a) MACRO_MAP_26(macro, __VA_ARGS__, ) +#define MACRO_MAP_28(macro, a, ...) macro(a) MACRO_MAP_27(macro, __VA_ARGS__, ) +#define MACRO_MAP_29(macro, a, ...) macro(a) MACRO_MAP_28(macro, __VA_ARGS__, ) +#define MACRO_MAP_30(macro, a, ...) macro(a) MACRO_MAP_29(macro, __VA_ARGS__, ) +#define MACRO_MAP_31(macro, a, ...) macro(a) MACRO_MAP_30(macro, __VA_ARGS__, ) +#define MACRO_MAP_32(macro, a, ...) macro(a) MACRO_MAP_31(macro, __VA_ARGS__, ) + + +#define MACRO_MAP_REC_0( ...) +#define MACRO_MAP_REC_1( macro, a, ...) macro(a) +#define MACRO_MAP_REC_2( macro, a, ...) macro(a) MACRO_MAP_REC_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_3( macro, a, ...) macro(a) MACRO_MAP_REC_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_4( macro, a, ...) macro(a) MACRO_MAP_REC_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_5( macro, a, ...) macro(a) MACRO_MAP_REC_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_6( macro, a, ...) macro(a) MACRO_MAP_REC_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_7( macro, a, ...) macro(a) MACRO_MAP_REC_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_8( macro, a, ...) macro(a) MACRO_MAP_REC_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_9( macro, a, ...) macro(a) MACRO_MAP_REC_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_10(macro, a, ...) macro(a) MACRO_MAP_REC_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_11(macro, a, ...) macro(a) MACRO_MAP_REC_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_12(macro, a, ...) macro(a) MACRO_MAP_REC_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_13(macro, a, ...) macro(a) MACRO_MAP_REC_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_14(macro, a, ...) macro(a) MACRO_MAP_REC_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_15(macro, a, ...) macro(a) MACRO_MAP_REC_14(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_16(macro, a, ...) macro(a) MACRO_MAP_REC_15(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_17(macro, a, ...) macro(a) MACRO_MAP_REC_16(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_18(macro, a, ...) macro(a) MACRO_MAP_REC_17(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_19(macro, a, ...) macro(a) MACRO_MAP_REC_18(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_20(macro, a, ...) macro(a) MACRO_MAP_REC_19(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_21(macro, a, ...) macro(a) MACRO_MAP_REC_20(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_22(macro, a, ...) macro(a) MACRO_MAP_REC_21(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_23(macro, a, ...) macro(a) MACRO_MAP_REC_22(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_24(macro, a, ...) macro(a) MACRO_MAP_REC_23(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_25(macro, a, ...) macro(a) MACRO_MAP_REC_24(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_26(macro, a, ...) macro(a) MACRO_MAP_REC_25(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_27(macro, a, ...) macro(a) MACRO_MAP_REC_26(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_28(macro, a, ...) macro(a) MACRO_MAP_REC_27(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_29(macro, a, ...) macro(a) MACRO_MAP_REC_28(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_30(macro, a, ...) macro(a) MACRO_MAP_REC_29(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_31(macro, a, ...) macro(a) MACRO_MAP_REC_30(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_32(macro, a, ...) macro(a) MACRO_MAP_REC_31(macro, __VA_ARGS__, ) + + +/** + * @brief Mapping macro with current index + * + * Basically macro similar to @ref MACRO_MAP, but the processing function would get an argument + * and current argument index (beginning from 0). + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR(...) MACRO_MAP_FOR_(__VA_ARGS__) +#define MACRO_MAP_FOR_N_LIST 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +#define MACRO_MAP_FOR_(...) MACRO_MAP_FOR_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with current index + * + * Macro is similar to @ref MACRO_MAP_FOR but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_FOR_N(N, ...) MACRO_MAP_FOR_N_(N, __VA_ARGS__) +#define MACRO_MAP_FOR_N_(N, ...) CONCAT_2(MACRO_MAP_FOR_, N)((MACRO_MAP_FOR_N_LIST), __VA_ARGS__, ) + +#define MACRO_MAP_FOR_0( n_list, ...) +#define MACRO_MAP_FOR_1( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) +#define MACRO_MAP_FOR_2( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_3( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_4( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_5( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_6( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_7( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_8( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_9( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_10(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_11(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_12(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_13(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_14(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_15(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_16(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_17(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_18(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_19(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_20(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_21(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_22(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_23(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_24(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_25(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_26(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_27(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_28(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_29(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_30(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_31(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_32(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) + + +/** + * @brief Mapping macro with current index and parameter + * + * Version of @ref MACRO_MAP_FOR that passes also the same parameter to all macros. + * + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM(param, ...) MACRO_MAP_FOR_PARAM_(param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_(param, ...) MACRO_MAP_FOR_PARAM_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), param, __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with with current index and parameter + * + * @param N Number of arguments to map + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM_N(N, param, ...) MACRO_MAP_FOR_PARAM_N_(N, param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_N_(N, param, ...) CONCAT_2(MACRO_MAP_FOR_PARAM_, N)((MACRO_MAP_FOR_N_LIST), param, __VA_ARGS__, ) + + +#define MACRO_MAP_FOR_PARAM_0( n_list, param, ...) +#define MACRO_MAP_FOR_PARAM_1( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) +#define MACRO_MAP_FOR_PARAM_2( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_3( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_4( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_5( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_6( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_7( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_8( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_9( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_10(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_11(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_12(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_13(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_14(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_15(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_16(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_17(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_18(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_19(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_20(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_21(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_22(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_23(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_24(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_25(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_26(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_27(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_28(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_29(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_30(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_31(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_32(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) + + + +/** + * @brief Repeating macro. + * + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT(count, macro, ...) MACRO_REPEAT_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_(count, macro, ...) CONCAT_2(MACRO_REPEAT_, count)(macro, __VA_ARGS__) + +#define MACRO_REPEAT_0(macro, ...) +#define MACRO_REPEAT_1(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_0(macro, __VA_ARGS__) +#define MACRO_REPEAT_2(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_1(macro, __VA_ARGS__) +#define MACRO_REPEAT_3(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_2(macro, __VA_ARGS__) +#define MACRO_REPEAT_4(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_3(macro, __VA_ARGS__) +#define MACRO_REPEAT_5(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_4(macro, __VA_ARGS__) +#define MACRO_REPEAT_6(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_5(macro, __VA_ARGS__) +#define MACRO_REPEAT_7(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_6(macro, __VA_ARGS__) +#define MACRO_REPEAT_8(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_7(macro, __VA_ARGS__) +#define MACRO_REPEAT_9(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_8(macro, __VA_ARGS__) +#define MACRO_REPEAT_10(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_9(macro, __VA_ARGS__) +#define MACRO_REPEAT_11(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_10(macro, __VA_ARGS__) +#define MACRO_REPEAT_12(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_11(macro, __VA_ARGS__) +#define MACRO_REPEAT_13(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_12(macro, __VA_ARGS__) +#define MACRO_REPEAT_14(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_13(macro, __VA_ARGS__) +#define MACRO_REPEAT_15(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_14(macro, __VA_ARGS__) +#define MACRO_REPEAT_16(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_15(macro, __VA_ARGS__) +#define MACRO_REPEAT_17(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_16(macro, __VA_ARGS__) +#define MACRO_REPEAT_18(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_17(macro, __VA_ARGS__) +#define MACRO_REPEAT_19(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_18(macro, __VA_ARGS__) +#define MACRO_REPEAT_20(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_19(macro, __VA_ARGS__) +#define MACRO_REPEAT_21(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_20(macro, __VA_ARGS__) +#define MACRO_REPEAT_22(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_21(macro, __VA_ARGS__) +#define MACRO_REPEAT_23(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_22(macro, __VA_ARGS__) +#define MACRO_REPEAT_24(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_23(macro, __VA_ARGS__) +#define MACRO_REPEAT_25(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_24(macro, __VA_ARGS__) +#define MACRO_REPEAT_26(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_25(macro, __VA_ARGS__) +#define MACRO_REPEAT_27(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_26(macro, __VA_ARGS__) +#define MACRO_REPEAT_28(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_27(macro, __VA_ARGS__) +#define MACRO_REPEAT_29(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_28(macro, __VA_ARGS__) +#define MACRO_REPEAT_30(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_29(macro, __VA_ARGS__) +#define MACRO_REPEAT_31(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_30(macro, __VA_ARGS__) +#define MACRO_REPEAT_32(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_31(macro, __VA_ARGS__) + + +/** + * @brief Repeating macro with current index. + * + * Macro similar to @ref MACRO_REPEAT but the processing function gets the arguments + * and the current argument index (beginning from 0). + + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(index, arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT_FOR(count, macro, ...) MACRO_REPEAT_FOR_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_(count, macro, ...) CONCAT_2(MACRO_REPEAT_FOR_, count)((MACRO_MAP_FOR_N_LIST), macro, __VA_ARGS__) + +#define MACRO_REPEAT_FOR_0(n_list, macro, ...) +#define MACRO_REPEAT_FOR_1(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_0((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_2(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_1((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_3(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_2((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_4(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_3((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_5(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_4((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_6(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_5((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_7(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_6((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_8(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_7((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_9(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_8((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_10(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_9((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_11(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_12(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_13(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_14(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_15(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_16(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_17(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_18(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_19(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_20(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_21(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_22(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_23(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_24(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_25(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_26(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_27(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_28(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_29(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_30(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_31(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_32(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) + + +/**@brief Adding curly brace to the macro parameter. + * + * Useful in array of structures initialization. + * + * @param p Parameter to put into the curly brace. */ +#define PARAM_CBRACE(p) { p }, + + +/**@brief Function for changing the value unit. + * + * @param[in] value Value to be rescaled. + * @param[in] old_unit_reversal Reversal of the incoming unit. + * @param[in] new_unit_reversal Reversal of the desired unit. + * + * @return Number of bytes written. + */ +static __INLINE uint64_t value_rescale(uint32_t value, uint32_t old_unit_reversal, uint16_t new_unit_reversal) +{ + return (uint64_t)ROUNDED_DIV((uint64_t)value * new_unit_reversal, old_unit_reversal); +} + +/**@brief Function for encoding a uint16 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x00FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0xFF00) >> 8); + return sizeof(uint16_t); +} + +/**@brief Function for encoding a three-byte value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint24_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + return 3; +} + +/**@brief Function for encoding a uint32 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0xFF000000) >> 24); + return sizeof(uint32_t); +} + +/**@brief Function for encoding a uint40 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint40_encode(uint64_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x00000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x0000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0x00FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((value & 0xFF00000000) >> 32); + return 5; +} + +/**@brief Function for encoding a uint48 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint48_encode(uint64_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x0000000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x00000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x000000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0x0000FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((value & 0x00FF00000000) >> 32); + p_encoded_data[5] = (uint8_t) ((value & 0xFF0000000000) >> 40); + return 6; +} + +/**@brief Function for decoding a uint16 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0])) | + (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 )); +} + +/**@brief Function for decoding a uint16 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0]) << 8 ) | + (((uint16_t)((uint8_t *)p_encoded_data)[1])) ); +} + +/**@brief Function for decoding a three-byte value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value (uint32_t). + */ +static __INLINE uint32_t uint24_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16)); +} + +/**@brief Function for decoding a uint32 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 )); +} + +/**@brief Function for decoding a uint32 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 24) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 0) ); +} + +/** + * @brief Function for encoding an uint16 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_big_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) (value >> 8); + p_encoded_data[1] = (uint8_t) (value & 0xFF); + + return sizeof(uint16_t); +} + +/*lint -esym(526, __rev) */ +/*lint -esym(628, __rev) */ +/**@brief Function for encoding a uint32 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_big_encode(uint32_t value, uint8_t * p_encoded_data) +{ + *(uint32_t *)p_encoded_data = __REV(value); + return sizeof(uint32_t); +} + +/**@brief Function for decoding a uint40 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. (uint64_t) + */ +static __INLINE uint64_t uint40_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32 )); +} + +/**@brief Function for decoding a uint48 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. (uint64_t) + */ +static __INLINE uint64_t uint48_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32) | + (((uint64_t)((uint8_t *)p_encoded_data)[5]) << 40 )); +} + +/** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts. + * + * @details The calculation is based on a linearized version of the battery's discharge + * curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and + * is considered to be the lower boundary. + * + * The discharge curve for CR2032 is non-linear. In this model it is split into + * 4 linear sections: + * - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV) + * - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV) + * - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV) + * - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV) + * + * These numbers are by no means accurate. Temperature and + * load in the actual application is not accounted for! + * + * @param[in] mvolts The voltage in mV + * + * @return Battery level in percent. +*/ +static __INLINE uint8_t battery_level_in_percent(const uint16_t mvolts) +{ + uint8_t battery_level; + + if (mvolts >= 3000) + { + battery_level = 100; + } + else if (mvolts > 2900) + { + battery_level = 100 - ((3000 - mvolts) * 58) / 100; + } + else if (mvolts > 2740) + { + battery_level = 42 - ((2900 - mvolts) * 24) / 160; + } + else if (mvolts > 2440) + { + battery_level = 18 - ((2740 - mvolts) * 12) / 300; + } + else if (mvolts > 2100) + { + battery_level = 6 - ((2440 - mvolts) * 6) / 340; + } + else + { + battery_level = 0; + } + + return battery_level; +} + +/**@brief Function for checking if a pointer value is aligned to a 4 byte boundary. + * + * @param[in] p Pointer value to be checked. + * + * @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise. + */ +static __INLINE bool is_word_aligned(void const* p) +{ + return (((uintptr_t)p & 0x03) == 0); +} + +/*lint -e{568, 685} */ +/** + * @brief Function for checking if provided address is located in stack space. + * + * @param[in] ptr Pointer to be checked. + * + * @return true if address is in stack space, false otherwise. + */ +static __INLINE bool is_address_from_stack(void * ptr) +{ + if (((uint32_t)ptr >= (uint32_t)STACK_BASE) && + ((uint32_t)ptr < (uint32_t)STACK_TOP) ) + { + return true; + } + else + { + return false; + } +} + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_H__ + +/** @} */ diff --git a/third_party/NordicSemiconductor/dependencies/app_util_platform.c b/third_party/NordicSemiconductor/dependencies/app_util_platform.c index aa10017fc..3c7129a58 100644 --- a/third_party/NordicSemiconductor/dependencies/app_util_platform.c +++ b/third_party/NordicSemiconductor/dependencies/app_util_platform.c @@ -1,129 +1,129 @@ -/** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "app_util_platform.h" - -#ifdef SOFTDEVICE_PRESENT -/* Global nvic state instance, required by nrf_nvic.h */ -nrf_nvic_state_t nrf_nvic_state; -#endif - -static uint32_t m_in_critical_region = 0; - -void app_util_disable_irq(void) -{ - __disable_irq(); - m_in_critical_region++; -} - -void app_util_enable_irq(void) -{ - m_in_critical_region--; - if (m_in_critical_region == 0) - { - __enable_irq(); - } -} - -void app_util_critical_region_enter(uint8_t *p_nested) -{ -#if __CORTEX_M == (0x04U) - ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) -#endif - -#if defined(SOFTDEVICE_PRESENT) - /* return value can be safely ignored */ - (void) sd_nvic_critical_region_enter(p_nested); -#else - (void)p_nested; - app_util_disable_irq(); -#endif -} - -void app_util_critical_region_exit(uint8_t nested) -{ -#if __CORTEX_M == (0x04U) - ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) -#endif - -#if defined(SOFTDEVICE_PRESENT) - /* return value can be safely ignored */ - (void) sd_nvic_critical_region_exit(nested); -#else - app_util_enable_irq(); - (void)nested; -#endif -} - - -uint8_t privilege_level_get(void) -{ -#if __CORTEX_M == (0x00U) || defined(_WIN32) || defined(__unix) || defined(__APPLE__) - /* the Cortex-M0 has no concept of privilege */ - return APP_LEVEL_PRIVILEGED; -#elif __CORTEX_M == (0x04U) - uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; - if (0 == isr_vector_num) - { - /* Thread Mode, check nPRIV */ - int32_t control = __get_CONTROL(); - return control & CONTROL_nPRIV_Msk ? APP_LEVEL_UNPRIVILEGED : APP_LEVEL_PRIVILEGED; - } - else - { - /* Handler Mode, always privileged */ - return APP_LEVEL_PRIVILEGED; - } -#endif -} - - -uint8_t current_int_priority_get(void) -{ - uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; - if (isr_vector_num > 0) - { - int32_t irq_type = ((int32_t)isr_vector_num - EXTERNAL_INT_VECTOR_OFFSET); - return (NVIC_GetPriority((IRQn_Type)irq_type) & 0xFF); - } - else - { - return APP_IRQ_PRIORITY_THREAD; - } -} +/** + * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "app_util_platform.h" + +#ifdef SOFTDEVICE_PRESENT +/* Global nvic state instance, required by nrf_nvic.h */ +nrf_nvic_state_t nrf_nvic_state; +#endif + +static uint32_t m_in_critical_region = 0; + +void app_util_disable_irq(void) +{ + __disable_irq(); + m_in_critical_region++; +} + +void app_util_enable_irq(void) +{ + m_in_critical_region--; + if (m_in_critical_region == 0) + { + __enable_irq(); + } +} + +void app_util_critical_region_enter(uint8_t *p_nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +#if defined(SOFTDEVICE_PRESENT) + /* return value can be safely ignored */ + (void) sd_nvic_critical_region_enter(p_nested); +#else + (void)p_nested; + app_util_disable_irq(); +#endif +} + +void app_util_critical_region_exit(uint8_t nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +#if defined(SOFTDEVICE_PRESENT) + /* return value can be safely ignored */ + (void) sd_nvic_critical_region_exit(nested); +#else + app_util_enable_irq(); + (void)nested; +#endif +} + + +uint8_t privilege_level_get(void) +{ +#if __CORTEX_M == (0x00U) || defined(_WIN32) || defined(__unix) || defined(__APPLE__) + /* the Cortex-M0 has no concept of privilege */ + return APP_LEVEL_PRIVILEGED; +#elif __CORTEX_M == (0x04U) + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (0 == isr_vector_num) + { + /* Thread Mode, check nPRIV */ + int32_t control = __get_CONTROL(); + return control & CONTROL_nPRIV_Msk ? APP_LEVEL_UNPRIVILEGED : APP_LEVEL_PRIVILEGED; + } + else + { + /* Handler Mode, always privileged */ + return APP_LEVEL_PRIVILEGED; + } +#endif +} + + +uint8_t current_int_priority_get(void) +{ + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (isr_vector_num > 0) + { + int32_t irq_type = ((int32_t)isr_vector_num - EXTERNAL_INT_VECTOR_OFFSET); + return (NVIC_GetPriority((IRQn_Type)irq_type) & 0xFF); + } + else + { + return APP_IRQ_PRIORITY_THREAD; + } +} diff --git a/third_party/NordicSemiconductor/dependencies/app_util_platform.h b/third_party/NordicSemiconductor/dependencies/app_util_platform.h index 0b9896e91..263258a8b 100644 --- a/third_party/NordicSemiconductor/dependencies/app_util_platform.h +++ b/third_party/NordicSemiconductor/dependencies/app_util_platform.h @@ -1,279 +1,279 @@ -/** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup app_util_platform Utility Functions and Definitions (Platform) - * @{ - * @ingroup app_common - * - * @brief Various types and definitions available to all applications when using SoftDevice. - */ - -#ifndef APP_UTIL_PLATFORM_H__ -#define APP_UTIL_PLATFORM_H__ - -#include -#include "compiler_abstraction.h" -#include "nrf.h" -#ifdef SOFTDEVICE_PRESENT -#include "nrf_soc.h" -#include "nrf_nvic.h" -#endif -#include "nrf_assert.h" -#include "app_error.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if __CORTEX_M == (0x00U) -#define _PRIO_SD_HIGH 0 -#define _PRIO_APP_HIGH 1 -#define _PRIO_APP_MID 1 -#define _PRIO_SD_LOW 2 -#define _PRIO_APP_LOW 3 -#define _PRIO_APP_LOWEST 3 -#define _PRIO_THREAD 4 -#elif __CORTEX_M == (0x04U) -#define _PRIO_SD_HIGH 0 -#define _PRIO_SD_MID 1 -#define _PRIO_APP_HIGH 2 -#define _PRIO_APP_MID 3 -#define _PRIO_SD_LOW 4 -#define _PRIO_SD_LOWEST 5 -#define _PRIO_APP_LOW 6 -#define _PRIO_APP_LOWEST 7 -#define _PRIO_THREAD 15 -#else - #error "No platform defined" -#endif - - -//lint -save -e113 -e452 -/**@brief The interrupt priorities available to the application while the SoftDevice is active. */ -typedef enum -{ -#ifndef SOFTDEVICE_PRESENT - APP_IRQ_PRIORITY_HIGHEST = _PRIO_SD_HIGH, -#else - APP_IRQ_PRIORITY_HIGHEST = _PRIO_APP_HIGH, -#endif - APP_IRQ_PRIORITY_HIGH = _PRIO_APP_HIGH, -#ifndef SOFTDEVICE_PRESENT - APP_IRQ_PRIORITY_MID = _PRIO_SD_LOW, -#else - APP_IRQ_PRIORITY_MID = _PRIO_APP_MID, -#endif - APP_IRQ_PRIORITY_LOW = _PRIO_APP_LOW, - APP_IRQ_PRIORITY_LOWEST = _PRIO_APP_LOWEST, - APP_IRQ_PRIORITY_THREAD = _PRIO_THREAD /**< "Interrupt level" when running in Thread Mode. */ -} app_irq_priority_t; -//lint -restore - - -/*@brief The privilege levels available to applications in Thread Mode */ -typedef enum -{ - APP_LEVEL_UNPRIVILEGED, - APP_LEVEL_PRIVILEGED -} app_level_t; - -/**@cond NO_DOXYGEN */ -#define EXTERNAL_INT_VECTOR_OFFSET 16 -/**@endcond */ - -/**@brief Macro for setting a breakpoint. - */ -#if defined(__GNUC__) -#define NRF_BREAKPOINT __asm__("BKPT 0"); -#else -#define NRF_BREAKPOINT __BKPT(0) -#endif - -/** @brief Macro for setting a breakpoint. - * - * If it is possible to detect debugger presence then it is set only in that case. - * - */ -#if __CORTEX_M == 0x04 -#define NRF_BREAKPOINT_COND do { \ - /* C_DEBUGEN == 1 -> Debugger Connected */ \ - if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) \ - { \ - /* Generate breakpoint if debugger is connected */ \ - NRF_BREAKPOINT; \ - } \ - }while (0) -#else -#define NRF_BREAKPOINT_COND NRF_BREAKPOINT -#endif // __CORTEX_M == 0x04 - -#if defined ( __CC_ARM ) -#define PACKED(TYPE) __packed TYPE -#define PACKED_STRUCT PACKED(struct) -#elif defined ( __GNUC__ ) -#define PACKED __attribute__((packed)) -#define PACKED_STRUCT struct PACKED -#elif defined (__ICCARM__) -#define PACKED_STRUCT __packed struct -#endif - -#if defined ( __CC_ARM ) -#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("push") \ - _Pragma ("O3") -#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("pop") -#elif defined ( __GNUC__ ) -#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma("GCC push_options") \ - _Pragma ("GCC optimize (\"Os\")") -#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("GCC pop_options") -#elif defined (__ICCARM__) -#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("optimize=high z") -#define PRAGMA_OPTIMIZATION_FORCE_END -#endif - - -void app_util_critical_region_enter (uint8_t *p_nested); -void app_util_critical_region_exit (uint8_t nested); - -/**@brief Macro for entering a critical region. - * - * @note Due to implementation details, there must exist one and only one call to - * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located - * in the same scope. - */ -#ifdef SOFTDEVICE_PRESENT -#define CRITICAL_REGION_ENTER() \ - { \ - uint8_t __CR_NESTED = 0; \ - app_util_critical_region_enter(&__CR_NESTED); -#else -#define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL) -#endif - -/**@brief Macro for leaving a critical region. - * - * @note Due to implementation details, there must exist one and only one call to - * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located - * in the same scope. - */ -#ifdef SOFTDEVICE_PRESENT -#define CRITICAL_REGION_EXIT() \ - app_util_critical_region_exit(__CR_NESTED); \ - } -#else -#define CRITICAL_REGION_EXIT() app_util_critical_region_exit(0) -#endif - -/* Workaround for Keil 4 */ -#ifndef IPSR_ISR_Msk -#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ -#endif - - - -/**@brief Macro to enable anonymous unions from a certain point in the code. - */ -#if defined(__CC_ARM) - #define ANON_UNIONS_ENABLE _Pragma("push") \ - _Pragma("anon_unions") \ - struct semicolon_swallower -#elif defined(__ICCARM__) - #define ANON_UNIONS_ENABLE _Pragma("language=extended") \ - struct semicolon_swallower -#else - #define ANON_UNIONS_ENABLE struct semicolon_swallower - // No action will be taken. - // For GCC anonymous unions are enabled by default. -#endif - -/**@brief Macro to disable anonymous unions from a certain point in the code. - * @note Call only after first calling @ref ANON_UNIONS_ENABLE. - */ -#if defined(__CC_ARM) - #define ANON_UNIONS_DISABLE _Pragma("pop") \ - struct semicolon_swallower -#elif defined(__ICCARM__) - #define ANON_UNIONS_DISABLE struct semicolon_swallower - // for IAR leave anonymous unions enabled -#else - #define ANON_UNIONS_DISABLE struct semicolon_swallower - // No action will be taken. - // For GCC anonymous unions are enabled by default. -#endif - -/**@brief Macro for adding pragma directive only for GCC. - */ -#ifdef __GNUC__ -#define GCC_PRAGMA(v) _Pragma(v) -#else -#define GCC_PRAGMA(v) -#endif - -/* Workaround for Keil 4 */ -#ifndef CONTROL_nPRIV_Msk -#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ -#endif - -/**@brief Function for finding the current interrupt level. - * - * @return Current interrupt level. - * @retval APP_IRQ_PRIORITY_HIGH We are running in Application High interrupt level. - * @retval APP_IRQ_PRIORITY_LOW We are running in Application Low interrupt level. - * @retval APP_IRQ_PRIORITY_THREAD We are running in Thread Mode. - */ -uint8_t current_int_priority_get(void); - - -/**@brief Function for finding out the current privilege level. - * - * @return Current privilege level. - * @retval APP_LEVEL_UNPRIVILEGED We are running in unprivileged level. - * @retval APP_LEVEL_PRIVILEGED We are running in privileged level. - */ -uint8_t privilege_level_get(void); - - -#ifdef __cplusplus -} -#endif - -#endif // APP_UTIL_PLATFORM_H__ - -/** @} */ +/** + * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup app_util_platform Utility Functions and Definitions (Platform) + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications when using SoftDevice. + */ + +#ifndef APP_UTIL_PLATFORM_H__ +#define APP_UTIL_PLATFORM_H__ + +#include +#include "compiler_abstraction.h" +#include "nrf.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#include "nrf_nvic.h" +#endif +#include "nrf_assert.h" +#include "app_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if __CORTEX_M == (0x00U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_APP_HIGH 1 +#define _PRIO_APP_MID 1 +#define _PRIO_SD_LOW 2 +#define _PRIO_APP_LOW 3 +#define _PRIO_APP_LOWEST 3 +#define _PRIO_THREAD 4 +#elif __CORTEX_M == (0x04U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_SD_MID 1 +#define _PRIO_APP_HIGH 2 +#define _PRIO_APP_MID 3 +#define _PRIO_SD_LOW 4 +#define _PRIO_SD_LOWEST 5 +#define _PRIO_APP_LOW 6 +#define _PRIO_APP_LOWEST 7 +#define _PRIO_THREAD 15 +#else + #error "No platform defined" +#endif + + +//lint -save -e113 -e452 +/**@brief The interrupt priorities available to the application while the SoftDevice is active. */ +typedef enum +{ +#ifndef SOFTDEVICE_PRESENT + APP_IRQ_PRIORITY_HIGHEST = _PRIO_SD_HIGH, +#else + APP_IRQ_PRIORITY_HIGHEST = _PRIO_APP_HIGH, +#endif + APP_IRQ_PRIORITY_HIGH = _PRIO_APP_HIGH, +#ifndef SOFTDEVICE_PRESENT + APP_IRQ_PRIORITY_MID = _PRIO_SD_LOW, +#else + APP_IRQ_PRIORITY_MID = _PRIO_APP_MID, +#endif + APP_IRQ_PRIORITY_LOW = _PRIO_APP_LOW, + APP_IRQ_PRIORITY_LOWEST = _PRIO_APP_LOWEST, + APP_IRQ_PRIORITY_THREAD = _PRIO_THREAD /**< "Interrupt level" when running in Thread Mode. */ +} app_irq_priority_t; +//lint -restore + + +/*@brief The privilege levels available to applications in Thread Mode */ +typedef enum +{ + APP_LEVEL_UNPRIVILEGED, + APP_LEVEL_PRIVILEGED +} app_level_t; + +/**@cond NO_DOXYGEN */ +#define EXTERNAL_INT_VECTOR_OFFSET 16 +/**@endcond */ + +/**@brief Macro for setting a breakpoint. + */ +#if defined(__GNUC__) +#define NRF_BREAKPOINT __asm__("BKPT 0"); +#else +#define NRF_BREAKPOINT __BKPT(0) +#endif + +/** @brief Macro for setting a breakpoint. + * + * If it is possible to detect debugger presence then it is set only in that case. + * + */ +#if __CORTEX_M == 0x04 +#define NRF_BREAKPOINT_COND do { \ + /* C_DEBUGEN == 1 -> Debugger Connected */ \ + if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) \ + { \ + /* Generate breakpoint if debugger is connected */ \ + NRF_BREAKPOINT; \ + } \ + }while (0) +#else +#define NRF_BREAKPOINT_COND NRF_BREAKPOINT +#endif // __CORTEX_M == 0x04 + +#if defined ( __CC_ARM ) +#define PACKED(TYPE) __packed TYPE +#define PACKED_STRUCT PACKED(struct) +#elif defined ( __GNUC__ ) +#define PACKED __attribute__((packed)) +#define PACKED_STRUCT struct PACKED +#elif defined (__ICCARM__) +#define PACKED_STRUCT __packed struct +#endif + +#if defined ( __CC_ARM ) +#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("push") \ + _Pragma ("O3") +#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("pop") +#elif defined ( __GNUC__ ) +#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma("GCC push_options") \ + _Pragma ("GCC optimize (\"Os\")") +#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("GCC pop_options") +#elif defined (__ICCARM__) +#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("optimize=high z") +#define PRAGMA_OPTIMIZATION_FORCE_END +#endif + + +void app_util_critical_region_enter (uint8_t *p_nested); +void app_util_critical_region_exit (uint8_t nested); + +/**@brief Macro for entering a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +#ifdef SOFTDEVICE_PRESENT +#define CRITICAL_REGION_ENTER() \ + { \ + uint8_t __CR_NESTED = 0; \ + app_util_critical_region_enter(&__CR_NESTED); +#else +#define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL) +#endif + +/**@brief Macro for leaving a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +#ifdef SOFTDEVICE_PRESENT +#define CRITICAL_REGION_EXIT() \ + app_util_critical_region_exit(__CR_NESTED); \ + } +#else +#define CRITICAL_REGION_EXIT() app_util_critical_region_exit(0) +#endif + +/* Workaround for Keil 4 */ +#ifndef IPSR_ISR_Msk +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ +#endif + + + +/**@brief Macro to enable anonymous unions from a certain point in the code. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_ENABLE _Pragma("push") \ + _Pragma("anon_unions") \ + struct semicolon_swallower +#elif defined(__ICCARM__) + #define ANON_UNIONS_ENABLE _Pragma("language=extended") \ + struct semicolon_swallower +#else + #define ANON_UNIONS_ENABLE struct semicolon_swallower + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro to disable anonymous unions from a certain point in the code. + * @note Call only after first calling @ref ANON_UNIONS_ENABLE. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_DISABLE _Pragma("pop") \ + struct semicolon_swallower +#elif defined(__ICCARM__) + #define ANON_UNIONS_DISABLE struct semicolon_swallower + // for IAR leave anonymous unions enabled +#else + #define ANON_UNIONS_DISABLE struct semicolon_swallower + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro for adding pragma directive only for GCC. + */ +#ifdef __GNUC__ +#define GCC_PRAGMA(v) _Pragma(v) +#else +#define GCC_PRAGMA(v) +#endif + +/* Workaround for Keil 4 */ +#ifndef CONTROL_nPRIV_Msk +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ +#endif + +/**@brief Function for finding the current interrupt level. + * + * @return Current interrupt level. + * @retval APP_IRQ_PRIORITY_HIGH We are running in Application High interrupt level. + * @retval APP_IRQ_PRIORITY_LOW We are running in Application Low interrupt level. + * @retval APP_IRQ_PRIORITY_THREAD We are running in Thread Mode. + */ +uint8_t current_int_priority_get(void); + + +/**@brief Function for finding out the current privilege level. + * + * @return Current privilege level. + * @retval APP_LEVEL_UNPRIVILEGED We are running in unprivileged level. + * @retval APP_LEVEL_PRIVILEGED We are running in privileged level. + */ +uint8_t privilege_level_get(void); + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_PLATFORM_H__ + +/** @} */ diff --git a/third_party/NordicSemiconductor/dependencies/nordic_common.h b/third_party/NordicSemiconductor/dependencies/nordic_common.h index d38719fa3..82884b1fc 100644 --- a/third_party/NordicSemiconductor/dependencies/nordic_common.h +++ b/third_party/NordicSemiconductor/dependencies/nordic_common.h @@ -1,215 +1,215 @@ -/** - * Copyright (c) 2008 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * @brief Common defines and macros for firmware developed by Nordic Semiconductor. - */ - -#ifndef NORDIC_COMMON_H__ -#define NORDIC_COMMON_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Check if selected module is enabled - * - * This is save function for driver enable checking. - * Correct from Lint point of view (not using default of undefined value). - * - * Usage: - * @code - #if NRF_MODULE_ENABLED(UART) - ... - #endif - * @endcode - * - * @param module The module name. - * - * @retval 1 The macro _ENABLE is defined and is non-zero. - * @retval 0 The macro _ENABLE is not defined or it equals zero. - * - * @note - * This macro intentionally does not implement second expansion level. - * The name of the module to be checked has to be given directly as a parameter. - * And given parameter would be connected with @c _ENABLED postfix directly - * without evaluating its value. - */ -//lint -emacro(491,NRF_MODULE_ENABLED) // Suppers warning 491 "non-standard use of 'defined' preprocessor operator" -#ifdef NRF_MODULE_ENABLE_ALL -#warning "Do not use NRF_MODULE_ENABLE_ALL for real builds." -#define NRF_MODULE_ENABLED(module) 1 -#else -#define NRF_MODULE_ENABLED(module) \ - ((defined(module ## _ENABLED) && (module ## _ENABLED)) ? 1 : 0) -#endif -/** The upper 8 bits of a 32 bit value */ -//lint -emacro(572,MSB_32) // Suppress warning 572 "Excessive shift value" -#define MSB_32(a) (((a) & 0xFF000000) >> 24) -/** The lower 8 bits (of a 32 bit value) */ -#define LSB_32(a) ((a) & 0x000000FF) - -/** The upper 8 bits of a 16 bit value */ -//lint -emacro(572,MSB_16) // Suppress warning 572 "Excessive shift value" -#define MSB_16(a) (((a) & 0xFF00) >> 8) -/** The lower 8 bits (of a 16 bit value) */ -#define LSB_16(a) ((a) & 0x00FF) - -/** Leaves the minimum of the two 32-bit arguments */ -/*lint -emacro(506, MIN) */ /* Suppress "Constant value Boolean */ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -/** Leaves the maximum of the two 32-bit arguments */ -/*lint -emacro(506, MAX) */ /* Suppress "Constant value Boolean */ -#define MAX(a, b) ((a) < (b) ? (b) : (a)) - -/**@brief Concatenates two parameters. - * - * It realizes two level expansion to make it sure that all the parameters - * are actually expanded before gluing them together. - * - * @param p1 First parameter to concatenating - * @param p2 Second parameter to concatenating - * - * @return Two parameters glued together. - * They have to create correct C mnemonic in other case - * preprocessor error would be generated. - * - * @sa CONCAT_3 - */ -#define CONCAT_2(p1, p2) CONCAT_2_(p1, p2) -/** Auxiliary macro used by @ref CONCAT_2 */ -#define CONCAT_2_(p1, p2) p1##p2 - -/**@brief Concatenates three parameters. - * - * It realizes two level expansion to make it sure that all the parameters - * are actually expanded before gluing them together. - * - * @param p1 First parameter to concatenating - * @param p2 Second parameter to concatenating - * @param p3 Third parameter to concatenating - * - * @return Three parameters glued together. - * They have to create correct C mnemonic in other case - * preprocessor error would be generated. - * - * @sa CONCAT_2 - */ -#define CONCAT_3(p1, p2, p3) CONCAT_3_(p1, p2, p3) -/** Auxiliary macro used by @ref CONCAT_3 */ -#define CONCAT_3_(p1, p2, p3) p1##p2##p3 - -#define STRINGIFY_(val) #val -/** Converts a macro argument into a character constant. - */ -#define STRINGIFY(val) STRINGIFY_(val) - -/** Counts number of elements inside the array - */ -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -/**@brief Set a bit in the uint32 word. - * - * @param[in] W Word whose bit is being set. - * @param[in] B Bit number in the word to be set. - */ -#define SET_BIT(W, B) ((W) |= (uint32_t)(1U << (B))) - - -/**@brief Clears a bit in the uint32 word. - * - * @param[in] W Word whose bit is to be cleared. - * @param[in] B Bit number in the word to be cleared. - */ -#define CLR_BIT(W, B) ((W) &= (~(uint32_t)(1U << (B)))) - - -/**@brief Checks if a bit is set. - * - * @param[in] W Word whose bit is to be checked. - * @param[in] B Bit number in the word to be checked. - * - * @retval 1 if bit is set. - * @retval 0 if bit is not set. - */ -#define IS_SET(W, B) (((W) >> (B)) & 1) - -#define BIT_0 0x01 /**< The value of bit 0 */ -#define BIT_1 0x02 /**< The value of bit 1 */ -#define BIT_2 0x04 /**< The value of bit 2 */ -#define BIT_3 0x08 /**< The value of bit 3 */ -#define BIT_4 0x10 /**< The value of bit 4 */ -#define BIT_5 0x20 /**< The value of bit 5 */ -#define BIT_6 0x40 /**< The value of bit 6 */ -#define BIT_7 0x80 /**< The value of bit 7 */ -#define BIT_8 0x0100 /**< The value of bit 8 */ -#define BIT_9 0x0200 /**< The value of bit 9 */ -#define BIT_10 0x0400 /**< The value of bit 10 */ -#define BIT_11 0x0800 /**< The value of bit 11 */ -#define BIT_12 0x1000 /**< The value of bit 12 */ -#define BIT_13 0x2000 /**< The value of bit 13 */ -#define BIT_14 0x4000 /**< The value of bit 14 */ -#define BIT_15 0x8000 /**< The value of bit 15 */ -#define BIT_16 0x00010000 /**< The value of bit 16 */ -#define BIT_17 0x00020000 /**< The value of bit 17 */ -#define BIT_18 0x00040000 /**< The value of bit 18 */ -#define BIT_19 0x00080000 /**< The value of bit 19 */ -#define BIT_20 0x00100000 /**< The value of bit 20 */ -#define BIT_21 0x00200000 /**< The value of bit 21 */ -#define BIT_22 0x00400000 /**< The value of bit 22 */ -#define BIT_23 0x00800000 /**< The value of bit 23 */ -#define BIT_24 0x01000000 /**< The value of bit 24 */ -#define BIT_25 0x02000000 /**< The value of bit 25 */ -#define BIT_26 0x04000000 /**< The value of bit 26 */ -#define BIT_27 0x08000000 /**< The value of bit 27 */ -#define BIT_28 0x10000000 /**< The value of bit 28 */ -#define BIT_29 0x20000000 /**< The value of bit 29 */ -#define BIT_30 0x40000000 /**< The value of bit 30 */ -#define BIT_31 0x80000000 /**< The value of bit 31 */ - -#define UNUSED_VARIABLE(X) ((void)(X)) -#define UNUSED_PARAMETER(X) UNUSED_VARIABLE(X) -#define UNUSED_RETURN_VALUE(X) UNUSED_VARIABLE(X) - -#ifdef __cplusplus -} -#endif - -#endif // NORDIC_COMMON_H__ +/** + * Copyright (c) 2008 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * @brief Common defines and macros for firmware developed by Nordic Semiconductor. + */ + +#ifndef NORDIC_COMMON_H__ +#define NORDIC_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Check if selected module is enabled + * + * This is save function for driver enable checking. + * Correct from Lint point of view (not using default of undefined value). + * + * Usage: + * @code + #if NRF_MODULE_ENABLED(UART) + ... + #endif + * @endcode + * + * @param module The module name. + * + * @retval 1 The macro _ENABLE is defined and is non-zero. + * @retval 0 The macro _ENABLE is not defined or it equals zero. + * + * @note + * This macro intentionally does not implement second expansion level. + * The name of the module to be checked has to be given directly as a parameter. + * And given parameter would be connected with @c _ENABLED postfix directly + * without evaluating its value. + */ +//lint -emacro(491,NRF_MODULE_ENABLED) // Suppers warning 491 "non-standard use of 'defined' preprocessor operator" +#ifdef NRF_MODULE_ENABLE_ALL +#warning "Do not use NRF_MODULE_ENABLE_ALL for real builds." +#define NRF_MODULE_ENABLED(module) 1 +#else +#define NRF_MODULE_ENABLED(module) \ + ((defined(module ## _ENABLED) && (module ## _ENABLED)) ? 1 : 0) +#endif +/** The upper 8 bits of a 32 bit value */ +//lint -emacro(572,MSB_32) // Suppress warning 572 "Excessive shift value" +#define MSB_32(a) (((a) & 0xFF000000) >> 24) +/** The lower 8 bits (of a 32 bit value) */ +#define LSB_32(a) ((a) & 0x000000FF) + +/** The upper 8 bits of a 16 bit value */ +//lint -emacro(572,MSB_16) // Suppress warning 572 "Excessive shift value" +#define MSB_16(a) (((a) & 0xFF00) >> 8) +/** The lower 8 bits (of a 16 bit value) */ +#define LSB_16(a) ((a) & 0x00FF) + +/** Leaves the minimum of the two 32-bit arguments */ +/*lint -emacro(506, MIN) */ /* Suppress "Constant value Boolean */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +/** Leaves the maximum of the two 32-bit arguments */ +/*lint -emacro(506, MAX) */ /* Suppress "Constant value Boolean */ +#define MAX(a, b) ((a) < (b) ? (b) : (a)) + +/**@brief Concatenates two parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * + * @return Two parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_3 + */ +#define CONCAT_2(p1, p2) CONCAT_2_(p1, p2) +/** Auxiliary macro used by @ref CONCAT_2 */ +#define CONCAT_2_(p1, p2) p1##p2 + +/**@brief Concatenates three parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * @param p3 Third parameter to concatenating + * + * @return Three parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_2 + */ +#define CONCAT_3(p1, p2, p3) CONCAT_3_(p1, p2, p3) +/** Auxiliary macro used by @ref CONCAT_3 */ +#define CONCAT_3_(p1, p2, p3) p1##p2##p3 + +#define STRINGIFY_(val) #val +/** Converts a macro argument into a character constant. + */ +#define STRINGIFY(val) STRINGIFY_(val) + +/** Counts number of elements inside the array + */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +/**@brief Set a bit in the uint32 word. + * + * @param[in] W Word whose bit is being set. + * @param[in] B Bit number in the word to be set. + */ +#define SET_BIT(W, B) ((W) |= (uint32_t)(1U << (B))) + + +/**@brief Clears a bit in the uint32 word. + * + * @param[in] W Word whose bit is to be cleared. + * @param[in] B Bit number in the word to be cleared. + */ +#define CLR_BIT(W, B) ((W) &= (~(uint32_t)(1U << (B)))) + + +/**@brief Checks if a bit is set. + * + * @param[in] W Word whose bit is to be checked. + * @param[in] B Bit number in the word to be checked. + * + * @retval 1 if bit is set. + * @retval 0 if bit is not set. + */ +#define IS_SET(W, B) (((W) >> (B)) & 1) + +#define BIT_0 0x01 /**< The value of bit 0 */ +#define BIT_1 0x02 /**< The value of bit 1 */ +#define BIT_2 0x04 /**< The value of bit 2 */ +#define BIT_3 0x08 /**< The value of bit 3 */ +#define BIT_4 0x10 /**< The value of bit 4 */ +#define BIT_5 0x20 /**< The value of bit 5 */ +#define BIT_6 0x40 /**< The value of bit 6 */ +#define BIT_7 0x80 /**< The value of bit 7 */ +#define BIT_8 0x0100 /**< The value of bit 8 */ +#define BIT_9 0x0200 /**< The value of bit 9 */ +#define BIT_10 0x0400 /**< The value of bit 10 */ +#define BIT_11 0x0800 /**< The value of bit 11 */ +#define BIT_12 0x1000 /**< The value of bit 12 */ +#define BIT_13 0x2000 /**< The value of bit 13 */ +#define BIT_14 0x4000 /**< The value of bit 14 */ +#define BIT_15 0x8000 /**< The value of bit 15 */ +#define BIT_16 0x00010000 /**< The value of bit 16 */ +#define BIT_17 0x00020000 /**< The value of bit 17 */ +#define BIT_18 0x00040000 /**< The value of bit 18 */ +#define BIT_19 0x00080000 /**< The value of bit 19 */ +#define BIT_20 0x00100000 /**< The value of bit 20 */ +#define BIT_21 0x00200000 /**< The value of bit 21 */ +#define BIT_22 0x00400000 /**< The value of bit 22 */ +#define BIT_23 0x00800000 /**< The value of bit 23 */ +#define BIT_24 0x01000000 /**< The value of bit 24 */ +#define BIT_25 0x02000000 /**< The value of bit 25 */ +#define BIT_26 0x04000000 /**< The value of bit 26 */ +#define BIT_27 0x08000000 /**< The value of bit 27 */ +#define BIT_28 0x10000000 /**< The value of bit 28 */ +#define BIT_29 0x20000000 /**< The value of bit 29 */ +#define BIT_30 0x40000000 /**< The value of bit 30 */ +#define BIT_31 0x80000000 /**< The value of bit 31 */ + +#define UNUSED_VARIABLE(X) ((void)(X)) +#define UNUSED_PARAMETER(X) UNUSED_VARIABLE(X) +#define UNUSED_RETURN_VALUE(X) UNUSED_VARIABLE(X) + +#ifdef __cplusplus +} +#endif + +#endif // NORDIC_COMMON_H__ diff --git a/third_party/NordicSemiconductor/dependencies/nrf_assert.h b/third_party/NordicSemiconductor/dependencies/nrf_assert.h index d46a092d8..438ab95d8 100644 --- a/third_party/NordicSemiconductor/dependencies/nrf_assert.h +++ b/third_party/NordicSemiconductor/dependencies/nrf_assert.h @@ -1,122 +1,122 @@ -/** - * Copyright (c) 2006 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * @brief Utilities for verifying program logic - */ - -#ifndef NRF_ASSERT_H_ -#define NRF_ASSERT_H_ - -#include -#include "nrf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief Function for handling assertions. - * - * - * @note - * This function is called when an assertion has triggered. - * - * @note - * This function is deprecated and will be removed in future releases. - * Use app_error_fault_handler instead. - * - * - * @post - * All hardware is put into an idle non-emitting state (in particular the radio is highly - * important to switch off since the radio might be in a state that makes it send - * packets continiously while a typical final infinit ASSERT loop is executing). - * - * - * @param line_num The line number where the assertion is called - * @param file_name Pointer to the file name - */ -//lint -save -esym(14, assert_nrf_callback) -void assert_nrf_callback(uint16_t line_num, const uint8_t *file_name); -//lint -restore - -#if (defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)) -#define NRF_ASSERT_PRESENT 1 -#else -#define NRF_ASSERT_PRESENT 0 -#endif - -//#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER) - -/*lint -emacro(506, ASSERT) */ /* Suppress "Constant value Boolean */ -/*lint -emacro(774, ASSERT) */ /* Suppress "Boolean within 'if' always evaluates to True" */ \ - -/** @brief Function for checking intended for production code. - * - * Check passes if "expr" evaluates to true. */ - -#ifdef _lint -#define ASSERT(expr) \ -if (expr) \ -{ \ -} \ -else \ -{ \ - while (1); \ -} -#else //_lint -#define ASSERT(expr) \ -if (NRF_ASSERT_PRESENT) \ -{ \ - if (expr) \ - { \ - } \ - else \ - { \ - assert_nrf_callback((uint16_t)__LINE__, (uint8_t *)__FILE__); \ - } \ -} - -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* NRF_ASSERT_H_ */ +/** + * Copyright (c) 2006 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * @brief Utilities for verifying program logic + */ + +#ifndef NRF_ASSERT_H_ +#define NRF_ASSERT_H_ + +#include +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Function for handling assertions. + * + * + * @note + * This function is called when an assertion has triggered. + * + * @note + * This function is deprecated and will be removed in future releases. + * Use app_error_fault_handler instead. + * + * + * @post + * All hardware is put into an idle non-emitting state (in particular the radio is highly + * important to switch off since the radio might be in a state that makes it send + * packets continiously while a typical final infinit ASSERT loop is executing). + * + * + * @param line_num The line number where the assertion is called + * @param file_name Pointer to the file name + */ +//lint -save -esym(14, assert_nrf_callback) +void assert_nrf_callback(uint16_t line_num, const uint8_t *file_name); +//lint -restore + +#if (defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)) +#define NRF_ASSERT_PRESENT 1 +#else +#define NRF_ASSERT_PRESENT 0 +#endif + +//#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER) + +/*lint -emacro(506, ASSERT) */ /* Suppress "Constant value Boolean */ +/*lint -emacro(774, ASSERT) */ /* Suppress "Boolean within 'if' always evaluates to True" */ \ + +/** @brief Function for checking intended for production code. + * + * Check passes if "expr" evaluates to true. */ + +#ifdef _lint +#define ASSERT(expr) \ +if (expr) \ +{ \ +} \ +else \ +{ \ + while (1); \ +} +#else //_lint +#define ASSERT(expr) \ +if (NRF_ASSERT_PRESENT) \ +{ \ + if (expr) \ + { \ + } \ + else \ + { \ + assert_nrf_callback((uint16_t)__LINE__, (uint8_t *)__FILE__); \ + } \ +} + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ASSERT_H_ */ diff --git a/third_party/NordicSemiconductor/dependencies/nrf_error.h b/third_party/NordicSemiconductor/dependencies/nrf_error.h index e97fa069d..c673beb10 100644 --- a/third_party/NordicSemiconductor/dependencies/nrf_error.h +++ b/third_party/NordicSemiconductor/dependencies/nrf_error.h @@ -1,95 +1,95 @@ -/** - * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Header guard */ - -#ifndef SOFTDEVICE_PRESENT - -/** - @defgroup nrf_error Global Error Codes - @{ - - @brief Global Error definitions -*/ - -#ifndef NRF_ERROR_H__ -#define NRF_ERROR_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** @defgroup NRF_ERRORS_BASE Error Codes Base number definitions - * @{ */ -#define NRF_ERROR_BASE_NUM (0x0) ///< Global error base -#define NRF_ERROR_SDM_BASE_NUM (0x1000) ///< SDM error base -#define NRF_ERROR_SOC_BASE_NUM (0x2000) ///< SoC error base -#define NRF_ERROR_STK_BASE_NUM (0x3000) ///< STK error base -/** @} */ - -#define NRF_SUCCESS (NRF_ERROR_BASE_NUM + 0) ///< Successful command -#define NRF_ERROR_SVC_HANDLER_MISSING (NRF_ERROR_BASE_NUM + 1) ///< SVC handler is missing -#define NRF_ERROR_SOFTDEVICE_NOT_ENABLED (NRF_ERROR_BASE_NUM + 2) ///< SoftDevice has not been enabled -#define NRF_ERROR_INTERNAL (NRF_ERROR_BASE_NUM + 3) ///< Internal Error -#define NRF_ERROR_NO_MEM (NRF_ERROR_BASE_NUM + 4) ///< No Memory for operation -#define NRF_ERROR_NOT_FOUND (NRF_ERROR_BASE_NUM + 5) ///< Not found -#define NRF_ERROR_NOT_SUPPORTED (NRF_ERROR_BASE_NUM + 6) ///< Not supported -#define NRF_ERROR_INVALID_PARAM (NRF_ERROR_BASE_NUM + 7) ///< Invalid Parameter -#define NRF_ERROR_INVALID_STATE (NRF_ERROR_BASE_NUM + 8) ///< Invalid state, operation disallowed in this state -#define NRF_ERROR_INVALID_LENGTH (NRF_ERROR_BASE_NUM + 9) ///< Invalid Length -#define NRF_ERROR_INVALID_FLAGS (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags -#define NRF_ERROR_INVALID_DATA (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data -#define NRF_ERROR_DATA_SIZE (NRF_ERROR_BASE_NUM + 12) ///< Data size exceeds limit -#define NRF_ERROR_TIMEOUT (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out -#define NRF_ERROR_NULL (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer -#define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation -#define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address -#define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy - -#ifdef __cplusplus -} -#endif - -#endif // NRF_ERROR_H__ - -/** - @} -*/ - -#endif // SOFTDEVICE_PRESENT +/** + * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Header guard */ + +#ifndef SOFTDEVICE_PRESENT + +/** + @defgroup nrf_error Global Error Codes + @{ + + @brief Global Error definitions +*/ + +#ifndef NRF_ERROR_H__ +#define NRF_ERROR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup NRF_ERRORS_BASE Error Codes Base number definitions + * @{ */ +#define NRF_ERROR_BASE_NUM (0x0) ///< Global error base +#define NRF_ERROR_SDM_BASE_NUM (0x1000) ///< SDM error base +#define NRF_ERROR_SOC_BASE_NUM (0x2000) ///< SoC error base +#define NRF_ERROR_STK_BASE_NUM (0x3000) ///< STK error base +/** @} */ + +#define NRF_SUCCESS (NRF_ERROR_BASE_NUM + 0) ///< Successful command +#define NRF_ERROR_SVC_HANDLER_MISSING (NRF_ERROR_BASE_NUM + 1) ///< SVC handler is missing +#define NRF_ERROR_SOFTDEVICE_NOT_ENABLED (NRF_ERROR_BASE_NUM + 2) ///< SoftDevice has not been enabled +#define NRF_ERROR_INTERNAL (NRF_ERROR_BASE_NUM + 3) ///< Internal Error +#define NRF_ERROR_NO_MEM (NRF_ERROR_BASE_NUM + 4) ///< No Memory for operation +#define NRF_ERROR_NOT_FOUND (NRF_ERROR_BASE_NUM + 5) ///< Not found +#define NRF_ERROR_NOT_SUPPORTED (NRF_ERROR_BASE_NUM + 6) ///< Not supported +#define NRF_ERROR_INVALID_PARAM (NRF_ERROR_BASE_NUM + 7) ///< Invalid Parameter +#define NRF_ERROR_INVALID_STATE (NRF_ERROR_BASE_NUM + 8) ///< Invalid state, operation disallowed in this state +#define NRF_ERROR_INVALID_LENGTH (NRF_ERROR_BASE_NUM + 9) ///< Invalid Length +#define NRF_ERROR_INVALID_FLAGS (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags +#define NRF_ERROR_INVALID_DATA (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data +#define NRF_ERROR_DATA_SIZE (NRF_ERROR_BASE_NUM + 12) ///< Data size exceeds limit +#define NRF_ERROR_TIMEOUT (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out +#define NRF_ERROR_NULL (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer +#define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation +#define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address +#define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy + +#ifdef __cplusplus +} +#endif + +#endif // NRF_ERROR_H__ + +/** + @} +*/ + +#endif // SOFTDEVICE_PRESENT diff --git a/third_party/NordicSemiconductor/dependencies/nrf_log.h b/third_party/NordicSemiconductor/dependencies/nrf_log.h index 870f6ec7e..d709d23f7 100644 --- a/third_party/NordicSemiconductor/dependencies/nrf_log.h +++ b/third_party/NordicSemiconductor/dependencies/nrf_log.h @@ -1,291 +1,291 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup nrf_log Logger module - * @{ - * @ingroup app_common - * - * @brief The nrf_log module interface. - */ - -#ifndef NRF_LOG_H_ -#define NRF_LOG_H_ - -#include "sdk_common.h" -#include "nrf_section.h" -#if NRF_MODULE_ENABLED(NRF_LOG) -#include "nrf_strerror.h" -#define NRF_LOG_ERROR_STRING_GET(code) nrf_strerror_get(code) -#else -#define NRF_LOG_ERROR_STRING_GET(code) "" -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief Severity level for the module. - * - * The severity level can be defined in a module to override the default. - */ -#ifndef NRF_LOG_LEVEL - #define NRF_LOG_LEVEL NRF_LOG_DEFAULT_LEVEL -#endif - -/** @brief Initial severity if filtering is enabled. - */ -#ifndef NRF_LOG_INITIAL_LEVEL - #define NRF_LOG_INITIAL_LEVEL NRF_LOG_LEVEL -#endif - - -#include "nrf_log_internal.h" - -/** @def NRF_LOG_ERROR - * @brief Macro for logging error messages. It takes a printf-like, formatted - * string with up to seven arguments. - * - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - */ - -/** @def NRF_LOG_WARNING - * @brief Macro for logging error messages. It takes a printf-like, formatted - * string with up to seven arguments. - * - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. - */ - -/** @def NRF_LOG_INFO - * @brief Macro for logging error messages. It takes a printf-like, formatted - * string with up to seven arguments. - * - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. - */ - -/** @def NRF_LOG_DEBUG - * @brief Macro for logging error messages. It takes a printf-like, formatted - * string with up to seven arguments. - * - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. - */ - -#define NRF_LOG_ERROR(...) NRF_LOG_INTERNAL_ERROR(__VA_ARGS__) -#define NRF_LOG_WARNING(...) NRF_LOG_INTERNAL_WARNING( __VA_ARGS__) -#define NRF_LOG_INFO(...) NRF_LOG_INTERNAL_INFO( __VA_ARGS__) -#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__) - -/** @def NRF_LOG_INST_ERROR - * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted - * string with up to seven arguments. - * - * @param p_inst Pointer to the instance with logging support. - * - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - */ - -/** @def NRF_LOG_INST_WARNING - * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted - * string with up to seven arguments. - * - * @param p_inst Pointer to the instance with logging support. - * - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - */ - -/** @def NRF_LOG_INST_INFO - * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted - * string with up to seven arguments. - * - * @param p_inst Pointer to the instance with logging support. - * - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - */ - -/** @def NRF_LOG_INST_DEBUG - * @brief Macro for logging error messages for given module instance. It takes a printf-like, formatted - * string with up to seven arguments. - * - * @param p_inst Pointer to the instance with logging support. - * - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - */ -#define NRF_LOG_INST_ERROR(p_inst,...) NRF_LOG_INTERNAL_INST_ERROR(p_inst,__VA_ARGS__) -#define NRF_LOG_INST_WARNING(p_inst,...) NRF_LOG_INTERNAL_INST_WARNING(p_inst,__VA_ARGS__) -#define NRF_LOG_INST_INFO(p_inst,...) NRF_LOG_INTERNAL_INST_INFO(p_inst, __VA_ARGS__) -#define NRF_LOG_INST_DEBUG(p_inst,...) NRF_LOG_INTERNAL_INST_DEBUG(p_inst, __VA_ARGS__) - -/** - * @brief Macro for logging a formatted string without any prefix or timestamp. - */ -#define NRF_LOG_RAW_INFO(...) NRF_LOG_INTERNAL_RAW_INFO( __VA_ARGS__) - -/** @def NRF_LOG_HEXDUMP_ERROR - * @brief Macro for logging raw bytes. - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - * - * @param p_data Pointer to data. - * @param len Data length in bytes. - */ -/** @def NRF_LOG_HEXDUMP_WARNING - * @brief Macro for logging raw bytes. - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. - * - * @param p_data Pointer to data. - * @param len Data length in bytes. - */ -/** @def NRF_LOG_HEXDUMP_INFO - * @brief Macro for logging raw bytes. - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. - * - * @param p_data Pointer to data. - * @param len Data length in bytes. - */ -/** @def NRF_LOG_HEXDUMP_DEBUG - * @brief Macro for logging raw bytes. - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. - * - * @param p_data Pointer to data. - * @param len Data length in bytes. - */ -#define NRF_LOG_HEXDUMP_ERROR(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) -#define NRF_LOG_HEXDUMP_WARNING(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) -#define NRF_LOG_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) -#define NRF_LOG_HEXDUMP_DEBUG(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) - -/** @def NRF_LOG_HEXDUMP_INST_ERROR - * @brief Macro for logging raw bytes for a specific module instance. - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - * - * @param p_inst Pointer to the instance with logging support. - * @param p_data Pointer to data. - * @param len Data length in bytes. - */ -/** @def NRF_LOG_HEXDUMP_INST_WARNING - * @brief Macro for logging raw bytes for a specific module instance. - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - * - * @param p_inst Pointer to the instance with logging support. - * @param p_data Pointer to data. - * @param len Data length in bytes. - */ -/** @def NRF_LOG_HEXDUMP_INST_INFO - * @brief Macro for logging raw bytes for a specific module instance. - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - * - * @param p_inst Pointer to the instance with logging support. - * @param p_data Pointer to data. - * @param len Data length in bytes. - */ -/** @def NRF_LOG_HEXDUMP_INST_DEBUG - * @brief Macro for logging raw bytes for a specific module instance. - * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. - * - * @param p_inst Pointer to the instance with logging support. - * @param p_data Pointer to data. - * @param len Data length in bytes. - */ -#define NRF_LOG_HEXDUMP_INST_ERROR(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) -#define NRF_LOG_HEXDUMP_INST_WARNING(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) -#define NRF_LOG_HEXDUMP_INST_INFO(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) -#define NRF_LOG_HEXDUMP_INST_DEBUG(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) - -/** - * @brief Macro for logging hexdump without any prefix or timestamp. - */ -#define NRF_LOG_RAW_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) - - -/** - * @brief Macro for copying a string to internal logger buffer if logs are deferred. - * - * @param _str String. - */ -#define NRF_LOG_PUSH(_str) NRF_LOG_INTERNAL_LOG_PUSH(_str) - -/** - * @brief Function for copying a string to the internal logger buffer if logs are deferred. - * - * Use this function to store a string that is volatile (for example allocated - * on stack) or that may change before the deferred logs are processed. Such string is copied - * into the internal logger buffer and is persistent until the log is processed. - * - * @note If the logs are not deferred, then this function returns the input parameter. - * - * @param p_str Pointer to the user string. - * - * @return Address to the location where the string is stored in the internal logger buffer. - */ -uint32_t nrf_log_push(char * const p_str); - -/** - * @brief Macro to be used in a formatted string to a pass float number to the log. - * - * Use this macro in a formatted string instead of the %f specifier together with - * @ref NRF_LOG_FLOAT macro. - * Example: NRF_LOG_INFO("My float number" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(f))) - */ -#define NRF_LOG_FLOAT_MARKER "%s%d.%02d" - -/** - * @brief Macro for dissecting a float number into two numbers (integer and residuum). - */ -#define NRF_LOG_FLOAT(val) (uint32_t)(((val) < 0 && (val) > -1.0) ? "-" : ""), \ - (int32_t)(val), \ - (int32_t)((((val) > 0) ? (val) - (int32_t)(val) \ - : (int32_t)(val) - (val))*100) - - -/** - * @brief Macro for registering an independent module. - * - * Registration creates set of dynamic (RAM) and constant variables associated with the module. - */ -#define NRF_LOG_MODULE_REGISTER() NRF_LOG_INTERNAL_MODULE_REGISTER() - - -#ifdef __cplusplus -} -#endif - -#endif // NRF_LOG_H_ - -/** @} */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_log Logger module + * @{ + * @ingroup app_common + * + * @brief The nrf_log module interface. + */ + +#ifndef NRF_LOG_H_ +#define NRF_LOG_H_ + +#include "sdk_common.h" +#include "nrf_section.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_strerror.h" +#define NRF_LOG_ERROR_STRING_GET(code) nrf_strerror_get(code) +#else +#define NRF_LOG_ERROR_STRING_GET(code) "" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Severity level for the module. + * + * The severity level can be defined in a module to override the default. + */ +#ifndef NRF_LOG_LEVEL + #define NRF_LOG_LEVEL NRF_LOG_DEFAULT_LEVEL +#endif + +/** @brief Initial severity if filtering is enabled. + */ +#ifndef NRF_LOG_INITIAL_LEVEL + #define NRF_LOG_INITIAL_LEVEL NRF_LOG_LEVEL +#endif + + +#include "nrf_log_internal.h" + +/** @def NRF_LOG_ERROR + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_WARNING + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + */ + +/** @def NRF_LOG_INFO + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + */ + +/** @def NRF_LOG_DEBUG + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + */ + +#define NRF_LOG_ERROR(...) NRF_LOG_INTERNAL_ERROR(__VA_ARGS__) +#define NRF_LOG_WARNING(...) NRF_LOG_INTERNAL_WARNING( __VA_ARGS__) +#define NRF_LOG_INFO(...) NRF_LOG_INTERNAL_INFO( __VA_ARGS__) +#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__) + +/** @def NRF_LOG_INST_ERROR + * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_INST_WARNING + * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_INST_INFO + * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_INST_DEBUG + * @brief Macro for logging error messages for given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ +#define NRF_LOG_INST_ERROR(p_inst,...) NRF_LOG_INTERNAL_INST_ERROR(p_inst,__VA_ARGS__) +#define NRF_LOG_INST_WARNING(p_inst,...) NRF_LOG_INTERNAL_INST_WARNING(p_inst,__VA_ARGS__) +#define NRF_LOG_INST_INFO(p_inst,...) NRF_LOG_INTERNAL_INST_INFO(p_inst, __VA_ARGS__) +#define NRF_LOG_INST_DEBUG(p_inst,...) NRF_LOG_INTERNAL_INST_DEBUG(p_inst, __VA_ARGS__) + +/** + * @brief Macro for logging a formatted string without any prefix or timestamp. + */ +#define NRF_LOG_RAW_INFO(...) NRF_LOG_INTERNAL_RAW_INFO( __VA_ARGS__) + +/** @def NRF_LOG_HEXDUMP_ERROR + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_WARNING + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INFO + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_DEBUG + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +#define NRF_LOG_HEXDUMP_ERROR(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) +#define NRF_LOG_HEXDUMP_WARNING(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) +#define NRF_LOG_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) +#define NRF_LOG_HEXDUMP_DEBUG(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) + +/** @def NRF_LOG_HEXDUMP_INST_ERROR + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INST_WARNING + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INST_INFO + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INST_DEBUG + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +#define NRF_LOG_HEXDUMP_INST_ERROR(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) +#define NRF_LOG_HEXDUMP_INST_WARNING(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) +#define NRF_LOG_HEXDUMP_INST_INFO(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) +#define NRF_LOG_HEXDUMP_INST_DEBUG(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) + +/** + * @brief Macro for logging hexdump without any prefix or timestamp. + */ +#define NRF_LOG_RAW_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) + + +/** + * @brief Macro for copying a string to internal logger buffer if logs are deferred. + * + * @param _str String. + */ +#define NRF_LOG_PUSH(_str) NRF_LOG_INTERNAL_LOG_PUSH(_str) + +/** + * @brief Function for copying a string to the internal logger buffer if logs are deferred. + * + * Use this function to store a string that is volatile (for example allocated + * on stack) or that may change before the deferred logs are processed. Such string is copied + * into the internal logger buffer and is persistent until the log is processed. + * + * @note If the logs are not deferred, then this function returns the input parameter. + * + * @param p_str Pointer to the user string. + * + * @return Address to the location where the string is stored in the internal logger buffer. + */ +uint32_t nrf_log_push(char * const p_str); + +/** + * @brief Macro to be used in a formatted string to a pass float number to the log. + * + * Use this macro in a formatted string instead of the %f specifier together with + * @ref NRF_LOG_FLOAT macro. + * Example: NRF_LOG_INFO("My float number" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(f))) + */ +#define NRF_LOG_FLOAT_MARKER "%s%d.%02d" + +/** + * @brief Macro for dissecting a float number into two numbers (integer and residuum). + */ +#define NRF_LOG_FLOAT(val) (uint32_t)(((val) < 0 && (val) > -1.0) ? "-" : ""), \ + (int32_t)(val), \ + (int32_t)((((val) > 0) ? (val) - (int32_t)(val) \ + : (int32_t)(val) - (val))*100) + + +/** + * @brief Macro for registering an independent module. + * + * Registration creates set of dynamic (RAM) and constant variables associated with the module. + */ +#define NRF_LOG_MODULE_REGISTER() NRF_LOG_INTERNAL_MODULE_REGISTER() + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_LOG_H_ + +/** @} */ diff --git a/third_party/NordicSemiconductor/dependencies/nrf_log_internal.h b/third_party/NordicSemiconductor/dependencies/nrf_log_internal.h index 9250426bf..1f74a7eac 100644 --- a/third_party/NordicSemiconductor/dependencies/nrf_log_internal.h +++ b/third_party/NordicSemiconductor/dependencies/nrf_log_internal.h @@ -1,528 +1,528 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef NRF_LOG_INTERNAL_H__ -#define NRF_LOG_INTERNAL_H__ -#include "sdk_common.h" -#include "nrf.h" -#include "nrf_error.h" -#include "app_util.h" -#include -#include -#include "nrf_log_instance.h" -#include "nrf_log_types.h" - -#ifndef NRF_LOG_ERROR_COLOR - #define NRF_LOG_ERROR_COLOR NRF_LOG_COLOR_DEFAULT -#endif - -#ifndef NRF_LOG_WARNING_COLOR - #define NRF_LOG_WARNING_COLOR NRF_LOG_COLOR_DEFAULT -#endif - -#ifndef NRF_LOG_INFO_COLOR - #define NRF_LOG_INFO_COLOR NRF_LOG_COLOR_DEFAULT -#endif - -#ifndef NRF_LOG_DEBUG_COLOR - #define NRF_LOG_DEBUG_COLOR NRF_LOG_COLOR_DEFAULT -#endif - - -#ifndef NRF_LOG_COLOR_DEFAULT -#define NRF_LOG_COLOR_DEFAULT 0 -#endif - -#ifndef NRF_LOG_DEFAULT_LEVEL -#define NRF_LOG_DEFAULT_LEVEL 0 -#endif - -#ifndef NRF_LOG_USES_COLORS -#define NRF_LOG_USES_COLORS 0 -#endif - -#ifndef NRF_LOG_USES_TIMESTAMP -#define NRF_LOG_USES_TIMESTAMP 0 -#endif - -#ifndef NRF_LOG_FILTERS_ENABLED -#define NRF_LOG_FILTERS_ENABLED 0 -#endif - -#ifndef NRF_LOG_MODULE_NAME - #define NRF_LOG_MODULE_NAME app -#endif - -#define NRF_LOG_LEVEL_BITS 3 -#define NRF_LOG_LEVEL_MASK ((1UL << NRF_LOG_LEVEL_BITS) - 1) -#define NRF_LOG_MODULE_ID_BITS 16 -#define NRF_LOG_MODULE_ID_POS 16 - - -#define NRF_LOG_MAX_NUM_OF_ARGS 6 - - -#if NRF_LOG_FILTERS_ENABLED && NRF_LOG_ENABLED - #define NRF_LOG_FILTER NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).filter - #define NRF_LOG_INST_FILTER(p_inst) (p_inst)->filter -#else - #undef NRF_LOG_FILTER - #define NRF_LOG_FILTER NRF_LOG_SEVERITY_DEBUG - #define NRF_LOG_INST_FILTER(p_inst) NRF_LOG_SEVERITY_DEBUG -#endif - -#if NRF_LOG_ENABLED -#define NRF_LOG_MODULE_ID NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).module_id -#define NRF_LOG_INST_ID(p_inst) (p_inst)->module_id -#else -#define NRF_LOG_MODULE_ID 0 -#define NRF_LOG_INST_ID(p_inst) 0 -#endif - - -#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__) -#define LOG_INTERNAL(type, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \ - __VA_ARGS__), type, __VA_ARGS__) -#if NRF_LOG_ENABLED -#define NRF_LOG_INTERNAL_LOG_PUSH(_str) nrf_log_push(_str) -#define LOG_INTERNAL_0(type, str) \ - nrf_log_frontend_std_0(type, str) -#define LOG_INTERNAL_1(type, str, arg0) \ - /*lint -save -e571*/nrf_log_frontend_std_1(type, str, (uint32_t)(arg0))/*lint -restore*/ -#define LOG_INTERNAL_2(type, str, arg0, arg1) \ - /*lint -save -e571*/nrf_log_frontend_std_2(type, str, (uint32_t)(arg0), \ - (uint32_t)(arg1))/*lint -restore*/ -#define LOG_INTERNAL_3(type, str, arg0, arg1, arg2) \ - /*lint -save -e571*/nrf_log_frontend_std_3(type, str, (uint32_t)(arg0), \ - (uint32_t)(arg1), (uint32_t)(arg2))/*lint -restore*/ -#define LOG_INTERNAL_4(type, str, arg0, arg1, arg2, arg3) \ - /*lint -save -e571*/nrf_log_frontend_std_4(type, str, (uint32_t)(arg0), \ - (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3))/*lint -restore*/ -#define LOG_INTERNAL_5(type, str, arg0, arg1, arg2, arg3, arg4) \ - /*lint -save -e571*/nrf_log_frontend_std_5(type, str, (uint32_t)(arg0), \ - (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4))/*lint -restore*/ -#define LOG_INTERNAL_6(type, str, arg0, arg1, arg2, arg3, arg4, arg5) \ - /*lint -save -e571*/nrf_log_frontend_std_6(type, str, (uint32_t)(arg0), \ - (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4), (uint32_t)(arg5))/*lint -restore*/ - - -#else //NRF_LOG_ENABLED -#define NRF_LOG_INTERNAL_LOG_PUSH(_str) (void)(_str) -#define LOG_INTERNAL_0(_type, _str) \ - (void)(_type); (void)(_str) -#define LOG_INTERNAL_1(_type, _str, _arg0) \ - (void)(_type); (void)(_str); (void)(_arg0) -#define LOG_INTERNAL_2(_type, _str, _arg0, _arg1) \ - (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1) -#define LOG_INTERNAL_3(_type, _str, _arg0, _arg1, _arg2) \ - (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2) -#define LOG_INTERNAL_4(_type, _str, _arg0, _arg1, _arg2, _arg3) \ - (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3) -#define LOG_INTERNAL_5(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4) \ - (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4) -#define LOG_INTERNAL_6(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4, _arg5) \ - (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4); (void)(_arg5) -#endif //NRF_LOG_ENABLED - -#define LOG_SEVERITY_MOD_ID(severity) ((severity) | NRF_LOG_MODULE_ID << NRF_LOG_MODULE_ID_POS) -#define LOG_SEVERITY_INST_ID(severity,p_inst) ((severity) | NRF_LOG_INST_ID(p_inst) << NRF_LOG_MODULE_ID_POS) - -#if NRF_LOG_ENABLED -#define LOG_HEXDUMP(_severity, _p_data, _length) \ - nrf_log_frontend_hexdump((_severity), (_p_data), (_length)) -#else -#define LOG_HEXDUMP(_severity, _p_data, _length) \ - (void)(_severity); (void)(_p_data); (void)_length -#endif - -#define NRF_LOG_INTERNAL_INST(level, level_id, p_inst, ...) \ - if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ - (level <= NRF_LOG_DEFAULT_LEVEL)) \ - { \ - if (NRF_LOG_INST_FILTER(p_inst) >= level) \ - { \ - LOG_INTERNAL(LOG_SEVERITY_INST_ID(level_id, p_inst), __VA_ARGS__); \ - } \ - } - -#define NRF_LOG_INTERNAL_MODULE(level, level_id, ...) \ - if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ - (level <= NRF_LOG_DEFAULT_LEVEL)) \ - { \ - if (NRF_LOG_FILTER >= level) \ - { \ - LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__); \ - } \ - } - -#define NRF_LOG_INTERNAL_HEXDUMP_INST(level, level_id, p_inst, p_data, len) \ - if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ - (level <= NRF_LOG_DEFAULT_LEVEL)) \ - { \ - if (NRF_LOG_INST_FILTER(p_inst) >= level) \ - { \ - LOG_HEXDUMP(LOG_SEVERITY_INST_ID(level_id, p_inst), \ - (p_data), (len)); \ - } \ - } - -#define NRF_LOG_INTERNAL_HEXDUMP_MODULE(level, level_id, p_data, len) \ - if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ - (level <= NRF_LOG_DEFAULT_LEVEL)) \ - { \ - if (NRF_LOG_FILTER >= level) \ - { \ - LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(level_id), \ - (p_data), (len)); \ - } \ - } - -#define NRF_LOG_INTERNAL_INST_ERROR(p_inst, ...) \ - NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, __VA_ARGS__) - -#define NRF_LOG_INTERNAL_ERROR(...) \ - NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR,__VA_ARGS__) - -#define NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) \ - NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, p_data, len) - -#define NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) \ - NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_data, len) - -#define NRF_LOG_INTERNAL_INST_WARNING(p_inst, ...) \ - NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, __VA_ARGS__) - -#define NRF_LOG_INTERNAL_WARNING(...) \ - NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING,__VA_ARGS__) - -#define NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) \ - NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, p_data, len) - -#define NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) \ - NRF_LOG_INTERNAL_HEXDUMP_(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_data, len) - -#define NRF_LOG_INTERNAL_INST_INFO(p_inst, ...) \ - NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, __VA_ARGS__) - -#define NRF_LOG_INTERNAL_INFO(...) \ - NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, __VA_ARGS__) - -#define NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) \ - NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, p_data, len) - -#define NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) \ - NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_data, len) - -#define NRF_LOG_INTERNAL_RAW_INFO(...) \ - NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, __VA_ARGS__) - -#define NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) \ - NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, p_data, len) - -#define NRF_LOG_INTERNAL_INST_DEBUG(p_inst, ...) \ - NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, __VA_ARGS__) - -#define NRF_LOG_INTERNAL_DEBUG(...) \ - NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, __VA_ARGS__) - -#define NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) \ - NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, p_data, len) - -#define NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) \ - NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_data, len) - - -#if NRF_LOG_ENABLED - -#ifdef UNIT_TEST -#define COMPILED_LOG_LEVEL 4 -#else -#define COMPILED_LOG_LEVEL NRF_LOG_LEVEL -#endif - - -#define NRF_LOG_INTERNAL_MODULE_REGISTER() \ - NRF_LOG_INTERNAL_ITEM_REGISTER(NRF_LOG_MODULE_NAME, \ - STRINGIFY(NRF_LOG_MODULE_NAME), \ - NRF_LOG_INFO_COLOR, \ - NRF_LOG_DEBUG_COLOR, \ - NRF_LOG_INITIAL_LEVEL, \ - COMPILED_LOG_LEVEL) - -#else -#define NRF_LOG_INTERNAL_MODULE_REGISTER() /*lint -save -e19*/ /*lint -restore*/ -#endif - -extern NRF_LOG_DYNAMIC_STRUCT_NAME NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME); - -/** - * Set of macros for encoding and decoding header for log entries. - * There are 3 types of entries: - * 1. Standard entry (STD) - * An entry consists of header, pointer to string and values. Header contains - * severity leveland determines number of arguments and thus size of the entry. - * Since flash address space starts from 0x00000000 and is limited to kB rather - * than MB 22 bits are used to store the address (4MB). It is used that way to - * save one RAM memory. - * - * -------------------------------- - * |TYPE|SEVERITY|NARGS| P_STR | - * |------------------------------| - * | Module_ID (optional) | - * |------------------------------| - * | TIMESTAMP (optional) | - * |------------------------------| - * | ARG0 | - * |------------------------------| - * | .... | - * |------------------------------| - * | ARG(nargs-1) | - * -------------------------------- - * - * 2. Hexdump entry (HEXDUMP) is used for dumping raw data. An entry consists of - * header, optional timestamp, pointer to string and data. A header contains - * length (10bit) and offset which is updated after backend processes part of - * data. - * - * -------------------------------- - * |TYPE|SEVERITY|NARGS|OFFSET|LEN| - * |------------------------------| - * | Module_ID (optional) | - * |------------------------------| - * | TIMESTAMP (optional) | - * |------------------------------| - * | P_STR | - * |------------------------------| - * | data | - * |------------------------------| - * | data | dummy | - * -------------------------------- - * - * 3. Pushed string. If string is pushed into the logger internal buffer it is - * stored as PUSHED entry. It consists of header, unused data (optional) and - * string. Unused data is present if string does not not fit into a buffer - * without wrapping (and string cannot be wrapped). In that case header - * contains information about offset. - * - * -------------------------------- - * |TYPE| OFFSET | LEN | - * |------------------------------| - * | OFFSET | - * |------------------------------| - * end| OFFSET | - * 0|------------------------------| - * | STRING | - * |------------------------------| - * | STRING | dummy | - * -------------------------------- - */ - -#define STD_ADDR_MASK ((uint32_t)(1U << 22) - 1U) -#define HEADER_TYPE_STD 1U -#define HEADER_TYPE_HEXDUMP 2U -#define HEADER_TYPE_PUSHED 0U -#define HEADER_TYPE_INVALID 3U - -typedef struct -{ - uint32_t type : 2; - uint32_t in_progress: 1; - uint32_t data : 29; -} nrf_log_generic_header_t; - -typedef struct -{ - uint32_t type : 2; - uint32_t in_progress: 1; - uint32_t severity : 3; - uint32_t nargs : 4; - uint32_t addr : 22; -} nrf_log_std_header_t; - -typedef struct -{ - uint32_t type : 2; - uint32_t in_progress: 1; - uint32_t severity : 3; - uint32_t offset : 10; - uint32_t reserved : 6; - uint32_t len : 10; -} nrf_log_hexdump_header_t; - -typedef struct -{ - uint32_t type : 2; - uint32_t reserved0 : 4; - uint32_t offset : 10; - uint32_t reserved1 : 6; - uint32_t len : 10; -} nrf_log_pushed_header_t; - -typedef union -{ - nrf_log_generic_header_t generic; - nrf_log_std_header_t std; - nrf_log_hexdump_header_t hexdump; - nrf_log_pushed_header_t pushed; - uint32_t raw; -} nrf_log_main_header_t; - -typedef struct -{ - nrf_log_main_header_t base; - uint32_t module_id; - uint32_t timestamp; -} nrf_log_header_t; - -#define HEADER_SIZE (sizeof(nrf_log_header_t)/sizeof(uint32_t) - \ - (NRF_LOG_USES_TIMESTAMP ? 0 : 1)) - -#define PUSHED_HEADER_SIZE (sizeof(nrf_log_pushed_header_t)/sizeof(uint32_t)) - -//Implementation assumes that pushed header has one word. -STATIC_ASSERT(PUSHED_HEADER_SIZE == 1); -/** - * @brief A function for logging raw string. - * - * @param severity_mid Severity. - * @param p_str A pointer to a string. - */ -void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str); - -/** - * @brief A function for logging a formatted string with one argument. - * - * @param severity_mid Severity. - * @param p_str A pointer to a formatted string. - * @param val0 An argument. - */ -void nrf_log_frontend_std_1(uint32_t severity_mid, - char const * const p_str, - uint32_t val0); - -/** - * @brief A function for logging a formatted string with 2 arguments. - * - * @param severity_mid Severity. - * @param p_str A pointer to a formatted string. - * @param val0, val1 Arguments for formatting string. - */ -void nrf_log_frontend_std_2(uint32_t severity_mid, - char const * const p_str, - uint32_t val0, - uint32_t val1); - -/** - * @brief A function for logging a formatted string with 3 arguments. - * - * @param severity_mid Severity. - * @param p_str A pointer to a formatted string. - * @param val0, val1, val2 Arguments for formatting string. - */ -void nrf_log_frontend_std_3(uint32_t severity_mid, - char const * const p_str, - uint32_t val0, - uint32_t val1, - uint32_t val2); - -/** - * @brief A function for logging a formatted string with 4 arguments. - * - * @param severity_mid Severity. - * @param p_str A pointer to a formatted string. - * @param val0, val1, val2, val3 Arguments for formatting string. - */ -void nrf_log_frontend_std_4(uint32_t severity_mid, - char const * const p_str, - uint32_t val0, - uint32_t val1, - uint32_t val2, - uint32_t val3); - -/** - * @brief A function for logging a formatted string with 5 arguments. - * - * @param severity_mid Severity. - * @param p_str A pointer to a formatted string. - * @param val0, val1, val2, val3, val4 Arguments for formatting string. - */ -void nrf_log_frontend_std_5(uint32_t severity_mid, - char const * const p_str, - uint32_t val0, - uint32_t val1, - uint32_t val2, - uint32_t val3, - uint32_t val4); - -/** - * @brief A function for logging a formatted string with 6 arguments. - * - * @param severity_mid Severity. - * @param p_str A pointer to a formatted string. - * @param val0, val1, val2, val3, val4, val5 Arguments for formatting string. - */ -void nrf_log_frontend_std_6(uint32_t severity_mid, - char const * const p_str, - uint32_t val0, - uint32_t val1, - uint32_t val2, - uint32_t val3, - uint32_t val4, - uint32_t val5); - -/** - * @brief A function for logging raw data. - * - * @param severity_mid Severity. - * @param p_str A pointer to a string which is prefixing the data. - * @param p_data A pointer to data to be dumped. - * @param length Length of data (in bytes). - * - */ -void nrf_log_frontend_hexdump(uint32_t severity_mid, - const void * const p_data, - uint16_t length); - -/** - * @brief A function for reading a byte from log backend. - * - * @return Byte. - */ -uint8_t nrf_log_getchar(void); -#endif // NRF_LOG_INTERNAL_H__ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_INTERNAL_H__ +#define NRF_LOG_INTERNAL_H__ +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_error.h" +#include "app_util.h" +#include +#include +#include "nrf_log_instance.h" +#include "nrf_log_types.h" + +#ifndef NRF_LOG_ERROR_COLOR + #define NRF_LOG_ERROR_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_WARNING_COLOR + #define NRF_LOG_WARNING_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_INFO_COLOR + #define NRF_LOG_INFO_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_DEBUG_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_LOG_COLOR_DEFAULT +#endif + + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 0 +#endif + +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif + +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 0 +#endif + +#ifndef NRF_LOG_MODULE_NAME + #define NRF_LOG_MODULE_NAME app +#endif + +#define NRF_LOG_LEVEL_BITS 3 +#define NRF_LOG_LEVEL_MASK ((1UL << NRF_LOG_LEVEL_BITS) - 1) +#define NRF_LOG_MODULE_ID_BITS 16 +#define NRF_LOG_MODULE_ID_POS 16 + + +#define NRF_LOG_MAX_NUM_OF_ARGS 6 + + +#if NRF_LOG_FILTERS_ENABLED && NRF_LOG_ENABLED + #define NRF_LOG_FILTER NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).filter + #define NRF_LOG_INST_FILTER(p_inst) (p_inst)->filter +#else + #undef NRF_LOG_FILTER + #define NRF_LOG_FILTER NRF_LOG_SEVERITY_DEBUG + #define NRF_LOG_INST_FILTER(p_inst) NRF_LOG_SEVERITY_DEBUG +#endif + +#if NRF_LOG_ENABLED +#define NRF_LOG_MODULE_ID NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).module_id +#define NRF_LOG_INST_ID(p_inst) (p_inst)->module_id +#else +#define NRF_LOG_MODULE_ID 0 +#define NRF_LOG_INST_ID(p_inst) 0 +#endif + + +#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__) +#define LOG_INTERNAL(type, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \ + __VA_ARGS__), type, __VA_ARGS__) +#if NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) nrf_log_push(_str) +#define LOG_INTERNAL_0(type, str) \ + nrf_log_frontend_std_0(type, str) +#define LOG_INTERNAL_1(type, str, arg0) \ + /*lint -save -e571*/nrf_log_frontend_std_1(type, str, (uint32_t)(arg0))/*lint -restore*/ +#define LOG_INTERNAL_2(type, str, arg0, arg1) \ + /*lint -save -e571*/nrf_log_frontend_std_2(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1))/*lint -restore*/ +#define LOG_INTERNAL_3(type, str, arg0, arg1, arg2) \ + /*lint -save -e571*/nrf_log_frontend_std_3(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2))/*lint -restore*/ +#define LOG_INTERNAL_4(type, str, arg0, arg1, arg2, arg3) \ + /*lint -save -e571*/nrf_log_frontend_std_4(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3))/*lint -restore*/ +#define LOG_INTERNAL_5(type, str, arg0, arg1, arg2, arg3, arg4) \ + /*lint -save -e571*/nrf_log_frontend_std_5(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4))/*lint -restore*/ +#define LOG_INTERNAL_6(type, str, arg0, arg1, arg2, arg3, arg4, arg5) \ + /*lint -save -e571*/nrf_log_frontend_std_6(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4), (uint32_t)(arg5))/*lint -restore*/ + + +#else //NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) (void)(_str) +#define LOG_INTERNAL_0(_type, _str) \ + (void)(_type); (void)(_str) +#define LOG_INTERNAL_1(_type, _str, _arg0) \ + (void)(_type); (void)(_str); (void)(_arg0) +#define LOG_INTERNAL_2(_type, _str, _arg0, _arg1) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1) +#define LOG_INTERNAL_3(_type, _str, _arg0, _arg1, _arg2) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2) +#define LOG_INTERNAL_4(_type, _str, _arg0, _arg1, _arg2, _arg3) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3) +#define LOG_INTERNAL_5(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4) +#define LOG_INTERNAL_6(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4, _arg5) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4); (void)(_arg5) +#endif //NRF_LOG_ENABLED + +#define LOG_SEVERITY_MOD_ID(severity) ((severity) | NRF_LOG_MODULE_ID << NRF_LOG_MODULE_ID_POS) +#define LOG_SEVERITY_INST_ID(severity,p_inst) ((severity) | NRF_LOG_INST_ID(p_inst) << NRF_LOG_MODULE_ID_POS) + +#if NRF_LOG_ENABLED +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + nrf_log_frontend_hexdump((_severity), (_p_data), (_length)) +#else +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + (void)(_severity); (void)(_p_data); (void)_length +#endif + +#define NRF_LOG_INTERNAL_INST(level, level_id, p_inst, ...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_INST_FILTER(p_inst) >= level) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_INST_ID(level_id, p_inst), __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_MODULE(level, level_id, ...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= level) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_HEXDUMP_INST(level, level_id, p_inst, p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_INST_FILTER(p_inst) >= level) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_INST_ID(level_id, p_inst), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_HEXDUMP_MODULE(level, level_id, p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= level) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(level_id), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_INST_ERROR(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_ERROR(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR,__VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_data, len) + +#define NRF_LOG_INTERNAL_INST_WARNING(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_WARNING(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING,__VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_data, len) + +#define NRF_LOG_INTERNAL_INST_INFO(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_INFO(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_data, len) + +#define NRF_LOG_INTERNAL_RAW_INFO(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, p_data, len) + +#define NRF_LOG_INTERNAL_INST_DEBUG(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_DEBUG(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_data, len) + + +#if NRF_LOG_ENABLED + +#ifdef UNIT_TEST +#define COMPILED_LOG_LEVEL 4 +#else +#define COMPILED_LOG_LEVEL NRF_LOG_LEVEL +#endif + + +#define NRF_LOG_INTERNAL_MODULE_REGISTER() \ + NRF_LOG_INTERNAL_ITEM_REGISTER(NRF_LOG_MODULE_NAME, \ + STRINGIFY(NRF_LOG_MODULE_NAME), \ + NRF_LOG_INFO_COLOR, \ + NRF_LOG_DEBUG_COLOR, \ + NRF_LOG_INITIAL_LEVEL, \ + COMPILED_LOG_LEVEL) + +#else +#define NRF_LOG_INTERNAL_MODULE_REGISTER() /*lint -save -e19*/ /*lint -restore*/ +#endif + +extern NRF_LOG_DYNAMIC_STRUCT_NAME NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME); + +/** + * Set of macros for encoding and decoding header for log entries. + * There are 3 types of entries: + * 1. Standard entry (STD) + * An entry consists of header, pointer to string and values. Header contains + * severity leveland determines number of arguments and thus size of the entry. + * Since flash address space starts from 0x00000000 and is limited to kB rather + * than MB 22 bits are used to store the address (4MB). It is used that way to + * save one RAM memory. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS| P_STR | + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | ARG0 | + * |------------------------------| + * | .... | + * |------------------------------| + * | ARG(nargs-1) | + * -------------------------------- + * + * 2. Hexdump entry (HEXDUMP) is used for dumping raw data. An entry consists of + * header, optional timestamp, pointer to string and data. A header contains + * length (10bit) and offset which is updated after backend processes part of + * data. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS|OFFSET|LEN| + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | P_STR | + * |------------------------------| + * | data | + * |------------------------------| + * | data | dummy | + * -------------------------------- + * + * 3. Pushed string. If string is pushed into the logger internal buffer it is + * stored as PUSHED entry. It consists of header, unused data (optional) and + * string. Unused data is present if string does not not fit into a buffer + * without wrapping (and string cannot be wrapped). In that case header + * contains information about offset. + * + * -------------------------------- + * |TYPE| OFFSET | LEN | + * |------------------------------| + * | OFFSET | + * |------------------------------| + * end| OFFSET | + * 0|------------------------------| + * | STRING | + * |------------------------------| + * | STRING | dummy | + * -------------------------------- + */ + +#define STD_ADDR_MASK ((uint32_t)(1U << 22) - 1U) +#define HEADER_TYPE_STD 1U +#define HEADER_TYPE_HEXDUMP 2U +#define HEADER_TYPE_PUSHED 0U +#define HEADER_TYPE_INVALID 3U + +typedef struct +{ + uint32_t type : 2; + uint32_t in_progress: 1; + uint32_t data : 29; +} nrf_log_generic_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t in_progress: 1; + uint32_t severity : 3; + uint32_t nargs : 4; + uint32_t addr : 22; +} nrf_log_std_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t in_progress: 1; + uint32_t severity : 3; + uint32_t offset : 10; + uint32_t reserved : 6; + uint32_t len : 10; +} nrf_log_hexdump_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t reserved0 : 4; + uint32_t offset : 10; + uint32_t reserved1 : 6; + uint32_t len : 10; +} nrf_log_pushed_header_t; + +typedef union +{ + nrf_log_generic_header_t generic; + nrf_log_std_header_t std; + nrf_log_hexdump_header_t hexdump; + nrf_log_pushed_header_t pushed; + uint32_t raw; +} nrf_log_main_header_t; + +typedef struct +{ + nrf_log_main_header_t base; + uint32_t module_id; + uint32_t timestamp; +} nrf_log_header_t; + +#define HEADER_SIZE (sizeof(nrf_log_header_t)/sizeof(uint32_t) - \ + (NRF_LOG_USES_TIMESTAMP ? 0 : 1)) + +#define PUSHED_HEADER_SIZE (sizeof(nrf_log_pushed_header_t)/sizeof(uint32_t)) + +//Implementation assumes that pushed header has one word. +STATIC_ASSERT(PUSHED_HEADER_SIZE == 1); +/** + * @brief A function for logging raw string. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string. + */ +void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str); + +/** + * @brief A function for logging a formatted string with one argument. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0 An argument. + */ +void nrf_log_frontend_std_1(uint32_t severity_mid, + char const * const p_str, + uint32_t val0); + +/** + * @brief A function for logging a formatted string with 2 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1 Arguments for formatting string. + */ +void nrf_log_frontend_std_2(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1); + +/** + * @brief A function for logging a formatted string with 3 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2 Arguments for formatting string. + */ +void nrf_log_frontend_std_3(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2); + +/** + * @brief A function for logging a formatted string with 4 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3 Arguments for formatting string. + */ +void nrf_log_frontend_std_4(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3); + +/** + * @brief A function for logging a formatted string with 5 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4 Arguments for formatting string. + */ +void nrf_log_frontend_std_5(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4); + +/** + * @brief A function for logging a formatted string with 6 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4, val5 Arguments for formatting string. + */ +void nrf_log_frontend_std_6(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4, + uint32_t val5); + +/** + * @brief A function for logging raw data. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string which is prefixing the data. + * @param p_data A pointer to data to be dumped. + * @param length Length of data (in bytes). + * + */ +void nrf_log_frontend_hexdump(uint32_t severity_mid, + const void * const p_data, + uint16_t length); + +/** + * @brief A function for reading a byte from log backend. + * + * @return Byte. + */ +uint8_t nrf_log_getchar(void); +#endif // NRF_LOG_INTERNAL_H__ diff --git a/third_party/NordicSemiconductor/dependencies/sdk_common.h b/third_party/NordicSemiconductor/dependencies/sdk_common.h index bbfcbfe49..5f42f03a4 100644 --- a/third_party/NordicSemiconductor/dependencies/sdk_common.h +++ b/third_party/NordicSemiconductor/dependencies/sdk_common.h @@ -1,77 +1,77 @@ -/** - * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @cond */ -/**@file - * - * @ingroup experimental_api - * @defgroup sdk_common SDK Common Header - * @brief All common headers needed for SDK examples will be included here so that application - * developer does not have to include headers on him/herself. - * @{ - */ - -#ifndef SDK_COMMON_H__ -#define SDK_COMMON_H__ - -#include -#include -#include -#include "sdk_config.h" -#include "nordic_common.h" -#include "compiler_abstraction.h" -#include "sdk_os.h" -#include "sdk_errors.h" -#include "app_util.h" -#include "sdk_macros.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** @} */ -/** @endcond */ - -#ifdef __cplusplus -} -#endif - -#endif // SDK_COMMON_H__ - +/** + * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @cond */ +/**@file + * + * @ingroup experimental_api + * @defgroup sdk_common SDK Common Header + * @brief All common headers needed for SDK examples will be included here so that application + * developer does not have to include headers on him/herself. + * @{ + */ + +#ifndef SDK_COMMON_H__ +#define SDK_COMMON_H__ + +#include +#include +#include +#include "sdk_config.h" +#include "nordic_common.h" +#include "compiler_abstraction.h" +#include "sdk_os.h" +#include "sdk_errors.h" +#include "app_util.h" +#include "sdk_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_COMMON_H__ + diff --git a/third_party/NordicSemiconductor/dependencies/sdk_config.h b/third_party/NordicSemiconductor/dependencies/sdk_config.h index eae55be52..8c8de287c 100644 --- a/third_party/NordicSemiconductor/dependencies/sdk_config.h +++ b/third_party/NordicSemiconductor/dependencies/sdk_config.h @@ -1,781 +1,781 @@ -#ifndef SDK_CONFIG_H -#define SDK_CONFIG_H - -#include -#undef PACKAGE - -#if defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wpedantic" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//========================================================== -// APP_USBD_ENABLED - app_usbd - USB Device library -//========================================================== -#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) -#ifndef APP_USBD_ENABLED -#define APP_USBD_ENABLED 1 -#endif -#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 -#ifndef APP_USBD_ENABLED -#define APP_USBD_ENABLED 0 -#endif -#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 - -// APP_USBD_VID - Vendor ID - -// Vendor ID ordered from USB IF: http://www.usb.org/developers/vendor/ -#ifndef APP_USBD_VID -#define APP_USBD_VID 0x1915 -#endif - -// APP_USBD_PID - Product ID - -// Selected Product ID -#ifndef APP_USBD_PID -#define APP_USBD_PID 0xCAFE -#endif - -// APP_USBD_DEVICE_VER_MAJOR - Device version, major part <0-99> - - -// Device version, will be converted automatically to BCD notation. Use just decimal values. - -#ifndef APP_USBD_DEVICE_VER_MAJOR -#define APP_USBD_DEVICE_VER_MAJOR 1 -#endif - -// APP_USBD_DEVICE_VER_MINOR - Device version, minor part <0-99> - - -// Device version, will be converted automatically to BCD notation. Use just decimal values. - -#ifndef APP_USBD_DEVICE_VER_MINOR -#define APP_USBD_DEVICE_VER_MINOR 0 -#endif - -// APP_USBD_CONFIG_SELF_POWERED - Self powered - - -#ifndef APP_USBD_CONFIG_SELF_POWERED -#define APP_USBD_CONFIG_SELF_POWERED 1 -#endif - -// APP_USBD_CONFIG_MAX_POWER - MaxPower field in configuration descriptor in milliamps. <0-500> - - -#ifndef APP_USBD_CONFIG_MAX_POWER -#define APP_USBD_CONFIG_MAX_POWER 500 -#endif - -// APP_USBD_CONFIG_POWER_EVENTS_PROCESS - Process power events - - -// Enable processing power events in USB event handler. - -#ifndef APP_USBD_CONFIG_POWER_EVENTS_PROCESS -#define APP_USBD_CONFIG_POWER_EVENTS_PROCESS 1 -#endif - -// APP_USBD_CONFIG_EVENT_QUEUE_ENABLE - Enable event queue - -// This is the default configuration when all the events are placed into internal queue. -// Disable it when external queue is used like app_scheduler or if you wish to process all events inside interrupts. -// Processing all events from the interrupt level adds requirement not to call any functions that modifies the USBD library state from the context higher than USB interrupt context. -// Functions that modify USBD state are functions for sleep, wakeup, start, stop, enable and disable. -//========================================================== -#ifndef APP_USBD_CONFIG_EVENT_QUEUE_ENABLE -#define APP_USBD_CONFIG_EVENT_QUEUE_ENABLE 1 -#endif -// APP_USBD_CONFIG_EVENT_QUEUE_SIZE - The size of event queue <16-64> - - -// The size of the queue for the events that would be processed in the main loop. - -#ifndef APP_USBD_CONFIG_EVENT_QUEUE_SIZE -#define APP_USBD_CONFIG_EVENT_QUEUE_SIZE 32 -#endif - -// APP_USBD_CONFIG_SOF_HANDLING_MODE - Change SOF events handling mode. - - -// Normal queue - SOF events are pushed normally into event queue. -// Compress queue - SOF events are counted and binded with other events or executed when queue is empty. -// This prevents queue from filling with SOF events. -// Interrupt - SOF events are processed in interrupt. -// <0=> Normal queue -// <1=> Compress queue -// <2=> Interrupt - -#ifndef APP_USBD_CONFIG_SOF_HANDLING_MODE -#define APP_USBD_CONFIG_SOF_HANDLING_MODE 1 -#endif - -// - -// APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE - Provide a function that generates timestamps for logs based on the current SOF - - -// The function app_usbd_sof_timestamp_get will be implemented if the logger is enabled. -// Use it when initializing the logger. -// SOF processing will be always enabled when this configuration parameter is active. -// Notice that this option is configured outside of APP_USBD_CONFIG_LOG_ENABLED. -// This means that it will work even if the logging in this very module is disabled. - -#ifndef APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE -#define APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE 0 -#endif - -// APP_USBD_CONFIG_DESC_STRING_SIZE - Maximum size of the NULL-terminated string of the string descriptor. <31-254> - - -// 31 characters can be stored in the internal USB buffer used for transfers. -// Any value higher than 31 creates an additional buffer just for descriptor strings. - -#ifndef APP_USBD_CONFIG_DESC_STRING_SIZE -#define APP_USBD_CONFIG_DESC_STRING_SIZE 31 -#endif - -// APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED - Enable UTF8 conversion. - - -// Enable UTF8-encoded characters. In normal processing, only ASCII characters are available. - -#ifndef APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED -#define APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED 0 -#endif - -// APP_USBD_STRINGS_LANGIDS - Supported languages identifiers. - -// Note: This value is not editable in Configuration Wizard. -// Comma-separated list of supported languages. -#ifndef APP_USBD_STRINGS_LANGIDS -#define APP_USBD_STRINGS_LANGIDS APP_USBD_LANG_AND_SUBLANG(APP_USBD_LANG_ENGLISH, APP_USBD_SUBLANG_ENGLISH_US) -#endif - -// APP_USBD_STRING_ID_MANUFACTURER - Define manufacturer string ID. - -// Setting ID to 0 disables the string. -//========================================================== -#ifndef APP_USBD_STRING_ID_MANUFACTURER -#define APP_USBD_STRING_ID_MANUFACTURER 1 -#endif -// APP_USBD_STRINGS_MANUFACTURER_EXTERN - Define whether @ref APP_USBD_STRINGS_MANUFACTURER is created by macro or declared as a global variable. - - -#ifndef APP_USBD_STRINGS_MANUFACTURER_EXTERN -#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0 -#endif - -// APP_USBD_STRINGS_MANUFACTURER - String descriptor for the manufacturer name. - -// Note: This value is not editable in Configuration Wizard. -// Comma-separated list of manufacturer names for each defined language. -// Use @ref APP_USBD_STRING_DESC macro to create string descriptor from a NULL-terminated string. -// Use @ref APP_USBD_STRING_RAW8_DESC macro to create string descriptor from comma-separated uint8_t values. -// Use @ref APP_USBD_STRING_RAW16_DESC macro to create string descriptor from comma-separated uint16_t values. -// Alternatively, configure the macro to point to any internal variable pointer that already contains the descriptor. -// Setting string to NULL disables that string. -// The order of manufacturer names must be the same like in @ref APP_USBD_STRINGS_LANGIDS. -#ifndef APP_USBD_STRINGS_MANUFACTURER -#define APP_USBD_STRINGS_MANUFACTURER APP_USBD_STRING_DESC("Nordic Semiconductor") -#endif - -// - -// APP_USBD_STRING_ID_PRODUCT - Define product string ID. - -// Setting ID to 0 disables the string. -//========================================================== -#ifndef APP_USBD_STRING_ID_PRODUCT -#define APP_USBD_STRING_ID_PRODUCT 2 -#endif -// APP_USBD_STRINGS_PRODUCT_EXTERN - Define whether @ref APP_USBD_STRINGS_PRODUCT is created by macro or declared as a global variable. - - -#ifndef APP_USBD_STRINGS_PRODUCT_EXTERN -#define APP_USBD_STRINGS_PRODUCT_EXTERN 0 -#endif - -// APP_USBD_STRINGS_PRODUCT - String descriptor for the product name. - -// Note: This value is not editable in Configuration Wizard. -// List of product names that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER. -#ifndef APP_USBD_STRINGS_PRODUCT -#define APP_USBD_STRINGS_PRODUCT APP_USBD_STRING_DESC("nRF52840 OpenThread Device") -#endif - -// - -// APP_USBD_STRING_ID_SERIAL - Define serial number string ID. - -// Setting ID to 0 disables the string. -//========================================================== -#ifndef APP_USBD_STRING_ID_SERIAL -#define APP_USBD_STRING_ID_SERIAL 3 -#endif -// APP_USBD_STRING_SERIAL_EXTERN - Define whether @ref APP_USBD_STRING_SERIAL is created by macro or declared as a global variable. - - -#ifndef APP_USBD_STRING_SERIAL_EXTERN -#define APP_USBD_STRING_SERIAL_EXTERN 1 -#endif - -// APP_USBD_STRING_SERIAL - String descriptor for the serial number. - -// Note: This value is not editable in Configuration Wizard. -// Serial number that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER. -#ifndef APP_USBD_STRING_SERIAL -#define APP_USBD_STRING_SERIAL g_extern_serial_number -#endif - -// - -// APP_USBD_STRING_ID_CONFIGURATION - Define configuration string ID. - -// Setting ID to 0 disables the string. -//========================================================== -#ifndef APP_USBD_STRING_ID_CONFIGURATION -#define APP_USBD_STRING_ID_CONFIGURATION 4 -#endif -// APP_USBD_STRING_CONFIGURATION_EXTERN - Define whether @ref APP_USBD_STRINGS_CONFIGURATION is created by macro or declared as global variable. - - -#ifndef APP_USBD_STRING_CONFIGURATION_EXTERN -#define APP_USBD_STRING_CONFIGURATION_EXTERN 0 -#endif - -// APP_USBD_STRINGS_CONFIGURATION - String descriptor for the device configuration. - -// Note: This value is not editable in Configuration Wizard. -// Configuration string that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER. -#ifndef APP_USBD_STRINGS_CONFIGURATION -#define APP_USBD_STRINGS_CONFIGURATION APP_USBD_STRING_DESC("Default configuration") -#endif - -// - -// APP_USBD_STRINGS_USER - Default values for user strings. - -// Note: This value is not editable in Configuration Wizard. -// This value stores all application specific user strings with the default initialization. -// The setup is done by X-macros. -// Expected macro parameters: -// @code -// X(mnemonic, [=str_idx], ...) -// @endcode -// - @c mnemonic: Mnemonic of the string descriptor that would be added to -// @ref app_usbd_string_desc_idx_t enumerator. -// - @c str_idx : String index value, can be set or left empty. -// For example, WinUSB driver requires descriptor to be present on 0xEE index. -// Then use X(USBD_STRING_WINUSB, =0xEE, (APP_USBD_STRING_DESC(...))) -// - @c ... : List of string descriptors for each defined language. -#ifndef APP_USBD_STRINGS_USER -#define APP_USBD_STRINGS_USER X(APP_USER_1, , APP_USBD_STRING_DESC("User 1")) -#endif - -// - -// APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module -//========================================================== -#ifndef APP_USBD_CONFIG_LOG_ENABLED -#define APP_USBD_CONFIG_LOG_ENABLED 0 -#endif - -// - -// - -// USBD_ENABLED - nrf_drv_usbd - USB driver -//========================================================== -#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) -#ifndef USBD_ENABLED -#define USBD_ENABLED 1 -#endif -#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 -#ifndef USBD_ENABLED -#define USBD_ENABLED 0 -#endif -#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 - -// Enable power USB detection. - -// Configure if the example supports USB port connection. - -#ifndef USBD_POWER_DETECTION -#define USBD_POWER_DETECTION 1 -#endif - -// USBD_CONFIG_IRQ_PRIORITY - Interrupt priority - -// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice -// <0=> 0 (highest) -// <1=> 1 -// <2=> 2 -// <3=> 3 -// <4=> 4 -// <5=> 5 -// <6=> 6 -// <7=> 7 - -#ifndef USBD_CONFIG_IRQ_PRIORITY -#define USBD_CONFIG_IRQ_PRIORITY 7 -#endif - -// USBD_CONFIG_DMASCHEDULER_MODE - USBD SMA scheduler working scheme - -// <0=> Prioritized access -// <1=> Round Robin - -#ifndef USBD_CONFIG_DMASCHEDULER_MODE -#define USBD_CONFIG_DMASCHEDULER_MODE 0 -#endif - -// USBD_CONFIG_DMASCHEDULER_ISO_BOOST - Give priority to isochronous transfers - - -// This option gives priority to isochronous transfers. -// Enabling it assures that isochronous transfers are always processed, -// even if multiple other transfers are pending. -// Isochronous endpoints are prioritized before the usbd_dma_scheduler_algorithm -// function is called, so the option is independent of the algorithm chosen. - -#ifndef USBD_CONFIG_DMASCHEDULER_ISO_BOOST -#define USBD_CONFIG_DMASCHEDULER_ISO_BOOST 1 -#endif - -// USBD_CONFIG_ISO_IN_ZLP - Respond to an IN token on ISO IN endpoint with ZLP when no data is ready - - -// If set, ISO IN endpoint will respond to an IN token with ZLP when no data is ready to be sent. -// Else, there will be no response. - -#ifndef USBD_CONFIG_ISO_IN_ZLP -#define USBD_CONFIG_ISO_IN_ZLP 0 -#endif - -#define NRFX_USBD_ENABLED USBD_ENABLED -#define NRFX_USBD_POWER_DETECTION USBD_POWER_DETECTION -#define NRFX_USBD_CONFIG_IRQ_PRIORITY USBD_CONFIG_IRQ_PRIORITY -#define NRFX_USBD_CONFIG_DMASCHEDULER_MODE USBD_CONFIG_DMASCHEDULER_MODE -#define NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST USBD_CONFIG_DMASCHEDULER_ISO_BOOST -#define NRFX_USBD_CONFIG_ISO_IN_ZLP USBD_CONFIG_ISO_IN_ZLP - -// - - -// Application info used by the USB DFU. - -// @def APP_NAME - -// Application name in a human readable string. - - -#ifndef APP_NAME -#define APP_NAME "OpenThread App" -#endif - - -// APP_VERSION_MAJOR - -// Application version major version. - -#ifndef APP_VERSION_MAJOR -#define APP_VERSION_MAJOR 1 -#endif - - -// APP_VERSION_MINOR - -// Application version minor version. - - -#ifndef APP_VERSION_MINOR -#define APP_VERSION_MINOR 0 -#endif - - -// APP_VERSION_PATCH - -// Application version patch version. - - -#ifndef APP_VERSION_PATCH -#define APP_VERSION_PATCH 0 -#endif - - -// @def APP_ID - -// Application ID. - - -#ifndef APP_ID -#define APP_ID 1 -#endif - - -// APP_VERSION_PRERELEASE - -// Application prerelease tag. - - -#ifndef APP_VERSION_PRERELEASE -#define APP_VERSION_PRERELEASE "" -#endif - - -// APP_VERSION_METADATA - -// Application metadata. - - -#ifndef APP_VERSION_METADATA -#define APP_VERSION_METADATA "" -#endif - -// app_usbd_cdc_acm - USB CDC ACM class - -//========================================================== -// APP_USBD_CDC_ACM_ENABLED - app_usbd_cdc_acm - USB CDC ACM class - - -#ifndef APP_USBD_CDC_ACM_ENABLED -#define APP_USBD_CDC_ACM_ENABLED 1 -#endif - -// APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE - Send ZLP on write with same size as endpoint - - -// If enabled, CDC ACM class will automatically send a zero length packet after transfer which has the same size as endpoint. -// This may limit throughput if a lot of binary data is sent, but in terminal mode operation it makes sure that the data is always displayed right after it is sent. - -#ifndef APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE -#define APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE 1 -#endif - -// - -// app_usbd_nrf_dfu_trigger - USB Trigger library - -//========================================================== -// APP_USBD_NRF_DFU_TRIGGER_ENABLED - - -// Enable possibility to enter the bootloader from the application via a software trigger send over USB. -// Requires configured BSP_SELF_PINRESET_PIN which is a GPIO pin connected to the reset pin. - -#ifndef APP_USBD_NRF_DFU_TRIGGER_ENABLED -#define APP_USBD_NRF_DFU_TRIGGER_ENABLED 0 -#endif - -// BSP_SELF_PINRESET_PIN - - -// Enable possibility to enter the bootloader from the application via a software trigger send over USB. -// Requires configured BSP_SELF_PINRESET_PIN which is a GPIO pin connected to the reset pin. -// NRF_GPIO_PIN_MAP(0,19) is a pin used on Nordic PCA10059 Dongle. - -#ifndef BSP_SELF_PINRESET_PIN -#define BSP_SELF_PINRESET_PIN NRF_GPIO_PIN_MAP(0, 19) -#endif - -// NRF_DFU_TRIGGER_USB_USB_SHARED - -// Flag indicating whether USB is used for other purposes in the application. - -#ifndef NRF_DFU_TRIGGER_USB_USB_SHARED -#define NRF_DFU_TRIGGER_USB_USB_SHARED 1 -#endif - - -// NRF_DFU_TRIGGER_USB_INTERFACE_NUM - -// The USB interface to use for the DFU Trigger library. -// According to the USB Specification, interface numbers cannot have gaps. Tailor this value to adhere to this -// limitation. Takes values between 0-255 - -#ifndef NRF_DFU_TRIGGER_USB_INTERFACE_NUM -#define NRF_DFU_TRIGGER_USB_INTERFACE_NUM 0 -#endif - -// - -//========================================================== - -// nrf_log - Logging - -//========================================================== -// NRF_LOG_ENABLED - Logging module for nRF5 SDK -//========================================================== -#ifndef NRF_LOG_ENABLED -#define NRF_LOG_ENABLED 0 -#endif - -// -// - -// segger_rtt - SEGGER RTT - -//========================================================== -// SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer. -// Note that either @ref NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE -// or this value is actually used. It depends on which one is bigger. - -#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP -#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 512 -#endif - -// SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Size of upstream buffer. -#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS -#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2 -#endif - -// SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of upstream buffer. -#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN -#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16 -#endif - -// SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Size of upstream buffer. -#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS -#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2 -#endif - -// SEGGER_RTT_CONFIG_DEFAULT_MODE - RTT behavior if the buffer is full. - - -// The following modes are supported: -// - SKIP - Do not block, output nothing. -// - TRIM - Do not block, output as much as fits. -// - BLOCK - Wait until there is space in the buffer. -// <0=> SKIP -// <1=> TRIM -// <2=> BLOCK_IF_FIFO_FULL - -#ifndef SEGGER_RTT_CONFIG_DEFAULT_MODE -#define SEGGER_RTT_CONFIG_DEFAULT_MODE 0 -#endif - -// -//========================================================== - -// CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver -//========================================================== -#ifndef CLOCK_ENABLED -#define CLOCK_ENABLED 1 -#endif -// CLOCK_CONFIG_XTAL_FREQ - HF XTAL Frequency - -// <0=> Default (64 MHz) - -#ifndef CLOCK_CONFIG_XTAL_FREQ -#define CLOCK_CONFIG_XTAL_FREQ 0 -#endif - -// CLOCK_CONFIG_LF_SRC - LF Clock Source - -// <0=> RC -// <1=> XTAL -// <2=> Synth - -#ifndef CLOCK_CONFIG_LF_SRC -#define CLOCK_CONFIG_LF_SRC 1 -#endif - -// CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority - - -// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice -// <0=> 0 (highest) -// <1=> 1 -// <2=> 2 -// <3=> 3 -// <4=> 4 -// <5=> 5 -// <6=> 6 -// <7=> 7 - -#ifndef CLOCK_CONFIG_IRQ_PRIORITY -#define CLOCK_CONFIG_IRQ_PRIORITY 7 -#endif - -// - -// POWER_ENABLED - nrf_drv_power - POWER peripheral driver -//========================================================== - -#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) -#ifndef POWER_ENABLED -#define POWER_ENABLED 1 -#endif -#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 -#ifndef POWER_ENABLED -#define POWER_ENABLED 0 -#endif -#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 - -// POWER_CONFIG_IRQ_PRIORITY - Interrupt priority - - -// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice -// <0=> 0 (highest) -// <1=> 1 -// <2=> 2 -// <3=> 3 -// <4=> 4 -// <5=> 5 -// <6=> 6 -// <7=> 7 - -#ifndef POWER_CONFIG_IRQ_PRIORITY -#define POWER_CONFIG_IRQ_PRIORITY 7 -#endif - -// POWER_CONFIG_DEFAULT_DCDCEN - The default configuration of main DCDC regulator - - -// This settings means only that components for DCDC regulator are installed and it can be enabled. - -#ifndef POWER_CONFIG_DEFAULT_DCDCEN -#define POWER_CONFIG_DEFAULT_DCDCEN 0 -#endif - -// POWER_CONFIG_DEFAULT_DCDCENHV - The default configuration of High Voltage DCDC regulator - - -// This settings means only that components for DCDC regulator are installed and it can be enabled. - -#ifndef POWER_CONFIG_DEFAULT_DCDCENHV -#define POWER_CONFIG_DEFAULT_DCDCENHV 0 -#endif - -// - - -// NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver -//========================================================== -#if (SPIS_AS_SERIAL_TRANSPORT == 1) -#ifndef NRFX_SPIS_ENABLED -#define NRFX_SPIS_ENABLED 1 -#endif -#else // SPIS_AS_SERIAL_TRANSPORT == 1 -#ifndef NRFX_SPIS_ENABLED -#define NRFX_SPIS_ENABLED 0 -#endif -#endif // SPIS_AS_SERIAL_TRANSPORT == 1 - -// NRFX_SPIS0_ENABLED - Enable SPIS0 instance - -#ifndef NRFX_SPIS0_ENABLED -#define NRFX_SPIS0_ENABLED 1 -#endif - -// NRFX_SPIS1_ENABLED - Enable SPIS1 instance - - -#ifndef NRFX_SPIS1_ENABLED -#define NRFX_SPIS1_ENABLED 0 -#endif - -// NRFX_SPIS2_ENABLED - Enable SPIS2 instance - - -#ifndef NRFX_SPIS2_ENABLED -#define NRFX_SPIS2_ENABLED 0 -#endif - -// NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority - -// <0=> 0 (highest) -// <1=> 1 -// <2=> 2 -// <3=> 3 -// <4=> 4 -// <5=> 5 -// <6=> 6 -// <7=> 7 - -#ifndef NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY -#define NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY 7 -#endif - -// NRFX_SPIS_DEFAULT_DEF - SPIS default DEF character <0-255> - - -#ifndef NRFX_SPIS_DEFAULT_DEF -#define NRFX_SPIS_DEFAULT_DEF 255 -#endif - -// NRFX_SPIS_DEFAULT_ORC - SPIS default ORC character <0-255> - - -#ifndef NRFX_SPIS_DEFAULT_ORC -#define NRFX_SPIS_DEFAULT_ORC 255 -#endif - -// NRFX_SPIS_CONFIG_LOG_ENABLED - Enables logging in the module. -//========================================================== -#ifndef NRFX_SPIS_CONFIG_LOG_ENABLED -#define NRFX_SPIS_CONFIG_LOG_ENABLED 0 -#endif -// NRFX_SPIS_CONFIG_LOG_LEVEL - Default Severity level - -// <0=> Off -// <1=> Error -// <2=> Warning -// <3=> Info -// <4=> Debug - -#ifndef NRFX_SPIS_CONFIG_LOG_LEVEL -#define NRFX_SPIS_CONFIG_LOG_LEVEL 3 -#endif - -// NRFX_SPIS_CONFIG_INFO_COLOR - ANSI escape code prefix. - -// <0=> Default -// <1=> Black -// <2=> Red -// <3=> Green -// <4=> Yellow -// <5=> Blue -// <6=> Magenta -// <7=> Cyan -// <8=> White - -#ifndef NRFX_SPIS_CONFIG_INFO_COLOR -#define NRFX_SPIS_CONFIG_INFO_COLOR 0 -#endif - -// NRFX_SPIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. - -// <0=> Default -// <1=> Black -// <2=> Red -// <3=> Green -// <4=> Yellow -// <5=> Blue -// <6=> Magenta -// <7=> Cyan -// <8=> White - -#ifndef NRFX_SPIS_CONFIG_DEBUG_COLOR -#define NRFX_SPIS_CONFIG_DEBUG_COLOR 0 -#endif - -// - -// - -// SYSTICK_ENABLED - nrf_drv_systick - SysTick driver - -#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) -#ifndef SYSTICK_ENABLED -#define SYSTICK_ENABLED 1 -#endif -#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 -#ifndef SYSTICK_ENABLED -#define SYSTICK_ENABLED 0 -#endif -#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 - -#endif //SDK_CONFIG_H +#ifndef SDK_CONFIG_H +#define SDK_CONFIG_H + +#include +#undef PACKAGE + +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wpedantic" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//========================================================== +// APP_USBD_ENABLED - app_usbd - USB Device library +//========================================================== +#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) +#ifndef APP_USBD_ENABLED +#define APP_USBD_ENABLED 1 +#endif +#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 +#ifndef APP_USBD_ENABLED +#define APP_USBD_ENABLED 0 +#endif +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 + +// APP_USBD_VID - Vendor ID + +// Vendor ID ordered from USB IF: http://www.usb.org/developers/vendor/ +#ifndef APP_USBD_VID +#define APP_USBD_VID 0x1915 +#endif + +// APP_USBD_PID - Product ID + +// Selected Product ID +#ifndef APP_USBD_PID +#define APP_USBD_PID 0xCAFE +#endif + +// APP_USBD_DEVICE_VER_MAJOR - Device version, major part <0-99> + + +// Device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MAJOR +#define APP_USBD_DEVICE_VER_MAJOR 1 +#endif + +// APP_USBD_DEVICE_VER_MINOR - Device version, minor part <0-99> + + +// Device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MINOR +#define APP_USBD_DEVICE_VER_MINOR 0 +#endif + +// APP_USBD_CONFIG_SELF_POWERED - Self powered + + +#ifndef APP_USBD_CONFIG_SELF_POWERED +#define APP_USBD_CONFIG_SELF_POWERED 1 +#endif + +// APP_USBD_CONFIG_MAX_POWER - MaxPower field in configuration descriptor in milliamps. <0-500> + + +#ifndef APP_USBD_CONFIG_MAX_POWER +#define APP_USBD_CONFIG_MAX_POWER 500 +#endif + +// APP_USBD_CONFIG_POWER_EVENTS_PROCESS - Process power events + + +// Enable processing power events in USB event handler. + +#ifndef APP_USBD_CONFIG_POWER_EVENTS_PROCESS +#define APP_USBD_CONFIG_POWER_EVENTS_PROCESS 1 +#endif + +// APP_USBD_CONFIG_EVENT_QUEUE_ENABLE - Enable event queue + +// This is the default configuration when all the events are placed into internal queue. +// Disable it when external queue is used like app_scheduler or if you wish to process all events inside interrupts. +// Processing all events from the interrupt level adds requirement not to call any functions that modifies the USBD library state from the context higher than USB interrupt context. +// Functions that modify USBD state are functions for sleep, wakeup, start, stop, enable and disable. +//========================================================== +#ifndef APP_USBD_CONFIG_EVENT_QUEUE_ENABLE +#define APP_USBD_CONFIG_EVENT_QUEUE_ENABLE 1 +#endif +// APP_USBD_CONFIG_EVENT_QUEUE_SIZE - The size of event queue <16-64> + + +// The size of the queue for the events that would be processed in the main loop. + +#ifndef APP_USBD_CONFIG_EVENT_QUEUE_SIZE +#define APP_USBD_CONFIG_EVENT_QUEUE_SIZE 32 +#endif + +// APP_USBD_CONFIG_SOF_HANDLING_MODE - Change SOF events handling mode. + + +// Normal queue - SOF events are pushed normally into event queue. +// Compress queue - SOF events are counted and binded with other events or executed when queue is empty. +// This prevents queue from filling with SOF events. +// Interrupt - SOF events are processed in interrupt. +// <0=> Normal queue +// <1=> Compress queue +// <2=> Interrupt + +#ifndef APP_USBD_CONFIG_SOF_HANDLING_MODE +#define APP_USBD_CONFIG_SOF_HANDLING_MODE 1 +#endif + +// + +// APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE - Provide a function that generates timestamps for logs based on the current SOF + + +// The function app_usbd_sof_timestamp_get will be implemented if the logger is enabled. +// Use it when initializing the logger. +// SOF processing will be always enabled when this configuration parameter is active. +// Notice that this option is configured outside of APP_USBD_CONFIG_LOG_ENABLED. +// This means that it will work even if the logging in this very module is disabled. + +#ifndef APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE +#define APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE 0 +#endif + +// APP_USBD_CONFIG_DESC_STRING_SIZE - Maximum size of the NULL-terminated string of the string descriptor. <31-254> + + +// 31 characters can be stored in the internal USB buffer used for transfers. +// Any value higher than 31 creates an additional buffer just for descriptor strings. + +#ifndef APP_USBD_CONFIG_DESC_STRING_SIZE +#define APP_USBD_CONFIG_DESC_STRING_SIZE 31 +#endif + +// APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED - Enable UTF8 conversion. + + +// Enable UTF8-encoded characters. In normal processing, only ASCII characters are available. + +#ifndef APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED +#define APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED 0 +#endif + +// APP_USBD_STRINGS_LANGIDS - Supported languages identifiers. + +// Note: This value is not editable in Configuration Wizard. +// Comma-separated list of supported languages. +#ifndef APP_USBD_STRINGS_LANGIDS +#define APP_USBD_STRINGS_LANGIDS APP_USBD_LANG_AND_SUBLANG(APP_USBD_LANG_ENGLISH, APP_USBD_SUBLANG_ENGLISH_US) +#endif + +// APP_USBD_STRING_ID_MANUFACTURER - Define manufacturer string ID. + +// Setting ID to 0 disables the string. +//========================================================== +#ifndef APP_USBD_STRING_ID_MANUFACTURER +#define APP_USBD_STRING_ID_MANUFACTURER 1 +#endif +// APP_USBD_STRINGS_MANUFACTURER_EXTERN - Define whether @ref APP_USBD_STRINGS_MANUFACTURER is created by macro or declared as a global variable. + + +#ifndef APP_USBD_STRINGS_MANUFACTURER_EXTERN +#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0 +#endif + +// APP_USBD_STRINGS_MANUFACTURER - String descriptor for the manufacturer name. + +// Note: This value is not editable in Configuration Wizard. +// Comma-separated list of manufacturer names for each defined language. +// Use @ref APP_USBD_STRING_DESC macro to create string descriptor from a NULL-terminated string. +// Use @ref APP_USBD_STRING_RAW8_DESC macro to create string descriptor from comma-separated uint8_t values. +// Use @ref APP_USBD_STRING_RAW16_DESC macro to create string descriptor from comma-separated uint16_t values. +// Alternatively, configure the macro to point to any internal variable pointer that already contains the descriptor. +// Setting string to NULL disables that string. +// The order of manufacturer names must be the same like in @ref APP_USBD_STRINGS_LANGIDS. +#ifndef APP_USBD_STRINGS_MANUFACTURER +#define APP_USBD_STRINGS_MANUFACTURER APP_USBD_STRING_DESC("Nordic Semiconductor") +#endif + +// + +// APP_USBD_STRING_ID_PRODUCT - Define product string ID. + +// Setting ID to 0 disables the string. +//========================================================== +#ifndef APP_USBD_STRING_ID_PRODUCT +#define APP_USBD_STRING_ID_PRODUCT 2 +#endif +// APP_USBD_STRINGS_PRODUCT_EXTERN - Define whether @ref APP_USBD_STRINGS_PRODUCT is created by macro or declared as a global variable. + + +#ifndef APP_USBD_STRINGS_PRODUCT_EXTERN +#define APP_USBD_STRINGS_PRODUCT_EXTERN 0 +#endif + +// APP_USBD_STRINGS_PRODUCT - String descriptor for the product name. + +// Note: This value is not editable in Configuration Wizard. +// List of product names that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER. +#ifndef APP_USBD_STRINGS_PRODUCT +#define APP_USBD_STRINGS_PRODUCT APP_USBD_STRING_DESC("nRF52840 OpenThread Device") +#endif + +// + +// APP_USBD_STRING_ID_SERIAL - Define serial number string ID. + +// Setting ID to 0 disables the string. +//========================================================== +#ifndef APP_USBD_STRING_ID_SERIAL +#define APP_USBD_STRING_ID_SERIAL 3 +#endif +// APP_USBD_STRING_SERIAL_EXTERN - Define whether @ref APP_USBD_STRING_SERIAL is created by macro or declared as a global variable. + + +#ifndef APP_USBD_STRING_SERIAL_EXTERN +#define APP_USBD_STRING_SERIAL_EXTERN 1 +#endif + +// APP_USBD_STRING_SERIAL - String descriptor for the serial number. + +// Note: This value is not editable in Configuration Wizard. +// Serial number that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER. +#ifndef APP_USBD_STRING_SERIAL +#define APP_USBD_STRING_SERIAL g_extern_serial_number +#endif + +// + +// APP_USBD_STRING_ID_CONFIGURATION - Define configuration string ID. + +// Setting ID to 0 disables the string. +//========================================================== +#ifndef APP_USBD_STRING_ID_CONFIGURATION +#define APP_USBD_STRING_ID_CONFIGURATION 4 +#endif +// APP_USBD_STRING_CONFIGURATION_EXTERN - Define whether @ref APP_USBD_STRINGS_CONFIGURATION is created by macro or declared as global variable. + + +#ifndef APP_USBD_STRING_CONFIGURATION_EXTERN +#define APP_USBD_STRING_CONFIGURATION_EXTERN 0 +#endif + +// APP_USBD_STRINGS_CONFIGURATION - String descriptor for the device configuration. + +// Note: This value is not editable in Configuration Wizard. +// Configuration string that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER. +#ifndef APP_USBD_STRINGS_CONFIGURATION +#define APP_USBD_STRINGS_CONFIGURATION APP_USBD_STRING_DESC("Default configuration") +#endif + +// + +// APP_USBD_STRINGS_USER - Default values for user strings. + +// Note: This value is not editable in Configuration Wizard. +// This value stores all application specific user strings with the default initialization. +// The setup is done by X-macros. +// Expected macro parameters: +// @code +// X(mnemonic, [=str_idx], ...) +// @endcode +// - @c mnemonic: Mnemonic of the string descriptor that would be added to +// @ref app_usbd_string_desc_idx_t enumerator. +// - @c str_idx : String index value, can be set or left empty. +// For example, WinUSB driver requires descriptor to be present on 0xEE index. +// Then use X(USBD_STRING_WINUSB, =0xEE, (APP_USBD_STRING_DESC(...))) +// - @c ... : List of string descriptors for each defined language. +#ifndef APP_USBD_STRINGS_USER +#define APP_USBD_STRINGS_USER X(APP_USER_1, , APP_USBD_STRING_DESC("User 1")) +#endif + +// + +// APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef APP_USBD_CONFIG_LOG_ENABLED +#define APP_USBD_CONFIG_LOG_ENABLED 0 +#endif + +// + +// + +// USBD_ENABLED - nrf_drv_usbd - USB driver +//========================================================== +#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) +#ifndef USBD_ENABLED +#define USBD_ENABLED 1 +#endif +#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 +#ifndef USBD_ENABLED +#define USBD_ENABLED 0 +#endif +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 + +// Enable power USB detection. + +// Configure if the example supports USB port connection. + +#ifndef USBD_POWER_DETECTION +#define USBD_POWER_DETECTION 1 +#endif + +// USBD_CONFIG_IRQ_PRIORITY - Interrupt priority + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef USBD_CONFIG_IRQ_PRIORITY +#define USBD_CONFIG_IRQ_PRIORITY 7 +#endif + +// USBD_CONFIG_DMASCHEDULER_MODE - USBD SMA scheduler working scheme + +// <0=> Prioritized access +// <1=> Round Robin + +#ifndef USBD_CONFIG_DMASCHEDULER_MODE +#define USBD_CONFIG_DMASCHEDULER_MODE 0 +#endif + +// USBD_CONFIG_DMASCHEDULER_ISO_BOOST - Give priority to isochronous transfers + + +// This option gives priority to isochronous transfers. +// Enabling it assures that isochronous transfers are always processed, +// even if multiple other transfers are pending. +// Isochronous endpoints are prioritized before the usbd_dma_scheduler_algorithm +// function is called, so the option is independent of the algorithm chosen. + +#ifndef USBD_CONFIG_DMASCHEDULER_ISO_BOOST +#define USBD_CONFIG_DMASCHEDULER_ISO_BOOST 1 +#endif + +// USBD_CONFIG_ISO_IN_ZLP - Respond to an IN token on ISO IN endpoint with ZLP when no data is ready + + +// If set, ISO IN endpoint will respond to an IN token with ZLP when no data is ready to be sent. +// Else, there will be no response. + +#ifndef USBD_CONFIG_ISO_IN_ZLP +#define USBD_CONFIG_ISO_IN_ZLP 0 +#endif + +#define NRFX_USBD_ENABLED USBD_ENABLED +#define NRFX_USBD_POWER_DETECTION USBD_POWER_DETECTION +#define NRFX_USBD_CONFIG_IRQ_PRIORITY USBD_CONFIG_IRQ_PRIORITY +#define NRFX_USBD_CONFIG_DMASCHEDULER_MODE USBD_CONFIG_DMASCHEDULER_MODE +#define NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST USBD_CONFIG_DMASCHEDULER_ISO_BOOST +#define NRFX_USBD_CONFIG_ISO_IN_ZLP USBD_CONFIG_ISO_IN_ZLP + +// + + +// Application info used by the USB DFU. + +// @def APP_NAME + +// Application name in a human readable string. + + +#ifndef APP_NAME +#define APP_NAME "OpenThread App" +#endif + + +// APP_VERSION_MAJOR + +// Application version major version. + +#ifndef APP_VERSION_MAJOR +#define APP_VERSION_MAJOR 1 +#endif + + +// APP_VERSION_MINOR + +// Application version minor version. + + +#ifndef APP_VERSION_MINOR +#define APP_VERSION_MINOR 0 +#endif + + +// APP_VERSION_PATCH + +// Application version patch version. + + +#ifndef APP_VERSION_PATCH +#define APP_VERSION_PATCH 0 +#endif + + +// @def APP_ID + +// Application ID. + + +#ifndef APP_ID +#define APP_ID 1 +#endif + + +// APP_VERSION_PRERELEASE + +// Application prerelease tag. + + +#ifndef APP_VERSION_PRERELEASE +#define APP_VERSION_PRERELEASE "" +#endif + + +// APP_VERSION_METADATA + +// Application metadata. + + +#ifndef APP_VERSION_METADATA +#define APP_VERSION_METADATA "" +#endif + +// app_usbd_cdc_acm - USB CDC ACM class + +//========================================================== +// APP_USBD_CDC_ACM_ENABLED - app_usbd_cdc_acm - USB CDC ACM class + + +#ifndef APP_USBD_CDC_ACM_ENABLED +#define APP_USBD_CDC_ACM_ENABLED 1 +#endif + +// APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE - Send ZLP on write with same size as endpoint + + +// If enabled, CDC ACM class will automatically send a zero length packet after transfer which has the same size as endpoint. +// This may limit throughput if a lot of binary data is sent, but in terminal mode operation it makes sure that the data is always displayed right after it is sent. + +#ifndef APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE +#define APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE 1 +#endif + +// + +// app_usbd_nrf_dfu_trigger - USB Trigger library + +//========================================================== +// APP_USBD_NRF_DFU_TRIGGER_ENABLED + + +// Enable possibility to enter the bootloader from the application via a software trigger send over USB. +// Requires configured BSP_SELF_PINRESET_PIN which is a GPIO pin connected to the reset pin. + +#ifndef APP_USBD_NRF_DFU_TRIGGER_ENABLED +#define APP_USBD_NRF_DFU_TRIGGER_ENABLED 0 +#endif + +// BSP_SELF_PINRESET_PIN + + +// Enable possibility to enter the bootloader from the application via a software trigger send over USB. +// Requires configured BSP_SELF_PINRESET_PIN which is a GPIO pin connected to the reset pin. +// NRF_GPIO_PIN_MAP(0,19) is a pin used on Nordic PCA10059 Dongle. + +#ifndef BSP_SELF_PINRESET_PIN +#define BSP_SELF_PINRESET_PIN NRF_GPIO_PIN_MAP(0, 19) +#endif + +// NRF_DFU_TRIGGER_USB_USB_SHARED + +// Flag indicating whether USB is used for other purposes in the application. + +#ifndef NRF_DFU_TRIGGER_USB_USB_SHARED +#define NRF_DFU_TRIGGER_USB_USB_SHARED 1 +#endif + + +// NRF_DFU_TRIGGER_USB_INTERFACE_NUM + +// The USB interface to use for the DFU Trigger library. +// According to the USB Specification, interface numbers cannot have gaps. Tailor this value to adhere to this +// limitation. Takes values between 0-255 + +#ifndef NRF_DFU_TRIGGER_USB_INTERFACE_NUM +#define NRF_DFU_TRIGGER_USB_INTERFACE_NUM 0 +#endif + +// + +//========================================================== + +// nrf_log - Logging + +//========================================================== +// NRF_LOG_ENABLED - Logging module for nRF5 SDK +//========================================================== +#ifndef NRF_LOG_ENABLED +#define NRF_LOG_ENABLED 0 +#endif + +// +// + +// segger_rtt - SEGGER RTT + +//========================================================== +// SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer. +// Note that either @ref NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE +// or this value is actually used. It depends on which one is bigger. + +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 512 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Size of upstream buffer. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of upstream buffer. +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Size of upstream buffer. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_DEFAULT_MODE - RTT behavior if the buffer is full. + + +// The following modes are supported: +// - SKIP - Do not block, output nothing. +// - TRIM - Do not block, output as much as fits. +// - BLOCK - Wait until there is space in the buffer. +// <0=> SKIP +// <1=> TRIM +// <2=> BLOCK_IF_FIFO_FULL + +#ifndef SEGGER_RTT_CONFIG_DEFAULT_MODE +#define SEGGER_RTT_CONFIG_DEFAULT_MODE 0 +#endif + +// +//========================================================== + +// CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver +//========================================================== +#ifndef CLOCK_ENABLED +#define CLOCK_ENABLED 1 +#endif +// CLOCK_CONFIG_XTAL_FREQ - HF XTAL Frequency + +// <0=> Default (64 MHz) + +#ifndef CLOCK_CONFIG_XTAL_FREQ +#define CLOCK_CONFIG_XTAL_FREQ 0 +#endif + +// CLOCK_CONFIG_LF_SRC - LF Clock Source + +// <0=> RC +// <1=> XTAL +// <2=> Synth + +#ifndef CLOCK_CONFIG_LF_SRC +#define CLOCK_CONFIG_LF_SRC 1 +#endif + +// CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef CLOCK_CONFIG_IRQ_PRIORITY +#define CLOCK_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// POWER_ENABLED - nrf_drv_power - POWER peripheral driver +//========================================================== + +#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) +#ifndef POWER_ENABLED +#define POWER_ENABLED 1 +#endif +#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 +#ifndef POWER_ENABLED +#define POWER_ENABLED 0 +#endif +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 + +// POWER_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef POWER_CONFIG_IRQ_PRIORITY +#define POWER_CONFIG_IRQ_PRIORITY 7 +#endif + +// POWER_CONFIG_DEFAULT_DCDCEN - The default configuration of main DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCEN +#define POWER_CONFIG_DEFAULT_DCDCEN 0 +#endif + +// POWER_CONFIG_DEFAULT_DCDCENHV - The default configuration of High Voltage DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCENHV +#define POWER_CONFIG_DEFAULT_DCDCENHV 0 +#endif + +// + + +// NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver +//========================================================== +#if (SPIS_AS_SERIAL_TRANSPORT == 1) +#ifndef NRFX_SPIS_ENABLED +#define NRFX_SPIS_ENABLED 1 +#endif +#else // SPIS_AS_SERIAL_TRANSPORT == 1 +#ifndef NRFX_SPIS_ENABLED +#define NRFX_SPIS_ENABLED 0 +#endif +#endif // SPIS_AS_SERIAL_TRANSPORT == 1 + +// NRFX_SPIS0_ENABLED - Enable SPIS0 instance + +#ifndef NRFX_SPIS0_ENABLED +#define NRFX_SPIS0_ENABLED 1 +#endif + +// NRFX_SPIS1_ENABLED - Enable SPIS1 instance + + +#ifndef NRFX_SPIS1_ENABLED +#define NRFX_SPIS1_ENABLED 0 +#endif + +// NRFX_SPIS2_ENABLED - Enable SPIS2 instance + + +#ifndef NRFX_SPIS2_ENABLED +#define NRFX_SPIS2_ENABLED 0 +#endif + +// NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// NRFX_SPIS_DEFAULT_DEF - SPIS default DEF character <0-255> + + +#ifndef NRFX_SPIS_DEFAULT_DEF +#define NRFX_SPIS_DEFAULT_DEF 255 +#endif + +// NRFX_SPIS_DEFAULT_ORC - SPIS default ORC character <0-255> + + +#ifndef NRFX_SPIS_DEFAULT_ORC +#define NRFX_SPIS_DEFAULT_ORC 255 +#endif + +// NRFX_SPIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_SPIS_CONFIG_LOG_ENABLED +#define NRFX_SPIS_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_SPIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_SPIS_CONFIG_LOG_LEVEL +#define NRFX_SPIS_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_SPIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SPIS_CONFIG_INFO_COLOR +#define NRFX_SPIS_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_SPIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SPIS_CONFIG_DEBUG_COLOR +#define NRFX_SPIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// SYSTICK_ENABLED - nrf_drv_systick - SysTick driver + +#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) +#ifndef SYSTICK_ENABLED +#define SYSTICK_ENABLED 1 +#endif +#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 +#ifndef SYSTICK_ENABLED +#define SYSTICK_ENABLED 0 +#endif +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 + +#endif //SDK_CONFIG_H diff --git a/third_party/NordicSemiconductor/dependencies/sdk_errors.h b/third_party/NordicSemiconductor/dependencies/sdk_errors.h index 2f125d25a..b482522aa 100644 --- a/third_party/NordicSemiconductor/dependencies/sdk_errors.h +++ b/third_party/NordicSemiconductor/dependencies/sdk_errors.h @@ -1,167 +1,167 @@ -/** - * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup sdk_error SDK Error codes - * @{ - * @ingroup app_common - * @{ - * @details Error codes are 32-bit unsigned integers with the most significant 16-bit reserved for - * identifying the module where the error occurred while the least least significant LSB - * are used to provide the cause or nature of error. Each module is assigned a 16-bit - * unsigned integer. Which it will use to identify all errors that occurred in it. 16-bit - * LSB range is with module id as the MSB in the 32-bit error code is reserved for the - * module. As an example, if 0x8800 identifies a certain SDK module, all values from - * 0x88000000 - 0x8800FFFF are reserved for this module. - * It should be noted that common error reasons have been assigned values to make it - * possible to decode error reason easily. As an example, lets module uninitialized has - * been assigned an error code 0x000A0. Then, if application encounters an error code - * 0xZZZZ00A0, it knows that it accessing a certain module without initializing it. - * Apart from this, each module is allowed to define error codes that are not covered by - * the common ones, however, these values are defined in a range that does not conflict - * with common error values. For module, specific error however, it is possible that the - * same error value is used by two different modules to indicated errors of very different - * nature. If error is already defined by the NRF common error codes, these are reused. - * A range is reserved for application as well, it can use this range for defining - * application specific errors. - * - * @note Success code, NRF_SUCCESS, does not include any module identifier. - - */ - -#ifndef SDK_ERRORS_H__ -#define SDK_ERRORS_H__ - -#include -#include "nrf_error.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup sdk_err_base Base defined for SDK Modules - * @{ - */ -#define NRF_ERROR_SDK_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x8000) /**< Base value defined for SDK module identifiers. */ -#define NRF_ERROR_SDK_COMMON_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x0080) /**< Base error value to be used for SDK error values. */ -/** @} */ - -/** - * @defgroup sdk_module_codes Codes reserved as identification for module where the error occurred. - * @{ - */ -#define NRF_ERROR_MEMORY_MANAGER_ERR_BASE (0x8100) /**< Base address for Memory Manager related errors. */ -#define NRF_ERROR_PERIPH_DRIVERS_ERR_BASE (0x8200) /**< Base address for Peripheral drivers related errors. */ -#define NRF_ERROR_GAZELLE_ERR_BASE (0x8300) /**< Base address for Gazelle related errors. */ -#define NRF_ERROR_BLE_IPSP_ERR_BASE (0x8400) /**< Base address for BLE IPSP related errors. */ -#define NRF_ERROR_CRYPTO_ERR_BASE (0x8500) /**< Base address for crypto related errors. */ -/** @} */ - - -/** - * @defgroup sdk_iot_errors Codes reserved as identification for IoT errors. - * @{ - */ -#define NRF_ERROR_IOT_ERR_BASE_START (0xA000) -#define NRF_ERROR_IOT_ERR_BASE_STOP (0xAFFF) -/** @} */ - - -/** - * @defgroup sdk_common_errors Codes reserved as identification for common errors. - * @{ - */ -#define NRF_ERROR_MODULE_NOT_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0000) ///< Module not initialized -#define NRF_ERROR_MUTEX_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0001) ///< Mutex initialization failed -#define NRF_ERROR_MUTEX_LOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0002) ///< Mutex lock failed -#define NRF_ERROR_MUTEX_UNLOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0003) ///< Mutex unlock failed -#define NRF_ERROR_MUTEX_COND_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0004) ///< Mutex conditional initialization failed -#define NRF_ERROR_MODULE_ALREADY_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0005) ///< Module already initialized -#define NRF_ERROR_STORAGE_FULL (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0006) ///< Storage full -#define NRF_ERROR_API_NOT_IMPLEMENTED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0010) ///< API not implemented -#define NRF_ERROR_FEATURE_NOT_ENABLED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0011) ///< Feature not enabled -#define NRF_ERROR_IO_PENDING (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0012) ///< Input/Output pending -/** @} */ - - -/** - * @defgroup drv_specific_errors Error / status codes specific to drivers. - * @{ - */ -#define NRF_ERROR_DRV_TWI_ERR_OVERRUN (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0000) -#define NRF_ERROR_DRV_TWI_ERR_ANACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0001) -#define NRF_ERROR_DRV_TWI_ERR_DNACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0002) -/** @} */ - - -/** - * @defgroup ble_ipsp_errors IPSP codes - * @brief Error and status codes specific to IPSP. - * @{ - */ -#define NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0000) -#define NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0001) -#define NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0002) -#define NRF_ERROR_BLE_IPSP_PEER_REJECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0003) -/* @} */ - - -/** - * @brief API Result. - * - * @details Indicates success or failure of an API procedure. In case of failure, a comprehensive - * error code indicating cause or reason for failure is provided. - * - * Though called an API result, it could used in Asynchronous notifications callback along - * with asynchronous callback as event result. This mechanism is employed when an event - * marks the end of procedure initiated using API. API result, in this case, will only be - * an indicative of whether the procedure has been requested successfully. - */ -typedef uint32_t ret_code_t; - -/** @} */ -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif // SDK_ERRORS_H__ +/** + * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_error SDK Error codes + * @{ + * @ingroup app_common + * @{ + * @details Error codes are 32-bit unsigned integers with the most significant 16-bit reserved for + * identifying the module where the error occurred while the least least significant LSB + * are used to provide the cause or nature of error. Each module is assigned a 16-bit + * unsigned integer. Which it will use to identify all errors that occurred in it. 16-bit + * LSB range is with module id as the MSB in the 32-bit error code is reserved for the + * module. As an example, if 0x8800 identifies a certain SDK module, all values from + * 0x88000000 - 0x8800FFFF are reserved for this module. + * It should be noted that common error reasons have been assigned values to make it + * possible to decode error reason easily. As an example, lets module uninitialized has + * been assigned an error code 0x000A0. Then, if application encounters an error code + * 0xZZZZ00A0, it knows that it accessing a certain module without initializing it. + * Apart from this, each module is allowed to define error codes that are not covered by + * the common ones, however, these values are defined in a range that does not conflict + * with common error values. For module, specific error however, it is possible that the + * same error value is used by two different modules to indicated errors of very different + * nature. If error is already defined by the NRF common error codes, these are reused. + * A range is reserved for application as well, it can use this range for defining + * application specific errors. + * + * @note Success code, NRF_SUCCESS, does not include any module identifier. + + */ + +#ifndef SDK_ERRORS_H__ +#define SDK_ERRORS_H__ + +#include +#include "nrf_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup sdk_err_base Base defined for SDK Modules + * @{ + */ +#define NRF_ERROR_SDK_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x8000) /**< Base value defined for SDK module identifiers. */ +#define NRF_ERROR_SDK_COMMON_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x0080) /**< Base error value to be used for SDK error values. */ +/** @} */ + +/** + * @defgroup sdk_module_codes Codes reserved as identification for module where the error occurred. + * @{ + */ +#define NRF_ERROR_MEMORY_MANAGER_ERR_BASE (0x8100) /**< Base address for Memory Manager related errors. */ +#define NRF_ERROR_PERIPH_DRIVERS_ERR_BASE (0x8200) /**< Base address for Peripheral drivers related errors. */ +#define NRF_ERROR_GAZELLE_ERR_BASE (0x8300) /**< Base address for Gazelle related errors. */ +#define NRF_ERROR_BLE_IPSP_ERR_BASE (0x8400) /**< Base address for BLE IPSP related errors. */ +#define NRF_ERROR_CRYPTO_ERR_BASE (0x8500) /**< Base address for crypto related errors. */ +/** @} */ + + +/** + * @defgroup sdk_iot_errors Codes reserved as identification for IoT errors. + * @{ + */ +#define NRF_ERROR_IOT_ERR_BASE_START (0xA000) +#define NRF_ERROR_IOT_ERR_BASE_STOP (0xAFFF) +/** @} */ + + +/** + * @defgroup sdk_common_errors Codes reserved as identification for common errors. + * @{ + */ +#define NRF_ERROR_MODULE_NOT_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0000) ///< Module not initialized +#define NRF_ERROR_MUTEX_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0001) ///< Mutex initialization failed +#define NRF_ERROR_MUTEX_LOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0002) ///< Mutex lock failed +#define NRF_ERROR_MUTEX_UNLOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0003) ///< Mutex unlock failed +#define NRF_ERROR_MUTEX_COND_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0004) ///< Mutex conditional initialization failed +#define NRF_ERROR_MODULE_ALREADY_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0005) ///< Module already initialized +#define NRF_ERROR_STORAGE_FULL (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0006) ///< Storage full +#define NRF_ERROR_API_NOT_IMPLEMENTED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0010) ///< API not implemented +#define NRF_ERROR_FEATURE_NOT_ENABLED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0011) ///< Feature not enabled +#define NRF_ERROR_IO_PENDING (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0012) ///< Input/Output pending +/** @} */ + + +/** + * @defgroup drv_specific_errors Error / status codes specific to drivers. + * @{ + */ +#define NRF_ERROR_DRV_TWI_ERR_OVERRUN (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0000) +#define NRF_ERROR_DRV_TWI_ERR_ANACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0001) +#define NRF_ERROR_DRV_TWI_ERR_DNACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0002) +/** @} */ + + +/** + * @defgroup ble_ipsp_errors IPSP codes + * @brief Error and status codes specific to IPSP. + * @{ + */ +#define NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0000) +#define NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0001) +#define NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0002) +#define NRF_ERROR_BLE_IPSP_PEER_REJECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0003) +/* @} */ + + +/** + * @brief API Result. + * + * @details Indicates success or failure of an API procedure. In case of failure, a comprehensive + * error code indicating cause or reason for failure is provided. + * + * Though called an API result, it could used in Asynchronous notifications callback along + * with asynchronous callback as event result. This mechanism is employed when an event + * marks the end of procedure initiated using API. API result, in this case, will only be + * an indicative of whether the procedure has been requested successfully. + */ +typedef uint32_t ret_code_t; + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_ERRORS_H__ diff --git a/third_party/NordicSemiconductor/dependencies/sdk_macros.h b/third_party/NordicSemiconductor/dependencies/sdk_macros.h index 7658f9dff..b93821d4a 100644 --- a/third_party/NordicSemiconductor/dependencies/sdk_macros.h +++ b/third_party/NordicSemiconductor/dependencies/sdk_macros.h @@ -1,215 +1,215 @@ -/** - * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - - * @defgroup sdk_common_macros SDK Common Header - * @ingroup app_common - * @brief Macros for parameter checking and similar tasks - * @{ - */ - -#ifndef SDK_MACROS_H__ -#define SDK_MACROS_H__ - -#include "nrf_assert.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/**@brief Macro for parameter checking. - * - * If @p _cond evaluates to true, does nothing. Otherwise, - * if @p _module ## _PARAM_CHECK_DISABLED is @e not set (default), prints an error message - * if @p _printfn is provided, and returns from the calling function context with code @p _err. - * If @p _module ## _PARAM_CHECK_DISABLED is set, behaves like the ASSERT macro. - * - * Parameter checking implemented using this macro can be optionally turned off for release code. - * Only disable runtime parameter checks if size if a major concern. - * - * @param _module The module name. - * @param _cond The condition to be evaluated. - * @param _err The error to be returned. - * @param _printfn A printf-compatible function used to log the error. - * Leave empty if no logging is needed. - * - * @hideinitializer - */ -/*lint -esym(666, NRF_PARAM_CHECK*) : Expression with side effects passed to macro */ -#define NRF_PARAM_CHECK(_module, _cond, _err, _printfn) \ - do \ - { \ - if ((_cond)) \ - { \ - /* Do nothing. */ \ - } \ - else if (!(_module ## _PARAM_CHECK_DISABLED)) \ - { \ - _printfn("%s check failed in %s() with value 0x%x.", #_cond, __func__, _err); \ - return (_err); \ - } \ - else \ - { \ - ASSERT((_cond)); \ - } \ - } while (0); - - -/**@brief Macro for verifying statement to be true. It will cause the exterior function to return - * err_code if the statement is not true. - * - * @param[in] statement Statement to test. - * @param[in] err_code Error value to return if test was invalid. - * - * @retval nothing, but will cause the exterior function to return @p err_code if @p statement - * is false. - */ -#define VERIFY_TRUE(statement, err_code) \ -do \ -{ \ - if (!(statement)) \ - { \ - return err_code; \ - } \ -} while (0) - - -/**@brief Macro for verifying statement to be true. It will cause the exterior function to return - * if the statement is not true. - * - * @param[in] statement Statement to test. - */ -#define VERIFY_TRUE_VOID(statement) VERIFY_TRUE((statement), ) - - -/**@brief Macro for verifying statement to be false. It will cause the exterior function to return - * err_code if the statement is not false. - * - * @param[in] statement Statement to test. - * @param[in] err_code Error value to return if test was invalid. - * - * @retval nothing, but will cause the exterior function to return @p err_code if @p statement - * is true. - */ -#define VERIFY_FALSE(statement, err_code) \ -do \ -{ \ - if ((statement)) \ - { \ - return err_code; \ - } \ -} while (0) - - -/**@brief Macro for verifying statement to be false. It will cause the exterior function to return - * if the statement is not false. - * - * @param[in] statement Statement to test. - */ -#define VERIFY_FALSE_VOID(statement) VERIFY_FALSE((statement), ) - - -/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior - * function to return error code of statement if it is not @ref NRF_SUCCESS. - * - * @param[in] statement Statement to check against NRF_SUCCESS. - */ -#define VERIFY_SUCCESS(statement) \ -do \ -{ \ - uint32_t _err_code = (uint32_t) (statement); \ - if (_err_code != NRF_SUCCESS) \ - { \ - return _err_code; \ - } \ -} while(0) - - -/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior - * function to return if the err_code is not @ref NRF_SUCCESS. - * - * @param[in] err_code The error code to check. - */ -#define VERIFY_SUCCESS_VOID(err_code) VERIFY_TRUE_VOID((err_code) == NRF_SUCCESS) - - -/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to - * return @ref NRF_ERROR_INVALID_STATE if not. - * - * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED - * should be true if the module is initialized, false if not. - */ -#define VERIFY_MODULE_INITIALIZED() VERIFY_TRUE((MODULE_INITIALIZED), NRF_ERROR_INVALID_STATE) - - -/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to - * return if not. - * - * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED - * should be true if the module is initialized, false if not. - */ -#define VERIFY_MODULE_INITIALIZED_VOID() VERIFY_TRUE_VOID((MODULE_INITIALIZED)) - - -/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to - * return if not. - * - * @param[in] param The variable to check if is NULL. - */ -#define VERIFY_PARAM_NOT_NULL(param) VERIFY_FALSE(((param) == NULL), NRF_ERROR_NULL) - - -/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to - * return if not. - * - * @param[in] param The variable to check if is NULL. - */ -#define VERIFY_PARAM_NOT_NULL_VOID(param) VERIFY_FALSE_VOID(((param) == NULL)) - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif // SDK_MACROS_H__ - +/** + * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + + * @defgroup sdk_common_macros SDK Common Header + * @ingroup app_common + * @brief Macros for parameter checking and similar tasks + * @{ + */ + +#ifndef SDK_MACROS_H__ +#define SDK_MACROS_H__ + +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Macro for parameter checking. + * + * If @p _cond evaluates to true, does nothing. Otherwise, + * if @p _module ## _PARAM_CHECK_DISABLED is @e not set (default), prints an error message + * if @p _printfn is provided, and returns from the calling function context with code @p _err. + * If @p _module ## _PARAM_CHECK_DISABLED is set, behaves like the ASSERT macro. + * + * Parameter checking implemented using this macro can be optionally turned off for release code. + * Only disable runtime parameter checks if size if a major concern. + * + * @param _module The module name. + * @param _cond The condition to be evaluated. + * @param _err The error to be returned. + * @param _printfn A printf-compatible function used to log the error. + * Leave empty if no logging is needed. + * + * @hideinitializer + */ +/*lint -esym(666, NRF_PARAM_CHECK*) : Expression with side effects passed to macro */ +#define NRF_PARAM_CHECK(_module, _cond, _err, _printfn) \ + do \ + { \ + if ((_cond)) \ + { \ + /* Do nothing. */ \ + } \ + else if (!(_module ## _PARAM_CHECK_DISABLED)) \ + { \ + _printfn("%s check failed in %s() with value 0x%x.", #_cond, __func__, _err); \ + return (_err); \ + } \ + else \ + { \ + ASSERT((_cond)); \ + } \ + } while (0); + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * err_code if the statement is not true. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is false. + */ +#define VERIFY_TRUE(statement, err_code) \ +do \ +{ \ + if (!(statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * if the statement is not true. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_TRUE_VOID(statement) VERIFY_TRUE((statement), ) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * err_code if the statement is not false. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is true. + */ +#define VERIFY_FALSE(statement, err_code) \ +do \ +{ \ + if ((statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * if the statement is not false. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_FALSE_VOID(statement) VERIFY_FALSE((statement), ) + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return error code of statement if it is not @ref NRF_SUCCESS. + * + * @param[in] statement Statement to check against NRF_SUCCESS. + */ +#define VERIFY_SUCCESS(statement) \ +do \ +{ \ + uint32_t _err_code = (uint32_t) (statement); \ + if (_err_code != NRF_SUCCESS) \ + { \ + return _err_code; \ + } \ +} while(0) + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return if the err_code is not @ref NRF_SUCCESS. + * + * @param[in] err_code The error code to check. + */ +#define VERIFY_SUCCESS_VOID(err_code) VERIFY_TRUE_VOID((err_code) == NRF_SUCCESS) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return @ref NRF_ERROR_INVALID_STATE if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#define VERIFY_MODULE_INITIALIZED() VERIFY_TRUE((MODULE_INITIALIZED), NRF_ERROR_INVALID_STATE) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#define VERIFY_MODULE_INITIALIZED_VOID() VERIFY_TRUE_VOID((MODULE_INITIALIZED)) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#define VERIFY_PARAM_NOT_NULL(param) VERIFY_FALSE(((param) == NULL), NRF_ERROR_NULL) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#define VERIFY_PARAM_NOT_NULL_VOID(param) VERIFY_FALSE_VOID(((param) == NULL)) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_MACROS_H__ + diff --git a/third_party/NordicSemiconductor/dependencies/sdk_os.h b/third_party/NordicSemiconductor/dependencies/sdk_os.h index 6e505c0f6..dd356bb00 100644 --- a/third_party/NordicSemiconductor/dependencies/sdk_os.h +++ b/third_party/NordicSemiconductor/dependencies/sdk_os.h @@ -1,76 +1,76 @@ -/** - * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @cond */ -/**@file - * - * @defgroup sdk_os SDK OS Abstraction - * @ingroup experimental_api - * @details In order to made SDK modules independent of use of an embedded OS, and permit - * application with varied task architecture, SDK abstracts the OS specific - * elements here in order to make all other modules agnostic to the OS or task - * architecture. - * @{ - */ - -#ifndef SDK_OS_H__ -#define SDK_OS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define SDK_MUTEX_DEFINE(X) -#define SDK_MUTEX_INIT(X) -#define SDK_MUTEX_LOCK(X) -#define SDK_MUTEX_UNLOCK(X) - -/** - * @defgroup os_data_type Data types. - */ - -/** @} */ -/** @endcond */ - -#ifdef __cplusplus -} -#endif - -#endif // SDK_OS_H__ - +/** + * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @cond */ +/**@file + * + * @defgroup sdk_os SDK OS Abstraction + * @ingroup experimental_api + * @details In order to made SDK modules independent of use of an embedded OS, and permit + * application with varied task architecture, SDK abstracts the OS specific + * elements here in order to make all other modules agnostic to the OS or task + * architecture. + * @{ + */ + +#ifndef SDK_OS_H__ +#define SDK_OS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SDK_MUTEX_DEFINE(X) +#define SDK_MUTEX_INIT(X) +#define SDK_MUTEX_LOCK(X) +#define SDK_MUTEX_UNLOCK(X) + +/** + * @defgroup os_data_type Data types. + */ + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_OS_H__ + diff --git a/third_party/NordicSemiconductor/dependencies/sdk_resources.h b/third_party/NordicSemiconductor/dependencies/sdk_resources.h index 3c5e5584c..0185632f7 100644 --- a/third_party/NordicSemiconductor/dependencies/sdk_resources.h +++ b/third_party/NordicSemiconductor/dependencies/sdk_resources.h @@ -1,86 +1,86 @@ -/** - * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * @brief Definition file for resource usage by SoftDevice, ESB and Gazell. - */ - -#ifndef SDK_RESOURCES_H__ -#define SDK_RESOURCES_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(SOFTDEVICE_PRESENT) || defined (BLE_STACK_SUPPORT_REQD) || defined (ANT_STACK_SUPPORT_REQD) - #include "nrf_sd_def.h" -#else - #define SD_PPI_RESTRICTED 0uL /**< 1 if PPI peripheral is restricted, 0 otherwise. */ - #define SD_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by SotfDevice (not available to th spplication). */ - #define SD_PPI_GROUPS_USED 0uL /**< PPI groups utilized by SotfDevice (not available to th spplication). */ - #define SD_TIMERS_USED 0uL /**< Timers used by SoftDevice. */ - #define SD_SWI_USED 0uL /**< Software interrupts used by SoftDevice. */ -#endif - -#ifdef GAZELL_PRESENT - #include "nrf_gzll_resources.h" -#else - #define GZLL_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by Gazell (not available to th spplication). */ - #define GZLL_TIMERS_USED 0uL /**< Timers used by Gazell. */ - #define GZLL_SWI_USED 0uL /**< Software interrupts used by Gazell */ -#endif - -#ifdef ESB_PRESENT - #include "nrf_esb_resources.h" -#else - #define ESB_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by ESB (not available to th spplication). */ - #define ESB_TIMERS_USED 0uL /**< Timers used by ESB. */ - #define ESB_SWI_USED 0uL /**< Software interrupts used by ESB */ -#endif - -#define NRF_PPI_CHANNELS_USED (SD_PPI_CHANNELS_USED | GZLL_PPI_CHANNELS_USED | ESB_PPI_CHANNELS_USED) -#define NRF_PPI_GROUPS_USED (SD_PPI_GROUPS_USED) -#define NRF_SWI_USED (SD_SWI_USED | GZLL_SWI_USED | ESB_SWI_USED) -#define NRF_TIMERS_USED (SD_TIMERS_USED | GZLL_TIMERS_USED | ESB_TIMERS_USED) - -#ifdef __cplusplus -} -#endif - -#endif // SDK_RESOURCES_H__ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * @brief Definition file for resource usage by SoftDevice, ESB and Gazell. + */ + +#ifndef SDK_RESOURCES_H__ +#define SDK_RESOURCES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(SOFTDEVICE_PRESENT) || defined (BLE_STACK_SUPPORT_REQD) || defined (ANT_STACK_SUPPORT_REQD) + #include "nrf_sd_def.h" +#else + #define SD_PPI_RESTRICTED 0uL /**< 1 if PPI peripheral is restricted, 0 otherwise. */ + #define SD_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by SotfDevice (not available to th spplication). */ + #define SD_PPI_GROUPS_USED 0uL /**< PPI groups utilized by SotfDevice (not available to th spplication). */ + #define SD_TIMERS_USED 0uL /**< Timers used by SoftDevice. */ + #define SD_SWI_USED 0uL /**< Software interrupts used by SoftDevice. */ +#endif + +#ifdef GAZELL_PRESENT + #include "nrf_gzll_resources.h" +#else + #define GZLL_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by Gazell (not available to th spplication). */ + #define GZLL_TIMERS_USED 0uL /**< Timers used by Gazell. */ + #define GZLL_SWI_USED 0uL /**< Software interrupts used by Gazell */ +#endif + +#ifdef ESB_PRESENT + #include "nrf_esb_resources.h" +#else + #define ESB_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by ESB (not available to th spplication). */ + #define ESB_TIMERS_USED 0uL /**< Timers used by ESB. */ + #define ESB_SWI_USED 0uL /**< Software interrupts used by ESB */ +#endif + +#define NRF_PPI_CHANNELS_USED (SD_PPI_CHANNELS_USED | GZLL_PPI_CHANNELS_USED | ESB_PPI_CHANNELS_USED) +#define NRF_PPI_GROUPS_USED (SD_PPI_GROUPS_USED) +#define NRF_SWI_USED (SD_SWI_USED | GZLL_SWI_USED | ESB_SWI_USED) +#define NRF_TIMERS_USED (SD_TIMERS_USED | GZLL_TIMERS_USED | ESB_TIMERS_USED) + +#ifdef __cplusplus +} +#endif + +#endif // SDK_RESOURCES_H__ diff --git a/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.c b/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.c index d8da26882..d45ca8d9d 100644 --- a/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.c +++ b/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.c @@ -1,601 +1,601 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -#include "nrf_drv_clock.h" - -#ifdef SOFTDEVICE_PRESENT -#include "nrf_sdh.h" -#include "nrf_sdh_soc.h" -#endif - -#define NRF_LOG_MODULE_NAME clock -#if CLOCK_CONFIG_LOG_ENABLED - #define NRF_LOG_LEVEL CLOCK_CONFIG_LOG_LEVEL - #define NRF_LOG_INFO_COLOR CLOCK_CONFIG_INFO_COLOR - #define NRF_LOG_DEBUG_COLOR CLOCK_CONFIG_DEBUG_COLOR -#else //CLOCK_CONFIG_LOG_ENABLED - #define NRF_LOG_LEVEL 0 -#endif //CLOCK_CONFIG_LOG_ENABLED -#include "nrf_log.h" -NRF_LOG_MODULE_REGISTER(); - -#define EVT_TO_STR(event) \ - (event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \ - (event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \ - (event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \ - (event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : \ - "UNKNOWN EVENT")))) - - -/*lint -save -e652 */ -#define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC -#define NRF_CLOCK_LFCLK_Xtal CLOCK_LFCLKSRC_SRC_Xtal -#define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth -/*lint -restore */ - -#if (CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC) && !defined(SOFTDEVICE_PRESENT) -#define CALIBRATION_SUPPORT 1 -#else -#define CALIBRATION_SUPPORT 0 -#endif -typedef enum -{ - CAL_STATE_IDLE, - CAL_STATE_CT, - CAL_STATE_HFCLK_REQ, - CAL_STATE_CAL, - CAL_STATE_ABORT, -} nrf_drv_clock_cal_state_t; - -/**@brief CLOCK control block. */ -typedef struct -{ - bool module_initialized; /*< Indicate the state of module */ - volatile bool hfclk_on; /*< High-frequency clock state. */ - volatile bool lfclk_on; /*< Low-frequency clock state. */ - volatile uint32_t hfclk_requests; /*< High-frequency clock request counter. */ - volatile nrf_drv_clock_handler_item_t * p_hf_head; - volatile uint32_t lfclk_requests; /*< Low-frequency clock request counter. */ - volatile nrf_drv_clock_handler_item_t * p_lf_head; -#if CALIBRATION_SUPPORT - nrf_drv_clock_handler_item_t cal_hfclk_started_handler_item; - nrf_drv_clock_event_handler_t cal_done_handler; - volatile nrf_drv_clock_cal_state_t cal_state; -#endif // CALIBRATION_SUPPORT -} nrf_drv_clock_cb_t; - -static nrf_drv_clock_cb_t m_clock_cb; - -static void clock_irq_handler(nrfx_clock_evt_type_t evt); - -static void lfclk_stop(void) -{ -#if CALIBRATION_SUPPORT - nrfx_clock_calibration_timer_stop(); -#endif - -#ifdef SOFTDEVICE_PRESENT - // If LFCLK is requested to stop while SD is still enabled, - // it indicates an error in the application. - // Enabling SD should increment the LFCLK request. - ASSERT(!nrf_sdh_is_enabled()); -#endif // SOFTDEVICE_PRESENT - - nrfx_clock_lfclk_stop(); - m_clock_cb.lfclk_on = false; -} - -static void hfclk_start(void) -{ -#ifdef SOFTDEVICE_PRESENT - if (nrf_sdh_is_enabled()) - { - (void)sd_clock_hfclk_request(); - return; - } -#endif // SOFTDEVICE_PRESENT - - nrfx_clock_hfclk_start(); -} - -static void hfclk_stop(void) -{ -#ifdef SOFTDEVICE_PRESENT - if (nrf_sdh_is_enabled()) - { - (void)sd_clock_hfclk_release(); - m_clock_cb.hfclk_on = false; - return; - } -#endif // SOFTDEVICE_PRESENT - - nrfx_clock_hfclk_stop(); - m_clock_cb.hfclk_on = false; -} - -bool nrf_drv_clock_init_check(void) -{ - return m_clock_cb.module_initialized; -} - -ret_code_t nrf_drv_clock_init(void) -{ - ret_code_t err_code = NRF_SUCCESS; - if (m_clock_cb.module_initialized) - { - err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED; - } - else - { - m_clock_cb.p_hf_head = NULL; - m_clock_cb.hfclk_requests = 0; - m_clock_cb.p_lf_head = NULL; - m_clock_cb.lfclk_requests = 0; - err_code = nrfx_clock_init(clock_irq_handler); -#ifdef SOFTDEVICE_PRESENT - if (!nrf_sdh_is_enabled()) -#endif - { - nrfx_clock_enable(); - } - -#if CALIBRATION_SUPPORT - m_clock_cb.cal_state = CAL_STATE_IDLE; -#endif - - m_clock_cb.module_initialized = true; - } - - NRF_LOG_INFO("Function: %s, error code: %s.", - (uint32_t)__func__, - (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); - return err_code; -} - -void nrf_drv_clock_uninit(void) -{ - ASSERT(m_clock_cb.module_initialized); - nrfx_clock_disable(); - nrfx_clock_uninit(); - - m_clock_cb.module_initialized = false; -} - -static void item_enqueue(nrf_drv_clock_handler_item_t ** p_head, - nrf_drv_clock_handler_item_t * p_item) -{ - nrf_drv_clock_handler_item_t * p_next = *p_head; - while (p_next) - { - if (p_next == p_item) - { - return; - } - p_next = p_next->p_next; - } - - p_item->p_next = (*p_head ? *p_head : NULL); - *p_head = p_item; -} - -static nrf_drv_clock_handler_item_t * item_dequeue(nrf_drv_clock_handler_item_t ** p_head) -{ - nrf_drv_clock_handler_item_t * p_item = *p_head; - if (p_item) - { - *p_head = p_item->p_next; - } - return p_item; -} - -void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) -{ - ASSERT(m_clock_cb.module_initialized); - - if (m_clock_cb.lfclk_on) - { - if (p_handler_item) - { - p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); - } - CRITICAL_REGION_ENTER(); - ++(m_clock_cb.lfclk_requests); - CRITICAL_REGION_EXIT(); - } - else - { - CRITICAL_REGION_ENTER(); - if (p_handler_item) - { - item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, - p_handler_item); - } - if (m_clock_cb.lfclk_requests == 0) - { - nrfx_clock_lfclk_start(); - } - ++(m_clock_cb.lfclk_requests); - CRITICAL_REGION_EXIT(); - } - - ASSERT(m_clock_cb.lfclk_requests > 0); -} - -void nrf_drv_clock_lfclk_release(void) -{ - ASSERT(m_clock_cb.module_initialized); - ASSERT(m_clock_cb.lfclk_requests > 0); - - CRITICAL_REGION_ENTER(); - --(m_clock_cb.lfclk_requests); - if (m_clock_cb.lfclk_requests == 0) - { - lfclk_stop(); - } - CRITICAL_REGION_EXIT(); -} - -bool nrf_drv_clock_lfclk_is_running(void) -{ - ASSERT(m_clock_cb.module_initialized); - -#ifdef SOFTDEVICE_PRESENT - if (nrf_sdh_is_enabled()) - { - return true; - } -#endif // SOFTDEVICE_PRESENT - - return nrfx_clock_lfclk_is_running(); -} - -void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) -{ - ASSERT(m_clock_cb.module_initialized); - - if (m_clock_cb.hfclk_on) - { - if (p_handler_item) - { - p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); - } - CRITICAL_REGION_ENTER(); - ++(m_clock_cb.hfclk_requests); - CRITICAL_REGION_EXIT(); - } - else - { - CRITICAL_REGION_ENTER(); - if (p_handler_item) - { - item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, - p_handler_item); - } - if (m_clock_cb.hfclk_requests == 0) - { - hfclk_start(); - } - ++(m_clock_cb.hfclk_requests); - CRITICAL_REGION_EXIT(); - } - - ASSERT(m_clock_cb.hfclk_requests > 0); -} - -void nrf_drv_clock_hfclk_release(void) -{ - ASSERT(m_clock_cb.module_initialized); - ASSERT(m_clock_cb.hfclk_requests > 0); - - CRITICAL_REGION_ENTER(); - --(m_clock_cb.hfclk_requests); - if (m_clock_cb.hfclk_requests == 0) - { - hfclk_stop(); - } - CRITICAL_REGION_EXIT(); -} - -bool nrf_drv_clock_hfclk_is_running(void) -{ - ASSERT(m_clock_cb.module_initialized); - -#ifdef SOFTDEVICE_PRESENT - if (nrf_sdh_is_enabled()) - { - uint32_t is_running; - UNUSED_VARIABLE(sd_clock_hfclk_is_running(&is_running)); - return (is_running ? true : false); - } -#endif // SOFTDEVICE_PRESENT - - return nrfx_clock_hfclk_is_running(); -} - -#if CALIBRATION_SUPPORT -static void clock_calibration_hf_started(nrf_drv_clock_evt_type_t event) -{ - if (m_clock_cb.cal_state == CAL_STATE_ABORT) - { - nrf_drv_clock_hfclk_release(); - m_clock_cb.cal_state = CAL_STATE_IDLE; - if (m_clock_cb.cal_done_handler) - { - m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); - } - } - else - { - ASSERT(event == NRF_DRV_CLOCK_EVT_HFCLK_STARTED); - if (nrfx_clock_calibration_start() != NRFX_SUCCESS) - { - ASSERT(false); - } - } -} -#endif // CALIBRATION_SUPPORT - -ret_code_t nrf_drv_clock_calibration_start(uint8_t interval, nrf_drv_clock_event_handler_t handler) -{ - ret_code_t err_code = NRF_SUCCESS; -#if CALIBRATION_SUPPORT - ASSERT(m_clock_cb.cal_state == CAL_STATE_IDLE); - if (m_clock_cb.lfclk_on == false) - { - err_code = NRF_ERROR_INVALID_STATE; - } - else if (m_clock_cb.cal_state == CAL_STATE_IDLE) - { - m_clock_cb.cal_done_handler = handler; - m_clock_cb.cal_hfclk_started_handler_item.event_handler = clock_calibration_hf_started; - if (interval == 0) - { - m_clock_cb.cal_state = CAL_STATE_HFCLK_REQ; - nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); - } - else - { - m_clock_cb.cal_state = CAL_STATE_CT; - nrfx_clock_calibration_timer_start(interval); - } - } - else - { - err_code = NRF_ERROR_BUSY; - } - NRF_LOG_WARNING("Function: %s, error code: %s.", - (uint32_t)__func__, - (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); - return err_code; -#else - UNUSED_PARAMETER(interval); - UNUSED_PARAMETER(handler); - err_code = NRF_ERROR_FORBIDDEN; - NRF_LOG_WARNING("Function: %s, error code: %s.", - (uint32_t)__func__, - (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); - return err_code; -#endif // CALIBRATION_SUPPORT -} - -ret_code_t nrf_drv_clock_calibration_abort(void) -{ - ret_code_t err_code = NRF_SUCCESS; -#if CALIBRATION_SUPPORT - CRITICAL_REGION_ENTER(); - switch (m_clock_cb.cal_state) - { - case CAL_STATE_CT: - nrfx_clock_calibration_timer_stop(); - m_clock_cb.cal_state = CAL_STATE_IDLE; - if (m_clock_cb.cal_done_handler) - { - m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); - } - break; - case CAL_STATE_HFCLK_REQ: - /* fall through. */ - case CAL_STATE_CAL: - m_clock_cb.cal_state = CAL_STATE_ABORT; - break; - default: - break; - } - CRITICAL_REGION_EXIT(); - - NRF_LOG_INFO("Function: %s, error code: %s.", - (uint32_t)__func__, - (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); - return err_code; -#else - err_code = NRF_ERROR_FORBIDDEN; - NRF_LOG_WARNING("Function: %s, error code: %s.", - (uint32_t)__func__, - (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); - return err_code; -#endif // CALIBRATION_SUPPORT -} - -ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating) -{ - ret_code_t err_code = NRF_SUCCESS; -#if CALIBRATION_SUPPORT - ASSERT(m_clock_cb.module_initialized); - *p_is_calibrating = (m_clock_cb.cal_state != CAL_STATE_IDLE); - NRF_LOG_INFO("Function: %s, error code: %s.", - (uint32_t)__func__, - (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); - return err_code; -#else - UNUSED_PARAMETER(p_is_calibrating); - err_code = NRF_ERROR_FORBIDDEN; - NRF_LOG_WARNING("Function: %s, error code: %s.", - (uint32_t)__func__, - (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); - return err_code; -#endif // CALIBRATION_SUPPORT -} - -__STATIC_INLINE void clock_clk_started_notify(nrf_drv_clock_evt_type_t evt_type) -{ - nrf_drv_clock_handler_item_t **p_head; - if (evt_type == NRF_DRV_CLOCK_EVT_HFCLK_STARTED) - { - p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head; - } - else - { - p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head; - } - - while (1) - { - nrf_drv_clock_handler_item_t * p_item = item_dequeue(p_head); - if (!p_item) - { - break; - } - - p_item->event_handler(evt_type); - } -} - -static void clock_irq_handler(nrfx_clock_evt_type_t evt) -{ - if (evt == NRFX_CLOCK_EVT_HFCLK_STARTED) - { - m_clock_cb.hfclk_on = true; - clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); - } - if (evt == NRFX_CLOCK_EVT_LFCLK_STARTED) - { - m_clock_cb.lfclk_on = true; - clock_clk_started_notify(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); - } -#if CALIBRATION_SUPPORT - if (evt == NRFX_CLOCK_EVT_CTTO) - { - nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); - } - - if (evt == NRFX_CLOCK_EVT_CAL_DONE) - { - nrf_drv_clock_hfclk_release(); - bool aborted = (m_clock_cb.cal_state == CAL_STATE_ABORT); - m_clock_cb.cal_state = CAL_STATE_IDLE; - if (m_clock_cb.cal_done_handler) - { - m_clock_cb.cal_done_handler(aborted ? - NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE); - } - } -#endif // CALIBRATION_SUPPORT -} - -#ifdef SOFTDEVICE_PRESENT -/** - * @brief SoftDevice SoC event handler. - * - * @param[in] evt_id SoC event. - * @param[in] p_context Context. - */ -static void soc_evt_handler(uint32_t evt_id, void * p_context) -{ - if (evt_id == NRF_EVT_HFCLKSTARTED) - { - m_clock_cb.hfclk_on = true; - clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); - } -} -NRF_SDH_SOC_OBSERVER(m_soc_evt_observer, CLOCK_CONFIG_SOC_OBSERVER_PRIO, soc_evt_handler, NULL); - -/** - * @brief SoftDevice enable/disable state handler. - * - * @param[in] state State. - * @param[in] p_context Context. - */ -static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) -{ - switch (state) - { - case NRF_SDH_EVT_STATE_ENABLE_PREPARE: - NVIC_DisableIRQ(POWER_CLOCK_IRQn); - break; - - case NRF_SDH_EVT_STATE_ENABLED: - CRITICAL_REGION_ENTER(); - /* Make sure that nrf_drv_clock module is initialized */ - if (!m_clock_cb.module_initialized) - { - (void)nrf_drv_clock_init(); - } - /* SD is one of the LFCLK requesters, but it will enable it by itself. */ - ++(m_clock_cb.lfclk_requests); - m_clock_cb.lfclk_on = true; - CRITICAL_REGION_EXIT(); - break; - - case NRF_SDH_EVT_STATE_DISABLED: - /* Reinit interrupts */ - ASSERT(m_clock_cb.module_initialized); - nrfx_clock_enable(); - - /* SD leaves LFCLK enabled - disable it if it is no longer required. */ - nrf_drv_clock_lfclk_release(); - break; - - default: - break; - } -} - -NRF_SDH_STATE_OBSERVER(m_sd_state_observer, CLOCK_CONFIG_STATE_OBSERVER_PRIO) = -{ - .handler = sd_state_evt_handler, - .p_context = NULL, -}; - -#endif // SOFTDEVICE_PRESENT - -#undef NRF_CLOCK_LFCLK_RC -#undef NRF_CLOCK_LFCLK_Xtal -#undef NRF_CLOCK_LFCLK_Synth +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "nrf_drv_clock.h" + +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#endif + +#define NRF_LOG_MODULE_NAME clock +#if CLOCK_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL CLOCK_CONFIG_LOG_LEVEL + #define NRF_LOG_INFO_COLOR CLOCK_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR CLOCK_CONFIG_DEBUG_COLOR +#else //CLOCK_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL 0 +#endif //CLOCK_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define EVT_TO_STR(event) \ + (event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \ + (event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : \ + "UNKNOWN EVENT")))) + + +/*lint -save -e652 */ +#define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC +#define NRF_CLOCK_LFCLK_Xtal CLOCK_LFCLKSRC_SRC_Xtal +#define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth +/*lint -restore */ + +#if (CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC) && !defined(SOFTDEVICE_PRESENT) +#define CALIBRATION_SUPPORT 1 +#else +#define CALIBRATION_SUPPORT 0 +#endif +typedef enum +{ + CAL_STATE_IDLE, + CAL_STATE_CT, + CAL_STATE_HFCLK_REQ, + CAL_STATE_CAL, + CAL_STATE_ABORT, +} nrf_drv_clock_cal_state_t; + +/**@brief CLOCK control block. */ +typedef struct +{ + bool module_initialized; /*< Indicate the state of module */ + volatile bool hfclk_on; /*< High-frequency clock state. */ + volatile bool lfclk_on; /*< Low-frequency clock state. */ + volatile uint32_t hfclk_requests; /*< High-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_hf_head; + volatile uint32_t lfclk_requests; /*< Low-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_lf_head; +#if CALIBRATION_SUPPORT + nrf_drv_clock_handler_item_t cal_hfclk_started_handler_item; + nrf_drv_clock_event_handler_t cal_done_handler; + volatile nrf_drv_clock_cal_state_t cal_state; +#endif // CALIBRATION_SUPPORT +} nrf_drv_clock_cb_t; + +static nrf_drv_clock_cb_t m_clock_cb; + +static void clock_irq_handler(nrfx_clock_evt_type_t evt); + +static void lfclk_stop(void) +{ +#if CALIBRATION_SUPPORT + nrfx_clock_calibration_timer_stop(); +#endif + +#ifdef SOFTDEVICE_PRESENT + // If LFCLK is requested to stop while SD is still enabled, + // it indicates an error in the application. + // Enabling SD should increment the LFCLK request. + ASSERT(!nrf_sdh_is_enabled()); +#endif // SOFTDEVICE_PRESENT + + nrfx_clock_lfclk_stop(); + m_clock_cb.lfclk_on = false; +} + +static void hfclk_start(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void)sd_clock_hfclk_request(); + return; + } +#endif // SOFTDEVICE_PRESENT + + nrfx_clock_hfclk_start(); +} + +static void hfclk_stop(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void)sd_clock_hfclk_release(); + m_clock_cb.hfclk_on = false; + return; + } +#endif // SOFTDEVICE_PRESENT + + nrfx_clock_hfclk_stop(); + m_clock_cb.hfclk_on = false; +} + +bool nrf_drv_clock_init_check(void) +{ + return m_clock_cb.module_initialized; +} + +ret_code_t nrf_drv_clock_init(void) +{ + ret_code_t err_code = NRF_SUCCESS; + if (m_clock_cb.module_initialized) + { + err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + else + { + m_clock_cb.p_hf_head = NULL; + m_clock_cb.hfclk_requests = 0; + m_clock_cb.p_lf_head = NULL; + m_clock_cb.lfclk_requests = 0; + err_code = nrfx_clock_init(clock_irq_handler); +#ifdef SOFTDEVICE_PRESENT + if (!nrf_sdh_is_enabled()) +#endif + { + nrfx_clock_enable(); + } + +#if CALIBRATION_SUPPORT + m_clock_cb.cal_state = CAL_STATE_IDLE; +#endif + + m_clock_cb.module_initialized = true; + } + + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_clock_uninit(void) +{ + ASSERT(m_clock_cb.module_initialized); + nrfx_clock_disable(); + nrfx_clock_uninit(); + + m_clock_cb.module_initialized = false; +} + +static void item_enqueue(nrf_drv_clock_handler_item_t ** p_head, + nrf_drv_clock_handler_item_t * p_item) +{ + nrf_drv_clock_handler_item_t * p_next = *p_head; + while (p_next) + { + if (p_next == p_item) + { + return; + } + p_next = p_next->p_next; + } + + p_item->p_next = (*p_head ? *p_head : NULL); + *p_head = p_item; +} + +static nrf_drv_clock_handler_item_t * item_dequeue(nrf_drv_clock_handler_item_t ** p_head) +{ + nrf_drv_clock_handler_item_t * p_item = *p_head; + if (p_item) + { + *p_head = p_item->p_next; + } + return p_item; +} + +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) +{ + ASSERT(m_clock_cb.module_initialized); + + if (m_clock_cb.lfclk_on) + { + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, + p_handler_item); + } + if (m_clock_cb.lfclk_requests == 0) + { + nrfx_clock_lfclk_start(); + } + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + + ASSERT(m_clock_cb.lfclk_requests > 0); +} + +void nrf_drv_clock_lfclk_release(void) +{ + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.lfclk_requests > 0); + + CRITICAL_REGION_ENTER(); + --(m_clock_cb.lfclk_requests); + if (m_clock_cb.lfclk_requests == 0) + { + lfclk_stop(); + } + CRITICAL_REGION_EXIT(); +} + +bool nrf_drv_clock_lfclk_is_running(void) +{ + ASSERT(m_clock_cb.module_initialized); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + return true; + } +#endif // SOFTDEVICE_PRESENT + + return nrfx_clock_lfclk_is_running(); +} + +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) +{ + ASSERT(m_clock_cb.module_initialized); + + if (m_clock_cb.hfclk_on) + { + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, + p_handler_item); + } + if (m_clock_cb.hfclk_requests == 0) + { + hfclk_start(); + } + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); + } + + ASSERT(m_clock_cb.hfclk_requests > 0); +} + +void nrf_drv_clock_hfclk_release(void) +{ + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.hfclk_requests > 0); + + CRITICAL_REGION_ENTER(); + --(m_clock_cb.hfclk_requests); + if (m_clock_cb.hfclk_requests == 0) + { + hfclk_stop(); + } + CRITICAL_REGION_EXIT(); +} + +bool nrf_drv_clock_hfclk_is_running(void) +{ + ASSERT(m_clock_cb.module_initialized); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + uint32_t is_running; + UNUSED_VARIABLE(sd_clock_hfclk_is_running(&is_running)); + return (is_running ? true : false); + } +#endif // SOFTDEVICE_PRESENT + + return nrfx_clock_hfclk_is_running(); +} + +#if CALIBRATION_SUPPORT +static void clock_calibration_hf_started(nrf_drv_clock_evt_type_t event) +{ + if (m_clock_cb.cal_state == CAL_STATE_ABORT) + { + nrf_drv_clock_hfclk_release(); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + } + else + { + ASSERT(event == NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + if (nrfx_clock_calibration_start() != NRFX_SUCCESS) + { + ASSERT(false); + } + } +} +#endif // CALIBRATION_SUPPORT + +ret_code_t nrf_drv_clock_calibration_start(uint8_t interval, nrf_drv_clock_event_handler_t handler) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.cal_state == CAL_STATE_IDLE); + if (m_clock_cb.lfclk_on == false) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (m_clock_cb.cal_state == CAL_STATE_IDLE) + { + m_clock_cb.cal_done_handler = handler; + m_clock_cb.cal_hfclk_started_handler_item.event_handler = clock_calibration_hf_started; + if (interval == 0) + { + m_clock_cb.cal_state = CAL_STATE_HFCLK_REQ; + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + else + { + m_clock_cb.cal_state = CAL_STATE_CT; + nrfx_clock_calibration_timer_start(interval); + } + } + else + { + err_code = NRF_ERROR_BUSY; + } + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + UNUSED_PARAMETER(interval); + UNUSED_PARAMETER(handler); + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_calibration_abort(void) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + CRITICAL_REGION_ENTER(); + switch (m_clock_cb.cal_state) + { + case CAL_STATE_CT: + nrfx_clock_calibration_timer_stop(); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + break; + case CAL_STATE_HFCLK_REQ: + /* fall through. */ + case CAL_STATE_CAL: + m_clock_cb.cal_state = CAL_STATE_ABORT; + break; + default: + break; + } + CRITICAL_REGION_EXIT(); + + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.module_initialized); + *p_is_calibrating = (m_clock_cb.cal_state != CAL_STATE_IDLE); + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + UNUSED_PARAMETER(p_is_calibrating); + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +__STATIC_INLINE void clock_clk_started_notify(nrf_drv_clock_evt_type_t evt_type) +{ + nrf_drv_clock_handler_item_t **p_head; + if (evt_type == NRF_DRV_CLOCK_EVT_HFCLK_STARTED) + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head; + } + else + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head; + } + + while (1) + { + nrf_drv_clock_handler_item_t * p_item = item_dequeue(p_head); + if (!p_item) + { + break; + } + + p_item->event_handler(evt_type); + } +} + +static void clock_irq_handler(nrfx_clock_evt_type_t evt) +{ + if (evt == NRFX_CLOCK_EVT_HFCLK_STARTED) + { + m_clock_cb.hfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + if (evt == NRFX_CLOCK_EVT_LFCLK_STARTED) + { + m_clock_cb.lfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } +#if CALIBRATION_SUPPORT + if (evt == NRFX_CLOCK_EVT_CTTO) + { + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + + if (evt == NRFX_CLOCK_EVT_CAL_DONE) + { + nrf_drv_clock_hfclk_release(); + bool aborted = (m_clock_cb.cal_state == CAL_STATE_ABORT); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(aborted ? + NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE); + } + } +#endif // CALIBRATION_SUPPORT +} + +#ifdef SOFTDEVICE_PRESENT +/** + * @brief SoftDevice SoC event handler. + * + * @param[in] evt_id SoC event. + * @param[in] p_context Context. + */ +static void soc_evt_handler(uint32_t evt_id, void * p_context) +{ + if (evt_id == NRF_EVT_HFCLKSTARTED) + { + m_clock_cb.hfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } +} +NRF_SDH_SOC_OBSERVER(m_soc_evt_observer, CLOCK_CONFIG_SOC_OBSERVER_PRIO, soc_evt_handler, NULL); + +/** + * @brief SoftDevice enable/disable state handler. + * + * @param[in] state State. + * @param[in] p_context Context. + */ +static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLE_PREPARE: + NVIC_DisableIRQ(POWER_CLOCK_IRQn); + break; + + case NRF_SDH_EVT_STATE_ENABLED: + CRITICAL_REGION_ENTER(); + /* Make sure that nrf_drv_clock module is initialized */ + if (!m_clock_cb.module_initialized) + { + (void)nrf_drv_clock_init(); + } + /* SD is one of the LFCLK requesters, but it will enable it by itself. */ + ++(m_clock_cb.lfclk_requests); + m_clock_cb.lfclk_on = true; + CRITICAL_REGION_EXIT(); + break; + + case NRF_SDH_EVT_STATE_DISABLED: + /* Reinit interrupts */ + ASSERT(m_clock_cb.module_initialized); + nrfx_clock_enable(); + + /* SD leaves LFCLK enabled - disable it if it is no longer required. */ + nrf_drv_clock_lfclk_release(); + break; + + default: + break; + } +} + +NRF_SDH_STATE_OBSERVER(m_sd_state_observer, CLOCK_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = sd_state_evt_handler, + .p_context = NULL, +}; + +#endif // SOFTDEVICE_PRESENT + +#undef NRF_CLOCK_LFCLK_RC +#undef NRF_CLOCK_LFCLK_Xtal +#undef NRF_CLOCK_LFCLK_Synth diff --git a/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.h b/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.h index e0ead2b0c..8b9867cbe 100644 --- a/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.h +++ b/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.h @@ -1,297 +1,297 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef NRF_DRV_CLOCK_H__ -#define NRF_DRV_CLOCK_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup nrf_drv_clock Clock driver - legacy layer - * @{ - * @ingroup nrf_clock - * - * @brief Layer providing compatibility with the former API. - */ - -/** - * @brief Clock events. - */ -typedef enum -{ - NRF_DRV_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started. - NRF_DRV_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started. - NRF_DRV_CLOCK_EVT_CAL_DONE, ///< Calibration is done. - NRF_DRV_CLOCK_EVT_CAL_ABORTED, ///< Calibration has been aborted. -} nrf_drv_clock_evt_type_t; - -/** - * @brief Clock event handler. - * - * @param[in] event Event. - */ -typedef void (*nrf_drv_clock_event_handler_t)(nrf_drv_clock_evt_type_t event); - -// Forward declaration of the nrf_drv_clock_handler_item_t type. -typedef struct nrf_drv_clock_handler_item_s nrf_drv_clock_handler_item_t; - -struct nrf_drv_clock_handler_item_s -{ - nrf_drv_clock_handler_item_t * p_next; ///< A pointer to the next handler that should be called when the clock is started. - nrf_drv_clock_event_handler_t event_handler; ///< Function to be called when the clock is started. -}; - -/** - * @brief Function for checking if driver is already initialized - * - * @retval true Driver is initialized - * @retval false Driver is uninitialized - */ -bool nrf_drv_clock_init_check(void); - -/** - * @brief Function for initializing the nrf_drv_clock module. - * - * After initialization, the module is in power off state (clocks are not requested). - * - * @retval NRF_SUCCESS If the procedure was successful. - * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the driver was already initialized. - */ -ret_code_t nrf_drv_clock_init(void); - -/** - * @brief Function for uninitializing the clock module. - * - */ -void nrf_drv_clock_uninit(void); - -/** - * @brief Function for requesting the LFCLK. - * - * The low-frequency clock can be requested by different modules - * or contexts. The driver ensures that the clock will be started only when it is requested - * the first time. If the clock is not ready but it was already started, the handler item that is - * provided as an input parameter is added to the list of handlers that will be notified - * when the clock is started. If the clock is already enabled, user callback is called from the - * current context. - * - * The first request will start the selected LFCLK source. If an event handler is - * provided, it will be called once the LFCLK is started. If the LFCLK was already started at this - * time, the event handler will be called from the context of this function. Additionally, - * the @ref nrf_drv_clock_lfclk_is_running function can be polled to check if the clock has started. - * - * @note When a SoftDevice is enabled, the LFCLK is always running and the driver cannot control it. - * - * @note The handler item provided by the user cannot be an automatic variable. - * - * @param[in] p_handler_item A pointer to the event handler structure. - */ -void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); - -/** - * @brief Function for releasing the LFCLK. - * - * If there are no more requests, the LFCLK source will be stopped. - * - * @note When a SoftDevice is enabled, the LFCLK is always running. - */ -void nrf_drv_clock_lfclk_release(void); - -/** - * @brief Function for checking the LFCLK state. - * - * @retval true If the LFCLK is running. - * @retval false If the LFCLK is not running. - */ -bool nrf_drv_clock_lfclk_is_running(void); - -/** - * @brief Function for requesting the high-accuracy source HFCLK. - * - * The high-accuracy source - * can be requested by different modules or contexts. The driver ensures that the high-accuracy - * clock will be started only when it is requested the first time. If the clock is not ready - * but it was already started, the handler item that is provided as an input parameter is added - * to the list of handlers that will be notified when the clock is started. - * - * If an event handler is provided, it will be called once the clock is started. If the clock was already - * started at this time, the event handler will be called from the context of this function. Additionally, - * the @ref nrf_drv_clock_hfclk_is_running function can be polled to check if the clock has started. - * - * @note If a SoftDevice is running, the clock is managed by the SoftDevice and all requests are handled by - * the SoftDevice. This function cannot be called from all interrupt priority levels in that case. - * @note The handler item provided by the user cannot be an automatic variable. - * - * @param[in] p_handler_item A pointer to the event handler structure. - */ -void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); - -/** - * @brief Function for releasing the high-accuracy source HFCLK. - * - * If there are no more requests, the high-accuracy source will be released. - */ -void nrf_drv_clock_hfclk_release(void); - -/** - * @brief Function for checking the HFCLK state. - * - * @retval true If the HFCLK is running (for \nRFXX XTAL source). - * @retval false If the HFCLK is not running. - */ -bool nrf_drv_clock_hfclk_is_running(void); - -/** - * @brief Function for starting a single calibration process. - * - * This function can also delay the start of calibration by a user-specified value. The delay will use - * a low-power timer that is part of the CLOCK module. @ref nrf_drv_clock_is_calibrating can be called to - * check if calibration is still in progress. If a handler is provided, the user can be notified when - * calibration is completed. The ext calibration can be started from the handler context. - * - * The calibration process consists of three phases: - * - Delay (optional) - * - Requesting the high-accuracy HFCLK - * - Hardware-supported calibration - * - * @param[in] delay Time after which the calibration will be started (in 0.25 s units). - * @param[in] handler NULL or user function to be called when calibration is completed or aborted. - * - * @retval NRF_SUCCESS If the procedure was successful. - * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. - * @retval NRF_ERROR_INVALID_STATE If the low-frequency clock is off. - * @retval NRF_ERROR_BUSY If calibration is in progress. - */ -ret_code_t nrf_drv_clock_calibration_start(uint8_t delay, nrf_drv_clock_event_handler_t handler); - -/** - * @brief Function for aborting calibration. - * - * This function aborts on-going calibration. If calibration was started, it cannot be stopped. If a handler - * was provided by @ref nrf_drv_clock_calibration_start, this handler will be called once - * aborted calibration is completed. @ref nrf_drv_clock_is_calibrating can also be used to check - * if the system is calibrating. - * - * @retval NRF_SUCCESS If the procedure was successful. - * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. - */ -ret_code_t nrf_drv_clock_calibration_abort(void); - -/** - * @brief Function for checking if calibration is in progress. - * - * This function indicates that the system is - * in calibration if it is in any of the calibration process phases (see @ref nrf_drv_clock_calibration_start). - * - * @param[out] p_is_calibrating True if calibration is in progress, false if not. - * - * @retval NRF_SUCCESS If the procedure was successful. - * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. - */ -ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating); - -/**@brief Function for returning a requested task address for the clock driver module. - * - * @param[in] task One of the peripheral tasks. - * - * @return Task address. - */ -__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task); - -/**@brief Function for returning a requested event address for the clock driver module. - * - * @param[in] event One of the peripheral events. - * - * @return Event address. - */ -__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event); - - -#ifdef SOFTDEVICE_PRESENT -/** - * @brief Function called by the SoftDevice handler if an @ref NRF_SOC_EVTS event is received from the SoftDevice. - * - * @param[in] evt_id One of NRF_SOC_EVTS values. - */ -void nrf_drv_clock_on_soc_event(uint32_t evt_id); - -/** - * @brief Function called by the SoftDevice handler when the SoftDevice has been enabled. - * - * This function is called just after the SoftDevice has been properly enabled. - * Its main purpose is to mark that LFCLK has been requested by SD. - */ -void nrf_drv_clock_on_sd_enable(void); - -/** - * @brief Function called by the SoftDevice handler when the SoftDevice has been disabled. - * - * This function is called just after the SoftDevice has been properly disabled. - * It has two purposes: - * 1. Releases the LFCLK from the SD. - * 2. Reinitializes an interrupt after the SD releases POWER_CLOCK_IRQ. - */ -void nrf_drv_clock_on_sd_disable(void); - -#endif -/** - *@} - **/ - -#ifndef SUPPRESS_INLINE_IMPLEMENTATION -__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task) -{ - return nrf_clock_task_address_get(task); -} - -__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event) -{ - return nrf_clock_event_address_get(event); -} -#endif //SUPPRESS_INLINE_IMPLEMENTATION - -#ifdef __cplusplus -} -#endif - -#endif // NRF_DRV_CLOCK_H__ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_DRV_CLOCK_H__ +#define NRF_DRV_CLOCK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_clock Clock driver - legacy layer + * @{ + * @ingroup nrf_clock + * + * @brief Layer providing compatibility with the former API. + */ + +/** + * @brief Clock events. + */ +typedef enum +{ + NRF_DRV_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started. + NRF_DRV_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started. + NRF_DRV_CLOCK_EVT_CAL_DONE, ///< Calibration is done. + NRF_DRV_CLOCK_EVT_CAL_ABORTED, ///< Calibration has been aborted. +} nrf_drv_clock_evt_type_t; + +/** + * @brief Clock event handler. + * + * @param[in] event Event. + */ +typedef void (*nrf_drv_clock_event_handler_t)(nrf_drv_clock_evt_type_t event); + +// Forward declaration of the nrf_drv_clock_handler_item_t type. +typedef struct nrf_drv_clock_handler_item_s nrf_drv_clock_handler_item_t; + +struct nrf_drv_clock_handler_item_s +{ + nrf_drv_clock_handler_item_t * p_next; ///< A pointer to the next handler that should be called when the clock is started. + nrf_drv_clock_event_handler_t event_handler; ///< Function to be called when the clock is started. +}; + +/** + * @brief Function for checking if driver is already initialized + * + * @retval true Driver is initialized + * @retval false Driver is uninitialized + */ +bool nrf_drv_clock_init_check(void); + +/** + * @brief Function for initializing the nrf_drv_clock module. + * + * After initialization, the module is in power off state (clocks are not requested). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the driver was already initialized. + */ +ret_code_t nrf_drv_clock_init(void); + +/** + * @brief Function for uninitializing the clock module. + * + */ +void nrf_drv_clock_uninit(void); + +/** + * @brief Function for requesting the LFCLK. + * + * The low-frequency clock can be requested by different modules + * or contexts. The driver ensures that the clock will be started only when it is requested + * the first time. If the clock is not ready but it was already started, the handler item that is + * provided as an input parameter is added to the list of handlers that will be notified + * when the clock is started. If the clock is already enabled, user callback is called from the + * current context. + * + * The first request will start the selected LFCLK source. If an event handler is + * provided, it will be called once the LFCLK is started. If the LFCLK was already started at this + * time, the event handler will be called from the context of this function. Additionally, + * the @ref nrf_drv_clock_lfclk_is_running function can be polled to check if the clock has started. + * + * @note When a SoftDevice is enabled, the LFCLK is always running and the driver cannot control it. + * + * @note The handler item provided by the user cannot be an automatic variable. + * + * @param[in] p_handler_item A pointer to the event handler structure. + */ +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); + +/** + * @brief Function for releasing the LFCLK. + * + * If there are no more requests, the LFCLK source will be stopped. + * + * @note When a SoftDevice is enabled, the LFCLK is always running. + */ +void nrf_drv_clock_lfclk_release(void); + +/** + * @brief Function for checking the LFCLK state. + * + * @retval true If the LFCLK is running. + * @retval false If the LFCLK is not running. + */ +bool nrf_drv_clock_lfclk_is_running(void); + +/** + * @brief Function for requesting the high-accuracy source HFCLK. + * + * The high-accuracy source + * can be requested by different modules or contexts. The driver ensures that the high-accuracy + * clock will be started only when it is requested the first time. If the clock is not ready + * but it was already started, the handler item that is provided as an input parameter is added + * to the list of handlers that will be notified when the clock is started. + * + * If an event handler is provided, it will be called once the clock is started. If the clock was already + * started at this time, the event handler will be called from the context of this function. Additionally, + * the @ref nrf_drv_clock_hfclk_is_running function can be polled to check if the clock has started. + * + * @note If a SoftDevice is running, the clock is managed by the SoftDevice and all requests are handled by + * the SoftDevice. This function cannot be called from all interrupt priority levels in that case. + * @note The handler item provided by the user cannot be an automatic variable. + * + * @param[in] p_handler_item A pointer to the event handler structure. + */ +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); + +/** + * @brief Function for releasing the high-accuracy source HFCLK. + * + * If there are no more requests, the high-accuracy source will be released. + */ +void nrf_drv_clock_hfclk_release(void); + +/** + * @brief Function for checking the HFCLK state. + * + * @retval true If the HFCLK is running (for \nRFXX XTAL source). + * @retval false If the HFCLK is not running. + */ +bool nrf_drv_clock_hfclk_is_running(void); + +/** + * @brief Function for starting a single calibration process. + * + * This function can also delay the start of calibration by a user-specified value. The delay will use + * a low-power timer that is part of the CLOCK module. @ref nrf_drv_clock_is_calibrating can be called to + * check if calibration is still in progress. If a handler is provided, the user can be notified when + * calibration is completed. The ext calibration can be started from the handler context. + * + * The calibration process consists of three phases: + * - Delay (optional) + * - Requesting the high-accuracy HFCLK + * - Hardware-supported calibration + * + * @param[in] delay Time after which the calibration will be started (in 0.25 s units). + * @param[in] handler NULL or user function to be called when calibration is completed or aborted. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + * @retval NRF_ERROR_INVALID_STATE If the low-frequency clock is off. + * @retval NRF_ERROR_BUSY If calibration is in progress. + */ +ret_code_t nrf_drv_clock_calibration_start(uint8_t delay, nrf_drv_clock_event_handler_t handler); + +/** + * @brief Function for aborting calibration. + * + * This function aborts on-going calibration. If calibration was started, it cannot be stopped. If a handler + * was provided by @ref nrf_drv_clock_calibration_start, this handler will be called once + * aborted calibration is completed. @ref nrf_drv_clock_is_calibrating can also be used to check + * if the system is calibrating. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_calibration_abort(void); + +/** + * @brief Function for checking if calibration is in progress. + * + * This function indicates that the system is + * in calibration if it is in any of the calibration process phases (see @ref nrf_drv_clock_calibration_start). + * + * @param[out] p_is_calibrating True if calibration is in progress, false if not. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating); + +/**@brief Function for returning a requested task address for the clock driver module. + * + * @param[in] task One of the peripheral tasks. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task); + +/**@brief Function for returning a requested event address for the clock driver module. + * + * @param[in] event One of the peripheral events. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event); + + +#ifdef SOFTDEVICE_PRESENT +/** + * @brief Function called by the SoftDevice handler if an @ref NRF_SOC_EVTS event is received from the SoftDevice. + * + * @param[in] evt_id One of NRF_SOC_EVTS values. + */ +void nrf_drv_clock_on_soc_event(uint32_t evt_id); + +/** + * @brief Function called by the SoftDevice handler when the SoftDevice has been enabled. + * + * This function is called just after the SoftDevice has been properly enabled. + * Its main purpose is to mark that LFCLK has been requested by SD. + */ +void nrf_drv_clock_on_sd_enable(void); + +/** + * @brief Function called by the SoftDevice handler when the SoftDevice has been disabled. + * + * This function is called just after the SoftDevice has been properly disabled. + * It has two purposes: + * 1. Releases the LFCLK from the SD. + * 2. Reinitializes an interrupt after the SD releases POWER_CLOCK_IRQ. + */ +void nrf_drv_clock_on_sd_disable(void); + +#endif +/** + *@} + **/ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task) +{ + return nrf_clock_task_address_get(task); +} + +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event) +{ + return nrf_clock_event_address_get(event); +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_CLOCK_H__ diff --git a/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.h b/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.h index 163c987e1..5eccd8b81 100644 --- a/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.h +++ b/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.h @@ -1,63 +1,63 @@ -/** - * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef NRF_DRV_COMMON_H__ -#define NRF_DRV_COMMON_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define INTERRUPT_PRIORITY_VALIDATION(pri) STATIC_ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) -#define INTERRUPT_PRIORITY_ASSERT(pri) ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) - -#define nrf_drv_irq_handler_t nrfx_irq_handler_t -#define nrf_drv_bitpos_to_event nrfx_bitpos_to_event -#define nrf_drv_event_to_bitpos nrfx_event_to_bitpos -#define nrf_drv_get_IRQn nrfx_get_irq_number -#define nrf_drv_is_in_RAM nrfx_is_in_ram - -#ifdef __cplusplus -} -#endif - -#endif // NRF_DRV_COMMON_H__ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_COMMON_H__ +#define NRF_DRV_COMMON_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define INTERRUPT_PRIORITY_VALIDATION(pri) STATIC_ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) +#define INTERRUPT_PRIORITY_ASSERT(pri) ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) + +#define nrf_drv_irq_handler_t nrfx_irq_handler_t +#define nrf_drv_bitpos_to_event nrfx_bitpos_to_event +#define nrf_drv_event_to_bitpos nrfx_event_to_bitpos +#define nrf_drv_get_IRQn nrfx_get_irq_number +#define nrf_drv_is_in_RAM nrfx_is_in_ram + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_COMMON_H__ diff --git a/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.c b/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.c index bba3d135e..44f7c2d1d 100644 --- a/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.c +++ b/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.c @@ -1,416 +1,416 @@ -/** - * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(POWER) -#include "nrf_drv_power.h" -#include -#ifdef SOFTDEVICE_PRESENT -#include "nrf_sdh.h" -#include "nrf_sdh_soc.h" -#endif - -#include - -// The structure with default configuration data. -static const nrfx_power_config_t m_drv_power_config_default = -{ - .dcdcen = NRFX_POWER_CONFIG_DEFAULT_DCDCEN, -#if NRF_POWER_HAS_VDDH - .dcdcenhv = NRFX_POWER_CONFIG_DEFAULT_DCDCENHV, -#endif -}; - -static bool m_initialized; - -bool nrf_drv_power_init_check(void) -{ - return m_initialized; -} - -ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config) -{ -#ifdef SOFTDEVICE_PRESENT - if (m_initialized) - { - return NRF_ERROR_MODULE_ALREADY_INITIALIZED; - } - if (nrf_sdh_is_enabled()) - { - return NRF_ERROR_INVALID_STATE; - } -#endif - if (p_config == NULL) - { - p_config = &m_drv_power_config_default; - } - - ret_code_t err_code = nrfx_power_init(p_config); - if (err_code == NRFX_SUCCESS) - { - m_initialized = true; - } - return err_code; -} - -void nrf_drv_power_uninit() -{ - nrfx_power_uninit(); - nrf_drv_power_pof_uninit(); -#if NRF_POWER_HAS_SLEEPEVT - nrf_drv_power_sleepevt_uninit(); -#endif -#if NRF_POWER_HAS_USBREG - nrf_drv_power_usbevt_uninit(); -#endif - m_initialized = false; -} - -ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config) -{ - ret_code_t err_code = NRF_SUCCESS; - nrfx_power_pof_init(p_config); -#ifdef SOFTDEVICE_PRESENT - if (nrf_sdh_is_enabled()) - { - /* Currently when SD is enabled - the configuration can be changed - * in very limited range. - * It is the SoftDevice limitation. - */ -#if NRF_POWER_HAS_VDDH - if (p_config->thrvddh != nrf_power_pofcon_vddh_get()) - { - /* Cannot change THRVDDH with current SD API */ - return NRF_ERROR_INVALID_STATE; - } -#endif - if (p_config->thr != nrf_power_pofcon_get(NULL)) - { - /* Only limited number of THR values are supported and - * the values taken by SD is different than the one in hardware - */ - uint8_t thr; - switch(p_config->thr) - { - case NRF_POWER_POFTHR_V21: - thr = NRF_POWER_THRESHOLD_V21; - break; - case NRF_POWER_POFTHR_V23: - thr = NRF_POWER_THRESHOLD_V23; - break; - case NRF_POWER_POFTHR_V25: - thr = NRF_POWER_THRESHOLD_V25; - break; - case NRF_POWER_POFTHR_V27: - thr = NRF_POWER_THRESHOLD_V27; - break; - default: - /* Cannot configure */ - nrfx_power_pof_uninit(); - return NRF_ERROR_INVALID_STATE; - } - err_code = sd_power_pof_threshold_set(thr); - if (err_code != NRF_SUCCESS) - { - return err_code; - } - } - err_code = sd_power_pof_enable(true); - } - else -#endif /* SOFTDEVICE_PRESENT */ - { - nrfx_power_pof_enable(p_config); - } - return err_code; -} - -void nrf_drv_power_pof_uninit() -{ -#ifdef SOFTDEVICE_PRESENT - if (nrf_sdh_is_enabled()) - { - ret_code_t err_code = sd_power_pof_enable(false); - ASSERT(err_code == NRF_SUCCESS); - UNUSED_VARIABLE(err_code); //handle no-debug case - } - else -#endif - { - nrfx_power_pof_disable(); - } - nrfx_power_pof_uninit(); -} - -#if NRF_POWER_HAS_SLEEPEVT -ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config) -{ - if (p_config->handler != NULL) - { -#ifdef SOFTDEVICE_PRESENT - if (nrf_sdh_is_enabled()) - { - if ((p_config->en_enter) || (p_config->en_exit)) - { - return NRF_ERROR_INVALID_STATE; - } - } - else -#endif - { - nrfx_power_sleepevt_enable(p_config); - } - } - return NRF_SUCCESS; -} - -void nrf_drv_power_sleepevt_uninit(void) -{ -#ifdef SOFTDEVICE_PRESENT - if (nrf_sdh_is_enabled()) - { - /* Nothing to do */ - } - else -#endif - { - nrfx_power_sleepevt_disable(); - } - nrfx_power_sleepevt_uninit(); -} -#endif /* NRF_POWER_HAS_SLEEPEVT */ - -#if NRF_POWER_HAS_USBREG - -#ifdef SOFTDEVICE_PRESENT -static ret_code_t nrf_drv_power_sd_usbevt_enable(bool enable) -{ - ret_code_t err_code; - err_code = sd_power_usbdetected_enable(enable); - ASSERT(err_code == NRF_SUCCESS); - if (err_code != NRF_SUCCESS) - { - return err_code; - } - - err_code = sd_power_usbpwrrdy_enable(enable); - ASSERT(err_code == NRF_SUCCESS); - if (err_code != NRF_SUCCESS) - { - return err_code; - } - - err_code = sd_power_usbremoved_enable(enable); - ASSERT(err_code == NRF_SUCCESS); - return err_code; -} -#endif // SOFTDEVICE_PRESENT - -ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config) -{ - nrf_drv_power_usbevt_uninit(); - nrfx_power_usbevt_init(p_config); -#ifdef SOFTDEVICE_PRESENT - if (nrf_sdh_is_enabled()) - { - ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(true); - ASSERT(err_code == NRF_SUCCESS); - if (err_code != NRF_SUCCESS) - { - return err_code; - } - - uint32_t regstatus; - err_code = sd_power_usbregstatus_get(®status); - ASSERT(err_code == NRF_SUCCESS); - if (err_code != NRF_SUCCESS) - { - return err_code; - } - - if (regstatus & POWER_USBREGSTATUS_VBUSDETECT_Msk) - { - nrfx_power_usb_event_handler_t usbevt_handler = nrfx_power_usb_handler_get(); - ASSERT(usbevt_handler != NULL); - usbevt_handler(NRFX_POWER_USB_EVT_DETECTED); - } - } - else -#endif - { - nrfx_power_usbevt_enable(); - } - return NRF_SUCCESS; -} - -void nrf_drv_power_usbevt_uninit(void) -{ -#ifdef SOFTDEVICE_PRESENT - CRITICAL_REGION_ENTER(); - if (nrf_sdh_is_enabled()) - { - ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(false); - ASSERT(err_code == NRF_SUCCESS); - UNUSED_VARIABLE(err_code); - } - else -#endif - { - nrfx_power_usbevt_disable(); - } -#ifdef SOFTDEVICE_PRESENT - CRITICAL_REGION_EXIT(); -#endif - nrfx_power_usbevt_uninit(); -} -#endif /* NRF_POWER_HAS_USBREG */ - -#ifdef SOFTDEVICE_PRESENT -static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context); -static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context); - -NRF_SDH_SOC_OBSERVER(m_soc_observer, POWER_CONFIG_SOC_OBSERVER_PRIO, - nrf_drv_power_sdh_soc_evt_handler, NULL); - -NRF_SDH_STATE_OBSERVER(m_sd_observer, POWER_CONFIG_STATE_OBSERVER_PRIO) = -{ - .handler = nrf_drv_power_sdh_state_evt_handler, - .p_context = NULL -}; - -static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context) -{ - if (evt_id == NRF_EVT_POWER_FAILURE_WARNING) - { - nrfx_power_pofwarn_event_handler_t pofwarn_handler = nrfx_power_pof_handler_get(); - /* Cannot be null if event is enabled */ - ASSERT(pofwarn_handler != NULL); - pofwarn_handler(); - } - -#if NRF_POWER_HAS_USBREG - nrfx_power_usb_event_handler_t usbevt_handler = nrfx_power_usb_handler_get(); - if (usbevt_handler != NULL) - { - switch (evt_id) - { - case NRF_EVT_POWER_USB_POWER_READY: - usbevt_handler(NRFX_POWER_USB_EVT_READY); - break; - - case NRF_EVT_POWER_USB_DETECTED: - usbevt_handler(NRFX_POWER_USB_EVT_DETECTED); - break; - - case NRF_EVT_POWER_USB_REMOVED: - usbevt_handler(NRFX_POWER_USB_EVT_REMOVED); - break; - - default: - break; - - } - } -#endif -} - -static void nrf_drv_power_on_sd_enable(void) -{ - ASSERT(m_initialized); /* This module has to be enabled first */ - CRITICAL_REGION_ENTER(); - if (nrfx_power_pof_handler_get() != NULL) - { - ret_code_t err_code = sd_power_pof_enable(true); - ASSERT(err_code == NRF_SUCCESS); - UNUSED_VARIABLE(err_code); //handle no-debug case - } - CRITICAL_REGION_EXIT(); - -#if NRF_POWER_HAS_USBREG - if (nrfx_power_usb_handler_get() != NULL) - { - ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(true); - ASSERT(err_code == NRF_SUCCESS); - UNUSED_VARIABLE(err_code); //handle no-debug case - } -#endif -} - -static void nrf_drv_power_on_sd_disable(void) -{ - /* Reinit interrupts */ - ASSERT(m_initialized); - NRFX_IRQ_PRIORITY_SET(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY); - NRFX_IRQ_ENABLE(POWER_CLOCK_IRQn); - if (nrfx_power_pof_handler_get() != NULL) - { - nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK); - } - -#if NRF_POWER_HAS_USBREG - if (nrfx_power_usb_handler_get() != NULL) - { - nrf_power_int_enable( - NRF_POWER_INT_USBDETECTED_MASK | - NRF_POWER_INT_USBREMOVED_MASK | - NRF_POWER_INT_USBPWRRDY_MASK); - } -#endif -} - -static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) -{ - switch (state) - { - case NRF_SDH_EVT_STATE_ENABLED: - nrf_drv_power_on_sd_enable(); - break; - - case NRF_SDH_EVT_STATE_DISABLED: - nrf_drv_power_on_sd_disable(); - break; - - default: - break; - } -} - -#endif // SOFTDEVICE_PRESENT -#endif //POWER_ENABLED +/** + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(POWER) +#include "nrf_drv_power.h" +#include +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#endif + +#include + +// The structure with default configuration data. +static const nrfx_power_config_t m_drv_power_config_default = +{ + .dcdcen = NRFX_POWER_CONFIG_DEFAULT_DCDCEN, +#if NRF_POWER_HAS_VDDH + .dcdcenhv = NRFX_POWER_CONFIG_DEFAULT_DCDCENHV, +#endif +}; + +static bool m_initialized; + +bool nrf_drv_power_init_check(void) +{ + return m_initialized; +} + +ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config) +{ +#ifdef SOFTDEVICE_PRESENT + if (m_initialized) + { + return NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + if (nrf_sdh_is_enabled()) + { + return NRF_ERROR_INVALID_STATE; + } +#endif + if (p_config == NULL) + { + p_config = &m_drv_power_config_default; + } + + ret_code_t err_code = nrfx_power_init(p_config); + if (err_code == NRFX_SUCCESS) + { + m_initialized = true; + } + return err_code; +} + +void nrf_drv_power_uninit() +{ + nrfx_power_uninit(); + nrf_drv_power_pof_uninit(); +#if NRF_POWER_HAS_SLEEPEVT + nrf_drv_power_sleepevt_uninit(); +#endif +#if NRF_POWER_HAS_USBREG + nrf_drv_power_usbevt_uninit(); +#endif + m_initialized = false; +} + +ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config) +{ + ret_code_t err_code = NRF_SUCCESS; + nrfx_power_pof_init(p_config); +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /* Currently when SD is enabled - the configuration can be changed + * in very limited range. + * It is the SoftDevice limitation. + */ +#if NRF_POWER_HAS_VDDH + if (p_config->thrvddh != nrf_power_pofcon_vddh_get()) + { + /* Cannot change THRVDDH with current SD API */ + return NRF_ERROR_INVALID_STATE; + } +#endif + if (p_config->thr != nrf_power_pofcon_get(NULL)) + { + /* Only limited number of THR values are supported and + * the values taken by SD is different than the one in hardware + */ + uint8_t thr; + switch(p_config->thr) + { + case NRF_POWER_POFTHR_V21: + thr = NRF_POWER_THRESHOLD_V21; + break; + case NRF_POWER_POFTHR_V23: + thr = NRF_POWER_THRESHOLD_V23; + break; + case NRF_POWER_POFTHR_V25: + thr = NRF_POWER_THRESHOLD_V25; + break; + case NRF_POWER_POFTHR_V27: + thr = NRF_POWER_THRESHOLD_V27; + break; + default: + /* Cannot configure */ + nrfx_power_pof_uninit(); + return NRF_ERROR_INVALID_STATE; + } + err_code = sd_power_pof_threshold_set(thr); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + err_code = sd_power_pof_enable(true); + } + else +#endif /* SOFTDEVICE_PRESENT */ + { + nrfx_power_pof_enable(p_config); + } + return err_code; +} + +void nrf_drv_power_pof_uninit() +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + ret_code_t err_code = sd_power_pof_enable(false); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); //handle no-debug case + } + else +#endif + { + nrfx_power_pof_disable(); + } + nrfx_power_pof_uninit(); +} + +#if NRF_POWER_HAS_SLEEPEVT +ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config) +{ + if (p_config->handler != NULL) + { +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + if ((p_config->en_enter) || (p_config->en_exit)) + { + return NRF_ERROR_INVALID_STATE; + } + } + else +#endif + { + nrfx_power_sleepevt_enable(p_config); + } + } + return NRF_SUCCESS; +} + +void nrf_drv_power_sleepevt_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /* Nothing to do */ + } + else +#endif + { + nrfx_power_sleepevt_disable(); + } + nrfx_power_sleepevt_uninit(); +} +#endif /* NRF_POWER_HAS_SLEEPEVT */ + +#if NRF_POWER_HAS_USBREG + +#ifdef SOFTDEVICE_PRESENT +static ret_code_t nrf_drv_power_sd_usbevt_enable(bool enable) +{ + ret_code_t err_code; + err_code = sd_power_usbdetected_enable(enable); + ASSERT(err_code == NRF_SUCCESS); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = sd_power_usbpwrrdy_enable(enable); + ASSERT(err_code == NRF_SUCCESS); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = sd_power_usbremoved_enable(enable); + ASSERT(err_code == NRF_SUCCESS); + return err_code; +} +#endif // SOFTDEVICE_PRESENT + +ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config) +{ + nrf_drv_power_usbevt_uninit(); + nrfx_power_usbevt_init(p_config); +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(true); + ASSERT(err_code == NRF_SUCCESS); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + uint32_t regstatus; + err_code = sd_power_usbregstatus_get(®status); + ASSERT(err_code == NRF_SUCCESS); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + if (regstatus & POWER_USBREGSTATUS_VBUSDETECT_Msk) + { + nrfx_power_usb_event_handler_t usbevt_handler = nrfx_power_usb_handler_get(); + ASSERT(usbevt_handler != NULL); + usbevt_handler(NRFX_POWER_USB_EVT_DETECTED); + } + } + else +#endif + { + nrfx_power_usbevt_enable(); + } + return NRF_SUCCESS; +} + +void nrf_drv_power_usbevt_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + CRITICAL_REGION_ENTER(); + if (nrf_sdh_is_enabled()) + { + ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(false); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); + } + else +#endif + { + nrfx_power_usbevt_disable(); + } +#ifdef SOFTDEVICE_PRESENT + CRITICAL_REGION_EXIT(); +#endif + nrfx_power_usbevt_uninit(); +} +#endif /* NRF_POWER_HAS_USBREG */ + +#ifdef SOFTDEVICE_PRESENT +static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context); +static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context); + +NRF_SDH_SOC_OBSERVER(m_soc_observer, POWER_CONFIG_SOC_OBSERVER_PRIO, + nrf_drv_power_sdh_soc_evt_handler, NULL); + +NRF_SDH_STATE_OBSERVER(m_sd_observer, POWER_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = nrf_drv_power_sdh_state_evt_handler, + .p_context = NULL +}; + +static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context) +{ + if (evt_id == NRF_EVT_POWER_FAILURE_WARNING) + { + nrfx_power_pofwarn_event_handler_t pofwarn_handler = nrfx_power_pof_handler_get(); + /* Cannot be null if event is enabled */ + ASSERT(pofwarn_handler != NULL); + pofwarn_handler(); + } + +#if NRF_POWER_HAS_USBREG + nrfx_power_usb_event_handler_t usbevt_handler = nrfx_power_usb_handler_get(); + if (usbevt_handler != NULL) + { + switch (evt_id) + { + case NRF_EVT_POWER_USB_POWER_READY: + usbevt_handler(NRFX_POWER_USB_EVT_READY); + break; + + case NRF_EVT_POWER_USB_DETECTED: + usbevt_handler(NRFX_POWER_USB_EVT_DETECTED); + break; + + case NRF_EVT_POWER_USB_REMOVED: + usbevt_handler(NRFX_POWER_USB_EVT_REMOVED); + break; + + default: + break; + + } + } +#endif +} + +static void nrf_drv_power_on_sd_enable(void) +{ + ASSERT(m_initialized); /* This module has to be enabled first */ + CRITICAL_REGION_ENTER(); + if (nrfx_power_pof_handler_get() != NULL) + { + ret_code_t err_code = sd_power_pof_enable(true); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); //handle no-debug case + } + CRITICAL_REGION_EXIT(); + +#if NRF_POWER_HAS_USBREG + if (nrfx_power_usb_handler_get() != NULL) + { + ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(true); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); //handle no-debug case + } +#endif +} + +static void nrf_drv_power_on_sd_disable(void) +{ + /* Reinit interrupts */ + ASSERT(m_initialized); + NRFX_IRQ_PRIORITY_SET(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY); + NRFX_IRQ_ENABLE(POWER_CLOCK_IRQn); + if (nrfx_power_pof_handler_get() != NULL) + { + nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK); + } + +#if NRF_POWER_HAS_USBREG + if (nrfx_power_usb_handler_get() != NULL) + { + nrf_power_int_enable( + NRF_POWER_INT_USBDETECTED_MASK | + NRF_POWER_INT_USBREMOVED_MASK | + NRF_POWER_INT_USBPWRRDY_MASK); + } +#endif +} + +static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLED: + nrf_drv_power_on_sd_enable(); + break; + + case NRF_SDH_EVT_STATE_DISABLED: + nrf_drv_power_on_sd_disable(); + break; + + default: + break; + } +} + +#endif // SOFTDEVICE_PRESENT +#endif //POWER_ENABLED diff --git a/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.h b/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.h index 170952789..347b18c89 100644 --- a/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.h +++ b/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.h @@ -1,232 +1,232 @@ -/** - * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef NRF_DRV_POWER_H__ -#define NRF_DRV_POWER_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup nrf_drv_power POWER driver - legacy layer - * @{ - * @ingroup nrf_power - * - * @brief Layer providing compatibility with the former API. - */ - -/** @brief Type definition for forwarding the new implementation. */ -typedef nrfx_power_config_t nrf_drv_power_config_t; -/** @brief Type definition for forwarding the new implementation. */ -typedef nrfx_power_pofwarn_config_t nrf_drv_power_pofwarn_config_t; -#if NRF_POWER_HAS_SLEEPEVT || defined(__SDK_DOXYGEN__) -/** @brief Type definition for forwarding the new implementation. */ -typedef nrfx_power_sleepevt_config_t nrf_drv_power_sleepevt_config_t; -#endif -#if NRF_POWER_HAS_USBREG || defined(__SDK_DOXYGEN__) -/** @brief Type definition for forwarding the new implementation. */ -typedef nrfx_power_usbevt_config_t nrf_drv_power_usbevt_config_t; -#endif - -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_MODE_CONSTLAT NRFX_POWER_MODE_CONSTLAT -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_MODE_LOWPWR NRFX_POWER_MODE_LOWPWR -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_power_mode_t nrfx_power_mode_t -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_SLEEP_EVT_ENTER NRFX_POWER_SLEEP_EVT_ENTER -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_SLEEP_EVT_EXIT NRFX_POWER_SLEEP_EVT_EXIT -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_power_sleep_evt_t nrfx_power_sleep_evt_t -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_USB_EVT_DETECTED NRFX_POWER_USB_EVT_DETECTED -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_USB_EVT_REMOVED NRFX_POWER_USB_EVT_REMOVED -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_USB_EVT_READY NRFX_POWER_USB_EVT_READY -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_power_usb_evt_t nrfx_power_usb_evt_t -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_USB_STATE_DISCONNECTED NRFX_POWER_USB_STATE_DISCONNECTED -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_USB_STATE_CONNECTED NRFX_POWER_USB_STATE_CONNECTED -/** @brief Macro for forwarding the new implementation. */ -#define NRF_DRV_POWER_USB_STATE_READY NRFX_POWER_USB_STATE_READY -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_power_usb_state_t nrfx_power_usb_state_t -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_power_pofwarn_event_handler_t nrfx_power_pofwarn_event_handler_t -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_power_sleep_event_handler_t nrfx_power_sleep_event_handler_t -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_power_usb_event_handler_t nrfx_power_usb_event_handler_t - -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_power_usbstatus_get nrfx_power_usbstatus_get - -/** - * @brief Function for checking if driver is already initialized - * - * This function is used to check whether common POWER_CLOCK interrupt - * should be disabled or not if @ref nrf_drv_clock tries to disable the interrupt. - * - * @retval true Driver is initialized - * @retval false Driver is uninitialized - * - * @sa nrf_drv_power_uninit - */ -bool nrf_drv_power_init_check(void); - -/** - * @brief Initialize power module driver - * - * Enabled power module driver would process all the interrupts from power system. - * - * @param[in] p_config Driver configuration. Can be NULL - the default configuration - * from @em sdk_config.h file would be used then. - * - * @retval NRF_ERROR_INVALID_STATE Power driver has to be enabled - * before SoftDevice. - * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED Module is initialized already. - * @retval NRF_SUCCESS Successfully initialized. - */ -ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config); - -/** - * @brief Unintialize power module driver - * - * Disables all the interrupt handling in the module. - * - * @sa nrf_drv_power_init - */ -void nrf_drv_power_uninit(void); - -/** - * @brief Initialize power failure comparator - * - * Configures and setups the power failure comparator and enables it. - * - * @param[in] p_config Configuration with values and event handler. - * If event handler is set to NULL, interrupt would be disabled. - * - * @retval NRF_ERROR_INVALID_STATE POF is initialized when SD is enabled and - * the configuration differs from the old one and - * is not possible to be set using SD interface. - * @retval NRF_SUCCESS Successfully initialized and configured. - */ -ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config); - -/** - * @brief Turn off the power failure comparator - * - * Disables and clears the settings of the power failure comparator. - */ -void nrf_drv_power_pof_uninit(void); - -#if NRF_POWER_HAS_SLEEPEVT || defined(__SDK_DOXYGEN__) - -/** - * @brief Initialize sleep entering and exiting events processing - * - * Configures and setups the sleep event processing. - * - * @param[in] p_config Configuration with values and event handler. - * - * @sa nrf_drv_power_sleepevt_uninit - * - * @note Sleep events are not available when SoftDevice is enabled. - * @note If sleep event is enabled when SoftDevice is initialized, sleep events - * would be automatically disabled - it is the limitation of the - * SoftDevice itself. - * - * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized - * when SD is enabled. - * @retval NRF_SUCCESS Successfully initialized and configured. - */ -ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config); - -/** - * @brief Uninitialize sleep entering and exiting events processing - * - * @sa nrf_drv_power_sleepevt_init - */ -void nrf_drv_power_sleepevt_uninit(void); - -#endif // NRF_POWER_HAS_SLEEPEVT || defined(__SDK_DOXYGEN__) - -#if NRF_POWER_HAS_USBREG || defined(__SDK_DOXYGEN__) - -/** - * @brief Initialize USB power event processing - * - * Configures and setups the USB power event processing. - * - * @param[in] p_config Configuration with values and event handler. - * - * @sa nrf_drv_power_usbevt_uninit - * - * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized - * when SD is enabled and SD does not support - * USB power events. - * @retval NRF_SUCCESS Successfully initialized and configured. - */ -ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config); - -/** - * @brief Uninitalize USB power event processing - * - * @sa nrf_drv_power_usbevt_init - */ -void nrf_drv_power_usbevt_uninit(void); - -#endif // NRF_POWER_HAS_USBREG || defined(__SDK_DOXYGEN__) - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif // NRF_DRV_POWER_H__ +/** + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_POWER_H__ +#define NRF_DRV_POWER_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_power POWER driver - legacy layer + * @{ + * @ingroup nrf_power + * + * @brief Layer providing compatibility with the former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_power_config_t nrf_drv_power_config_t; +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_power_pofwarn_config_t nrf_drv_power_pofwarn_config_t; +#if NRF_POWER_HAS_SLEEPEVT || defined(__SDK_DOXYGEN__) +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_power_sleepevt_config_t nrf_drv_power_sleepevt_config_t; +#endif +#if NRF_POWER_HAS_USBREG || defined(__SDK_DOXYGEN__) +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_power_usbevt_config_t nrf_drv_power_usbevt_config_t; +#endif + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_MODE_CONSTLAT NRFX_POWER_MODE_CONSTLAT +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_MODE_LOWPWR NRFX_POWER_MODE_LOWPWR +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_mode_t nrfx_power_mode_t +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_SLEEP_EVT_ENTER NRFX_POWER_SLEEP_EVT_ENTER +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_SLEEP_EVT_EXIT NRFX_POWER_SLEEP_EVT_EXIT +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_sleep_evt_t nrfx_power_sleep_evt_t +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_EVT_DETECTED NRFX_POWER_USB_EVT_DETECTED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_EVT_REMOVED NRFX_POWER_USB_EVT_REMOVED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_EVT_READY NRFX_POWER_USB_EVT_READY +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_usb_evt_t nrfx_power_usb_evt_t +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_STATE_DISCONNECTED NRFX_POWER_USB_STATE_DISCONNECTED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_STATE_CONNECTED NRFX_POWER_USB_STATE_CONNECTED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_STATE_READY NRFX_POWER_USB_STATE_READY +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_usb_state_t nrfx_power_usb_state_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_pofwarn_event_handler_t nrfx_power_pofwarn_event_handler_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_sleep_event_handler_t nrfx_power_sleep_event_handler_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_usb_event_handler_t nrfx_power_usb_event_handler_t + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_usbstatus_get nrfx_power_usbstatus_get + +/** + * @brief Function for checking if driver is already initialized + * + * This function is used to check whether common POWER_CLOCK interrupt + * should be disabled or not if @ref nrf_drv_clock tries to disable the interrupt. + * + * @retval true Driver is initialized + * @retval false Driver is uninitialized + * + * @sa nrf_drv_power_uninit + */ +bool nrf_drv_power_init_check(void); + +/** + * @brief Initialize power module driver + * + * Enabled power module driver would process all the interrupts from power system. + * + * @param[in] p_config Driver configuration. Can be NULL - the default configuration + * from @em sdk_config.h file would be used then. + * + * @retval NRF_ERROR_INVALID_STATE Power driver has to be enabled + * before SoftDevice. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED Module is initialized already. + * @retval NRF_SUCCESS Successfully initialized. + */ +ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config); + +/** + * @brief Unintialize power module driver + * + * Disables all the interrupt handling in the module. + * + * @sa nrf_drv_power_init + */ +void nrf_drv_power_uninit(void); + +/** + * @brief Initialize power failure comparator + * + * Configures and setups the power failure comparator and enables it. + * + * @param[in] p_config Configuration with values and event handler. + * If event handler is set to NULL, interrupt would be disabled. + * + * @retval NRF_ERROR_INVALID_STATE POF is initialized when SD is enabled and + * the configuration differs from the old one and + * is not possible to be set using SD interface. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config); + +/** + * @brief Turn off the power failure comparator + * + * Disables and clears the settings of the power failure comparator. + */ +void nrf_drv_power_pof_uninit(void); + +#if NRF_POWER_HAS_SLEEPEVT || defined(__SDK_DOXYGEN__) + +/** + * @brief Initialize sleep entering and exiting events processing + * + * Configures and setups the sleep event processing. + * + * @param[in] p_config Configuration with values and event handler. + * + * @sa nrf_drv_power_sleepevt_uninit + * + * @note Sleep events are not available when SoftDevice is enabled. + * @note If sleep event is enabled when SoftDevice is initialized, sleep events + * would be automatically disabled - it is the limitation of the + * SoftDevice itself. + * + * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized + * when SD is enabled. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config); + +/** + * @brief Uninitialize sleep entering and exiting events processing + * + * @sa nrf_drv_power_sleepevt_init + */ +void nrf_drv_power_sleepevt_uninit(void); + +#endif // NRF_POWER_HAS_SLEEPEVT || defined(__SDK_DOXYGEN__) + +#if NRF_POWER_HAS_USBREG || defined(__SDK_DOXYGEN__) + +/** + * @brief Initialize USB power event processing + * + * Configures and setups the USB power event processing. + * + * @param[in] p_config Configuration with values and event handler. + * + * @sa nrf_drv_power_usbevt_uninit + * + * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized + * when SD is enabled and SD does not support + * USB power events. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config); + +/** + * @brief Uninitalize USB power event processing + * + * @sa nrf_drv_power_usbevt_init + */ +void nrf_drv_power_usbevt_uninit(void); + +#endif // NRF_POWER_HAS_USBREG || defined(__SDK_DOXYGEN__) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_POWER_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/README.md b/third_party/NordicSemiconductor/drivers/radio/README.md index ec3cb58e8..ba308c1f6 100644 --- a/third_party/NordicSemiconductor/drivers/radio/README.md +++ b/third_party/NordicSemiconductor/drivers/radio/README.md @@ -1,3 +1,3 @@ -# nRF 802.15.4 radio driver. - +# nRF 802.15.4 radio driver. + Copy of [the nRF52840 IEEE 802.15.4 radio driver](https://github.com/NordicSemiconductor/nRF-IEEE-802.15.4-radio-driver). \ No newline at end of file diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h index cf7394ede..6d8abd635 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h @@ -1,1179 +1,1179 @@ -/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @defgroup nrf_802154 802.15.4 radio driver - * @{ - * - */ - -#ifndef NRF_802154_H_ -#define NRF_802154_H_ - -#include -#include - -#include "nrf_802154_config.h" -#include "nrf_802154_types.h" - -#if ENABLE_FEM -#include "fem/nrf_fem_control_api.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Timestamp value indicating that the timestamp is inaccurate. - */ -#define NRF_802154_NO_TIMESTAMP 0 - -/** - * @brief Initializes the 802.15.4 driver. - * - * This function initializes the RADIO peripheral in the @ref RADIO_STATE_SLEEP state. - * - * @note This function is to be called once, before any other functions from this module. - */ -void nrf_802154_init(void); - -/** - * @brief Deinitializes the 802.15.4 driver. - * - * This function deinitializes the RADIO peripheral and resets it to the default state. - */ -void nrf_802154_deinit(void); - -#if !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING -/** - * @brief Handles the interrupt request from the RADIO peripheral. - * - * @note If NRF_802154_INTERNAL_RADIO_IRQ_HANDLING is enabled, the driver internally handles the - * RADIO IRQ, and this function must not be called. - * - * This function is intended for use in an operating system environment, where the OS handles IRQ - * and indirectly passes it to the driver, or with a RAAL implementation that indirectly passes - * radio IRQ to the driver (that is, SoftDevice). - */ -void nrf_802154_radio_irq_handler(void); -#endif // !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING - -/** - * @brief Sets the channel on which the radio is to operate. - * - * @param[in] channel Channel number (11-26). - */ -void nrf_802154_channel_set(uint8_t channel); - -/** - * @brief Gets the channel on which the radio operates. - * - * @returns Channel number (11-26). - */ -uint8_t nrf_802154_channel_get(void); - -/** - * @brief Sets the transmit power. - * - * @note The driver recalculates the requested value to the nearest value accepted by the hardware. - * The calculation result is rounded up. - * - * @param[in] power Transmit power in dBm. - */ -void nrf_802154_tx_power_set(int8_t power); - -/** - * @brief Gets the currently set transmit power. - * - * @returns Currently used transmit power, in dBm. - */ -int8_t nrf_802154_tx_power_get(void); - -/** - * @defgroup nrf_802154_frontend Frontend Module management - * @{ - */ - -#if ENABLE_FEM - -/** Structure that contains the run-time configuration of the Frontend Module. */ -typedef nrf_fem_control_cfg_t nrf_802154_fem_control_cfg_t; - -/** Macro with the default configuration of the Frontend Module. */ -#define NRF_802154_FEM_DEFAULT_SETTINGS \ - ((nrf_802154_fem_control_cfg_t) { \ - .pa_cfg = { \ - .enable = 1, \ - .active_high = 1, \ - .gpio_pin = NRF_FEM_CONTROL_DEFAULT_PA_PIN, \ - }, \ - .lna_cfg = { \ - .enable = 1, \ - .active_high = 1, \ - .gpio_pin = NRF_FEM_CONTROL_DEFAULT_LNA_PIN, \ - }, \ - .pa_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL, \ - .lna_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL, \ - .ppi_ch_id_set = NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL, \ - .ppi_ch_id_clr = NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL, \ - }) - -/** - * @brief Sets the PA & LNA GPIO toggle configuration. - * - * @note This function must not be called when the radio is in use. - * - * @param[in] p_cfg Pointer to the PA & LNA GPIO toggle configuration. - * - */ -void nrf_802154_fem_control_cfg_set(const nrf_802154_fem_control_cfg_t * p_cfg); - -/** - * @brief Get the PA & LNA GPIO toggle configuration. - * - * @param[out] p_cfg Pointer to the structure for the PA & LNA GPIO toggle configuration. - * - */ -void nrf_802154_fem_control_cfg_get(nrf_802154_fem_control_cfg_t * p_cfg); - -#endif // ENABLE_FEM - -/** - * @} - * @defgroup nrf_802154_addresses Setting addresses and PAN ID of the device - * @{ - */ - -/** - * @brief Sets the PAN ID used by the device. - * - * @param[in] p_pan_id Pointer to the PAN ID (2 bytes, little-endian). - * - * This function makes a copy of the PAN ID. - */ -void nrf_802154_pan_id_set(const uint8_t * p_pan_id); - -/** - * @brief Sets the extended address of the device. - * - * @param[in] p_extended_address Pointer to the extended address (8 bytes, little-endian). - * - * This function makes a copy of the address. - */ -void nrf_802154_extended_address_set(const uint8_t * p_extended_address); - -/** - * @brief Sets the short address of the device. - * - * @param[in] p_short_address Pointer to the short address (2 bytes, little-endian). - * - * This function makes a copy of the address. - */ -void nrf_802154_short_address_set(const uint8_t * p_short_address); - -/** - * @} - * @defgroup nrf_802154_data Functions to calculate data given by the driver - * @{ - */ - -/** - * @brief Converts the energy level received during the energy detection procedure to a dBm value. - * - * @param[in] energy_level Energy level passed by @ref nrf_802154_energy_detected. - * - * @return Result of the energy detection procedure in dBm. - */ -int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level); - -/** - * @brief Converts a given dBm level to a CCA energy detection threshold value. - * - * @param[in] dbm Energy level in dBm used to calculate the CCAEDTHRES value. - * - * @return Energy level value corresponding to the given dBm level that is to be written to - * the CCACTRL register. - */ -uint8_t nrf_802154_ccaedthres_from_dbm_calculate(int8_t dbm); - -/** - * @brief Calculates the timestamp of the first symbol of the preamble in a received frame. - * - * @param[in] end_timestamp Timestamp of the end of the last symbol in the frame, - * in microseconds. - * @param[in] psdu_length Number of bytes in the frame PSDU. - * - * @return Timestamp of the beginning of the first preamble symbol of a given frame, - * in microseconds. - */ -uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t psdu_length); - -/** - * @} - * @defgroup nrf_802154_transitions Functions to request FSM transitions and check current state - * @{ - */ - -/** - * @brief Gets the current state of the radio. - */ -nrf_802154_state_t nrf_802154_state_get(void); - -/** - * @brief Changes the radio state to the @ref RADIO_STATE_SLEEP state. - * - * The sleep state is the lowest power state. In this state, the radio cannot transmit or receive - * frames. It is the only state in which the driver releases the high-frequency clock and does not - * request timeslots from a radio arbiter. - * - * @note If another module requests it, the high-frequency clock may be enabled even in the radio - * sleep state. - * - * @retval true The radio changes its state to the low power mode. - * @retval false The driver could not schedule changing state. - */ -bool nrf_802154_sleep(void); - -/** - * @brief Changes the radio state to the @ref RADIO_STATE_SLEEP state if the radio is idle. - * - * The sleep state is the lowest power state. In this state, the radio cannot transmit or receive - * frames. It is the only state in which the driver releases the high-frequency clock and does not - * request timeslots from a radio arbiter. - * - * @note If another module requests it, the high-frequency clock may be enabled even in the radio - * sleep state. - * - * @retval NRF_802154_SLEEP_ERROR_NONE The radio changes its state to the low power mode. - * @retval NRF_802154_SLEEP_ERROR_BUSY The driver could not schedule changing state. - */ -nrf_802154_sleep_error_t nrf_802154_sleep_if_idle(void); - -/** - * @brief Changes the radio state to @ref RADIO_STATE_RX. - * - * In the receive state, the radio receives frames and may automatically send ACK frames when - * appropriate. The received frame is reported to the higher layer by a call to - * @ref nrf_802154_received. - * - * @retval true The radio enters the receive state. - * @retval false The driver could not enter the receive state. - */ -bool nrf_802154_receive(void); - -/** - * @brief Requests reception at the specified time. - * - * This function works as a delayed version of @ref nrf_802154_receive. It is asynchronous. - * It queues the delayed reception using the Radio Scheduler module. - * If the delayed reception cannot be performed (@ref nrf_802154_receive_at would return false) - * or the requested reception timeslot is denied, @ref nrf_drv_radio802154_receive_failed is called - * with the @ref NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED argument. - * - * If the requested reception time is in the past, the function returns false and does not - * schedule reception. - * - * A scheduled reception can be cancelled by a call to @ref nrf_802154_receive_at_cancel. - * - * @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler, - * in microseconds (us). - * @param[in] dt Delta of delay time from @p t0, in microseconds (us). - * @param[in] timeout Reception timeout (counted from @p t0 + @p dt), in microseconds (us). - * @param[in] channel Radio channel on which the frame is to be received. - * - * @retval true The reception procedure was scheduled. - * @retval false The driver could not schedule the reception procedure. - */ -bool nrf_802154_receive_at(uint32_t t0, - uint32_t dt, - uint32_t timeout, - uint8_t channel); - -/** - * @brief Cancels a delayed reception scheduled by a call to @ref nrf_802154_receive_at. - * - * If the receive window has been scheduled but has not started yet, this function prevents - * entering the receive window. If the receive window has been scheduled and has already started, - * the radio remains in the receive state, but a window timeout will not be reported. - * - * @retval true The delayed reception was scheduled and successfully cancelled. - * @retval false No delayed reception was scheduled. - */ -bool nrf_802154_receive_at_cancel(void); - -#if NRF_802154_USE_RAW_API -/** - * @brief Changes the radio state to @ref RADIO_STATE_TX. - * - * @note If the CPU is halted or interrupted while this function is executed, - * @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed can be called before this - * function returns a result. - * - * @note This function is implemented in zero-copy fashion. It passes the given buffer pointer to - * the RADIO peripheral. - * - * In the transmit state, the radio transmits a given frame. If requested, it waits for - * an ACK frame. Depending on @ref NRF_802154_ACK_TIMEOUT_ENABLED, the radio driver automatically - * stops waiting for an ACK frame or waits indefinitely for an ACK frame. If it is configured to - * wait, the MAC layer is responsible for calling @ref nrf_802154_receive or - * @ref nrf_802154_sleep after the ACK timeout. - * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted - * or @ref nrf_802154_transmit_failed. - * - * @verbatim - * p_data - * v - * +-----+-----------------------------------------------------------+------------+ - * | PHR | MAC header and payload | FCS | - * +-----+-----------------------------------------------------------+------------+ - * | | - * | <---------------------------- PHR -----------------------------------> | - * @endverbatim - * - * @param[in] p_data Pointer to the array with data to transmit. The first byte must contain frame - * length (including PHR and FCS). The following bytes contain data. The CRC is - * computed automatically by the radio hardware. Therefore, the FCS field can - * contain any bytes. - * @param[in] cca If the driver is to perform a CCA procedure before transmission. - * - * @retval true The transmission procedure was scheduled. - * @retval false The driver could not schedule the transmission procedure. - */ -bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca); - -#else // NRF_802154_USE_RAW_API - -/** - * @brief Changes the radio state to transmit. - * - * @note If the CPU is halted or interrupted while this function is executed, - * @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed must be called before this - * function returns a result. - * - * @note This function copies the given buffer. It maintains an internal buffer, which is used to - * make a frame copy. To prevent unnecessary memory consumption and to perform zero-copy - * transmission, use @ref nrf_802154_transmit_raw instead. - * - * In the transmit state, the radio transmits a given frame. If requested, it waits for - * an ACK frame. Depending on @ref NRF_802154_ACK_TIMEOUT_ENABLED, the radio driver automatically - * stops waiting for an ACK frame or waits indefinitely for an ACK frame. If it is configured to - * wait, the MAC layer is responsible for calling @ref nrf_802154_receive or - * @ref nrf_802154_sleep after the ACK timeout. - * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted - * or @ref nrf_802154_transmit_failed. - * - * @verbatim - * p_data - * v - * +-----+-----------------------------------------------------------+------------+ - * | PHR | MAC header and payload | FCS | - * +-----+-----------------------------------------------------------+------------+ - * | | - * | <------------------ length -----------------------------> | - * @endverbatim - * - * @param[in] p_data Pointer to the array with the payload of data to transmit. The array should - * exclude PHR or FCS fields of the 802.15.4 frame. - * @param[in] length Length of the given frame. This value must exclude PHR and FCS fields from - * the given frame (exact size of buffer pointed to by @p p_data). - * @param[in] cca If the driver is to perform a CCA procedure before transmission. - * - * @retval true The transmission procedure was scheduled. - * @retval false The driver could not schedule the transmission procedure. - */ -bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca); - -#endif // NRF_802154_USE_RAW_API - -/** - * @brief Requests transmission at the specified time. - * - * @note This function is implemented in a zero-copy fashion. It passes the given buffer pointer to - * the RADIO peripheral. - * - * This function works as a delayed version of @ref nrf_802154_transmit_raw. It is asynchronous. - * It queues the delayed transmission using the Radio Scheduler module and performs it - * at the specified time. - * - * If the delayed transmission is successfully performed, @ref nrf_802154_transmitted is called. - * If the delayed transmission cannot be performed (@ref nrf_802154_transmit_raw would return false) - * or the requested transmission timeslot is denied, @ref nrf_802154_transmit_failed with the - * @ref NRF_802154_TX_ERROR_TIMESLOT_DENIED argument is called. - * - * This function is designed to transmit the first symbol of SHR at the given time. - * - * If the requested transmission time is in the past, the function returns false and does not - * schedule transmission. - * - * A successfully scheduled transmission can be cancelled by a call - * to @ref nrf_802154_transmit_at_cancel. - * - * @param[in] p_data Pointer to the array with data to transmit. The first byte must contain - * the frame length (including PHR and FCS). The following bytes contain data. - * The CRC is computed automatically by the radio hardware. Therefore, the FCS - * field can contain any bytes. - * @param[in] cca If the driver is to perform a CCA procedure before transmission. - * @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler, - * in microseconds (us). - * @param[in] dt Delta of delay time from @p t0, in microseconds (us). - * @param[in] channel Radio channel on which the frame is to be transmitted. - * - * @retval true The transmission procedure was scheduled. - * @retval false The driver could not schedule the transmission procedure. - */ -bool nrf_802154_transmit_raw_at(const uint8_t * p_data, - bool cca, - uint32_t t0, - uint32_t dt, - uint8_t channel); - -/** - * @brief Cancels a delayed transmission scheduled by a call to @ref nrf_802154_transmit_raw_at. - * - * If a delayed transmission has been scheduled but the transmission has not been started yet, - * a call to this function prevents the transmission. If the transmission is ongoing, - * it will not be aborted. - * - * If a delayed transmission has not been scheduled (or has already finished), this function does - * not change state and returns false. - * - * @retval true The delayed transmission was scheduled and successfully cancelled. - * @retval false No delayed transmission was scheduled. - */ -bool nrf_802154_transmit_at_cancel(void); - -/** - * @brief Changes the radio state to energy detection. - * - * In the energy detection state, the radio detects the maximum energy for a given time. - * The result of the detection is reported to the higher layer by @ref nrf_802154_energy_detected. - * - * @note @ref nrf_802154_energy_detected can be called before this function returns a result. - * @note Performing the energy detection procedure can take longer than requested in @p time_us. - * The procedure is performed only during the timeslots granted by a radio arbiter. - * It can be interrupted by other protocols using the radio hardware. If the procedure is - * interrupted, it is automatically continued and the sum of time periods during which the - * procedure is carried out is not less than the requested @p time_us. - * - * @param[in] time_us Duration of energy detection procedure. The given value is rounded up to - * multiplication of 8 symbols (128 us). - * - * @retval true The energy detection procedure was scheduled. - * @retval false The driver could not schedule the energy detection procedure. - */ -bool nrf_802154_energy_detection(uint32_t time_us); - -/** - * @brief Changes the radio state to @ref RADIO_STATE_CCA. - * - * @note @ref nrf_802154_cca_done can be called before this function returns a result. - * - * In the CCA state, the radio verifies if the channel is clear. The result of the verification is - * reported to the higher layer by @ref nrf_802154_cca_done. - * - * @retval true The CCA procedure was scheduled. - * @retval false The driver could not schedule the CCA procedure. - */ -bool nrf_802154_cca(void); - -/** - * @brief Changes the radio state to continuous carrier. - * - * @note When the radio is emitting continuous carrier signals, it blocks all transmissions on the - * selected channel. This function is to be called only during radio tests. Do not - * use it during normal device operation. - * - * @retval true The continuous carrier procedure was scheduled. - * @retval false The driver could not schedule the continuous carrier procedure. - */ -bool nrf_802154_continuous_carrier(void); - -/** - * @} - * @defgroup nrf_802154_calls Calls to higher layer - * @{ - */ - -/** - * @brief Notifies about the start of the ACK frame transmission. - * - * @note This function must be very short to prevent dropping frames by the driver. - * - * @param[in] p_data Pointer to a buffer with PHR and PSDU of the ACK frame. - */ -extern void nrf_802154_tx_ack_started(const uint8_t * p_data); - -#if NRF_802154_USE_RAW_API - -/** - * @brief Notifies that a frame was received. - * - * @note The buffer pointed to by @p p_data is not modified by the radio driver (and cannot be used - * to receive a frame) until @ref nrf_802154_buffer_free_raw is called. - * @note The buffer pointed to by @p p_data may be modified by the function handler (and other - * modules) until @ref nrf_802154_buffer_free_raw is called. - * - * @verbatim - * p_data - * v - * +-----+-----------------------------------------------------------+------------+ - * | PHR | MAC Header and payload | FCS | - * +-----+-----------------------------------------------------------+------------+ - * | | - * | <---------------------------- PHR -----------------------------------> | - * @endverbatim - * - * @param[in] p_data Pointer to a buffer that contains PHR and PSDU of the received frame. - * The first byte in the buffer is the length of the frame (PHR). The following - * bytes contain the frame itself (PSDU). The length byte (PHR) includes FCS. - * FCS is already verified by the hardware and may be modified by the hardware. - * @param[in] power RSSI of the received frame. - * @param[in] lqi LQI of the received frame. - */ -extern void nrf_802154_received_raw(uint8_t * p_data, int8_t power, uint8_t lqi); - -/** - * @brief Notifies that a frame was received at a given time. - * - * This function works like @ref nrf_802154_received_raw and adds a timestamp to the parameter - * list. - * - * @note The received frame usually contains a timestamp. However, due to a race condition, - * the timestamp may be invalid. This erroneous situation is indicated by - * the @ref NRF_802154_NO_TIMESTAMP value of the @p time parameter. - * - * @param[in] p_data Pointer to a buffer that contains PHR and PSDU of the received frame. - * The first byte in the buffer is the length of the frame (PHR). The following - * bytes contain the frame itself (PSDU). The length byte (PHR) includes FCS. - * FCS is already verified by the hardware and may be modified by the hardware. - * @param[in] power RSSI of the received frame. - * @param[in] lqi LQI of the received frame. - * @param[in] time Timestamp taken when the last symbol of the frame was received, in - * microseconds (us), or @ref NRF_802154_NO_TIMESTAMP if the timestamp - * is invalid. - */ -extern void nrf_802154_received_timestamp_raw(uint8_t * p_data, - int8_t power, - uint8_t lqi, - uint32_t time); - -#else // NRF_802154_USE_RAW_API - -/** - * @brief Notifies that a frame was received. - * - * @note The buffer pointed to by @p p_data is not modified by the radio driver (and cannot - * be used to receive a frame) until @ref nrf_802154_buffer_free is called. - * @note The buffer pointed to by @p p_data can be modified by the function handler (and other - * modules) until @ref nrf_802154_buffer_free is called. - * - * @verbatim - * p_data - * v - * +-----+-----------------------------------------------------------+------------+ - * | PHR | MAC Header and payload | FCS | - * +-----+-----------------------------------------------------------+------------+ - * | | - * | <------------------ length -----------------------------> | - * @endverbatim - * - * @param[in] p_data Pointer to a buffer that contains only the payload of the received frame - * (PSDU without FCS). - * @param[in] length Length of the received payload. - * @param[in] power RSSI of the received frame. - * @param[in] lqi LQI of the received frame. - */ -extern void nrf_802154_received(uint8_t * p_data, uint8_t length, int8_t power, uint8_t lqi); - -/** - * @brief Notifies that a frame was received at a given time. - * - * This function works like @ref nrf_802154_received and adds a timestamp to the parameter list. - * - * @note The received frame usually contains a timestamp. However, due to a race condition, - * the timestamp may be invalid. This erroneous situation is indicated by - * the @ref NRF_802154_NO_TIMESTAMP value of the @p time parameter. - * - * @param[in] p_data Pointer to a buffer that contains only the payload of the received frame - * (PSDU without FCS). - * @param[in] length Length of the received payload. - * @param[in] power RSSI of the received frame. - * @param[in] lqi LQI of the received frame. - * @param[in] time Timestamp taken when the last symbol of the frame was received, - * in microseconds (us), or @ref NRF_802154_NO_TIMESTAMP if the timestamp - * is invalid. - */ -extern void nrf_802154_received_timestamp(uint8_t * p_data, - uint8_t length, - int8_t power, - uint8_t lqi, - uint32_t time); - -#endif // !NRF_802154_USE_RAW_API - -/** - * @brief Notifies that the reception of a frame failed. - * - * @param[in] error Error code that indicates the reason of the failure. - */ -extern void nrf_802154_receive_failed(nrf_802154_rx_error_t error); - -/** - * @brief Notifies that transmitting a frame has started. - * - * @note Usually, @ref nrf_802154_transmitted is called shortly after this function. - * However, if the transmit procedure is interrupted, it might happen that - * @ref nrf_802154_transmitted is not called. - * @note This function should be very short to prevent dropping frames by the driver. - * - * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame being - * transmitted. - */ -extern void nrf_802154_tx_started(const uint8_t * p_frame); - -#if NRF_802154_USE_RAW_API - -/** - * @brief Notifies that a frame was transmitted. - * - * @note If ACK was requested for the transmitted frame, this function is called after a proper ACK - * is received. If ACK was not requested, this function is called just after transmission has - * ended. - * @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot be used - * to receive a frame) until @ref nrf_802154_buffer_free_raw is called. - * @note The buffer pointed to by @p p_ack may be modified by the function handler (and other - * modules) until @ref nrf_802154_buffer_free_raw is called. - * - * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame. - * @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of the received ACK. - * The first byte in the buffer is the length of the frame (PHR). The following - * bytes contain the ACK frame itself (PSDU). The length byte (PHR) includes - * FCS. FCS is already verified by the hardware and may be modified by the - * hardware. If ACK was not requested, @p p_ack is set to NULL. - * @param[in] power RSSI of the received frame or 0 if ACK was not requested. - * @param[in] lqi LQI of the received frame or 0 if ACK was not requested. - */ -extern void nrf_802154_transmitted_raw(const uint8_t * p_frame, - uint8_t * p_ack, - int8_t power, - uint8_t lqi); - -/** - * @brief Notifies that a frame was transmitted. - * - * This function works like @ref nrf_802154_transmitted_raw and adds a timestamp to the parameter - * list. - * - * @note @p timestamp may be inaccurate due to software latency (IRQ handling). - * @note @p timestamp granularity depends on the granularity of the timer driver in the - * platform/timer directory. - * @note Including a timestamp for received frames uses resources like CPU time and memory. If the - * timestamp is not required, use @ref nrf_802154_received instead. - * - * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame. - * @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of the received ACK. - * The first byte in the buffer is the length of the frame (PHR). The following - * bytes contain the ACK frame itself (PSDU). The length byte (PHR) includes - * FCS. FCS is already verified by the hardware and may be modified by the - * hardware. If ACK was not requested, @p p_ack is set to NULL. - * @param[in] power RSSI of the received frame or 0 if ACK was not requested. - * @param[in] lqi LQI of the received frame or 0 if ACK was not requested. - * @param[in] time Timestamp taken when the last symbol of ACK is received or 0 if ACK was not - * requested. - */ -extern void nrf_802154_transmitted_timestamp_raw(const uint8_t * p_frame, - uint8_t * p_ack, - int8_t power, - uint8_t lqi, - uint32_t time); - -#else // NRF_802154_USE_RAW_API - -/** - * @brief Notifies that a frame was transmitted. - * - * @note If ACK was requested for the transmitted frame, this function is called after a proper ACK - * is received. If ACK was not requested, this function is called just after transmission has - * ended. - * @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot - * be used to receive a frame) until @ref nrf_802154_buffer_free is - * called. - * @note The buffer pointed to by @p p_ack may be modified by the function handler (and other - * modules) until @ref nrf_802154_buffer_free is called. - * @note The next higher layer must handle either @ref nrf_802154_transmitted or - * @ref nrf_802154_transmitted_raw. It should not handle both functions. - * - * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame. - * @param[in] p_ack Pointer to a buffer that contains only the received ACK payload (PSDU - * excluding FCS). - * If ACK was not requested, @p p_ack is set to NULL. - * @param[in] length Length of the received ACK payload or 0 if ACK was not requested. - * @param[in] power RSSI of the received frame or 0 if ACK was not requested. - * @param[in] lqi LQI of the received frame or 0 if ACK was not requested. - */ -extern void nrf_802154_transmitted(const uint8_t * p_frame, - uint8_t * p_ack, - uint8_t length, - int8_t power, - uint8_t lqi); - -/** - * @brief Notifies that a frame was transmitted. - * - * This function works like @ref nrf_802154_transmitted and adds a timestamp to the parameter - * list. - * - * @note @p timestamp may be inaccurate due to software latency (IRQ handling). - * @note @p timestamp granularity depends on the granularity of the timer driver - * in the platform/timer directory. - * @note Including a timestamp for received frames uses resources like CPU time and memory. If the - * timestamp is not required, use @ref nrf_802154_received instead. - * - * @param[in] p_frame Pointer to the buffer containing PHR and PSDU of the transmitted frame. - * @param[in] p_ack Pointer to the buffer containing only the received ACK payload (PSDU - * excluding FCS). - * If ACK was not requested, @p p_ack is set to NULL. - * @param[in] length Length of the received ACK payload. - * @param[in] power RSSI of the received frame or 0 if ACK was not requested. - * @param[in] lqi LQI of the received frame or 0 if ACK was not requested. - * @param[in] time Timestamp taken when the last symbol of ACK is received or 0 if ACK was not - * requested. - */ -extern void nrf_802154_transmitted_timestamp(const uint8_t * p_frame, - uint8_t * p_ack, - uint8_t length, - int8_t power, - uint8_t lqi, - uint32_t time); - -#endif // !NRF_802154_USE_RAW_API - -/** - * @brief Notifies that a frame was not transmitted due to a busy channel. - * - * This function is called if the transmission procedure fails. - * - * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that was not - * transmitted. - * @param[in] error Reason of the failure. - */ -extern void nrf_802154_transmit_failed(const uint8_t * p_frame, - nrf_802154_tx_error_t error); - -/** - * @brief Notifies that the energy detection procedure finished. - * - * @note This function passes the EnergyLevel defined in the 802.15.4-2006 specification: - * 0x00 - 0xff, proportionally to the detected energy level (dBm above receiver sensitivity). - * To calculate the result in dBm, use @ref nrf_802154_dbm_from_energy_level_calculate. - * - * @param[in] result Maximum energy detected during the energy detection procedure. - */ -extern void nrf_802154_energy_detected(uint8_t result); - -/** - * @brief Notifies that the energy detection procedure failed. - * - * @param[in] error Reason of the failure. - */ -extern void nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error); - -/** - * @brief Notifies that the CCA procedure has finished. - * - * @param[in] channel_free Indication if the channel is free. - */ -extern void nrf_802154_cca_done(bool channel_free); - -/** - * @brief Notifies that the CCA procedure failed. - * - * @param[in] error Reason of the failure. - */ -extern void nrf_802154_cca_failed(nrf_802154_cca_error_t error); - -/** - * @} - * @defgroup nrf_802154_memman Driver memory management - * @{ - */ - -#if NRF_802154_USE_RAW_API - -/** - * @brief Notifies the driver that the buffer containing the received frame is not used anymore. - * - * @note The buffer pointed to by @p p_data may be modified by this function. - * @note This function can be safely called only from the main context. To free the buffer from - * a callback or the IRQ context, use @ref nrf_802154_buffer_free_immediately_raw. - * - * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed - * by the higher layer. - */ -void nrf_802154_buffer_free_raw(uint8_t * p_data); - -/** - * @brief Notifies the driver that the buffer containing the received frame is not used anymore. - * - * @note The buffer pointed to by @p p_data may be modified by this function. - * @note This function can be safely called from any context. If the driver is busy processing - * a request called from a context with lower priority, this function returns false and - * the caller should free the buffer later. - * - * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed - * by the higher layer. - * - * @retval true Buffer was freed successfully. - * @retval false Buffer cannot be freed right now due to ongoing operation. - */ -bool nrf_802154_buffer_free_immediately_raw(uint8_t * p_data); - -#else // NRF_802154_USE_RAW_API - -/** - * @brief Notifies the driver that the buffer containing the received frame is not used anymore. - * - * @note The buffer pointed to by @p p_data may be modified by this function. - * @note This function can be safely called only from the main context. To free the buffer from - * a callback or IRQ context, use @ref nrf_802154_buffer_free_immediately. - * - * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed - * by the higher layer. - */ -void nrf_802154_buffer_free(uint8_t * p_data); - -/** - * @brief Notifies the driver that the buffer containing the received frame is not used anymore. - * - * @note The buffer pointed to by @p p_data may be modified by this function. - * @note This function can be safely called from any context. If the driver is busy processing - * a request called from a context with lower priority, this function returns false and - * the caller should free the buffer later. - * - * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed - * by the higher layer. - * - * @retval true Buffer was freed successfully. - * @retval false Buffer cannot be freed right now due to ongoing operation. - */ -bool nrf_802154_buffer_free_immediately(uint8_t * p_data); - -#endif // NRF_802154_USE_RAW_API - -/** - * @} - * @defgroup nrf_802154_rssi RSSI measurement function - * @{ - */ - -/** - * @brief Begins the RSSI measurement. - * - * @note This function is to be called in the @ref RADIO_STATE_RX state. - * - * The result will be available after the measurement process is finished. The result can be read by - * @ref nrf_802154_rssi_last_get. Check the documentation of the RADIO peripheral to check - * the duration of the RSSI measurement procedure. - * - * @retval true RSSI measurement successfully requested. - * @retval false RSSI measurement cannot be scheduled at the moment. - */ -bool nrf_802154_rssi_measure_begin(void); - -/** - * @brief Gets the result of the last RSSI measurement. - * - * @returns RSSI measurement result, in dBm. - */ -int8_t nrf_802154_rssi_last_get(void); - -/** - * @} - * @defgroup nrf_802154_prom Promiscuous mode - * @{ - */ - -/** - * @brief Enables or disables the promiscuous radio mode. - * - * @note The promiscuous mode is disabled by default. - * - * In the promiscuous mode, the driver notifies the higher layer that it received any frame - * (regardless frame type or destination address). - * In normal mode (not promiscuous), the higher layer is not notified about ACK frames and frames - * with unknown type. Also, frames with a destination address not matching the device address are - * ignored. - * - * @param[in] enabled If the promiscuous mode is to be enabled. - */ -void nrf_802154_promiscuous_set(bool enabled); - -/** - * @brief Checks if the radio is in the promiscuous mode. - * - * @retval True Radio is in the promiscuous mode. - * @retval False Radio is not in the promiscuous mode. - */ -bool nrf_802154_promiscuous_get(void); - -/** - * @} - * @defgroup nrf_802154_autoack Auto ACK management - * @{ - */ - -/** - * @brief Enables or disables the automatic acknowledgments (auto ACK). - * - * @note The auto ACK is enabled by default. - * - * If the auto ACK is enabled, the driver prepares and sends ACK frames automatically - * aTurnaroundTime (192 us) after the proper frame is received. The driver prepares an ACK frame - * according to the data provided by @ref nrf_802154_ack_data_set. - * When the auto ACK is enabled, the driver notifies the next higher layer about the received frame - * after the ACK frame is transmitted. - * If the auto ACK is disabled, the driver does not transmit ACK frames. It notifies the next higher - * layer about the received frames when a frame is received. In this mode, the next higher layer is - * responsible for sending the ACK frame. ACK frames should be sent using @ref nrf_802154_transmit. - * - * @param[in] enabled If the auto ACK should be enabled. - */ -void nrf_802154_auto_ack_set(bool enabled); - -/** - * @brief Checks if the auto ACK is enabled. - * - * @retval True Auto ACK is enabled. - * @retval False Auto ACK is disabled. - */ -bool nrf_802154_auto_ack_get(void); - -/** - * @brief Configures the device as the PAN coordinator. - * - * @note That information is used for packet filtering. - * - * @param[in] enabled The radio is configured as the PAN coordinator. - */ -void nrf_802154_pan_coord_set(bool enabled); - -/** - * @brief Checks if the radio is configured as the PAN coordinator. - * - * @retval true The radio is configured as the PAN coordinator. - * @retval false The radio is not configured as the PAN coordinator. - */ -bool nrf_802154_pan_coord_get(void); - -/** - * @brief Adds the address of a peer node for which the provided ACK data is to be set. - * - * @param[in] p_addr Array of bytes containing the address of the node (little-endian). - * @param[in] extended If the given address is an extended MAC address or a short MAC address. - * @param[in] p_data Pointer to the buffer containing data to be set. - * @param[in] length Length of @p p_data. - * @param[in] data_type Type of data to be set. Refer to the @ref nrf_802154_ack_data_t type. - * - * @retval True Address successfully added to the list. - * @retval False Not enough memory to store this address in the list. - */ -bool nrf_802154_ack_data_set(const uint8_t * p_addr, - bool extended, - const void * p_data, - uint16_t length, - uint8_t data_type); - -/** - * @brief Removes the address of a peer node for which the ACK data is set. - * - * The ACK data that was previously set for the given address is automatically removed. - * - * @param[in] p_addr Array of bytes containing the address of the node (little-endian). - * @param[in] extended If the given address is an extended MAC address or a short MAC address. - * @param[in] data_type Type of data to be removed. Refer to the @ref nrf_802154_ack_data_t type. - * - * @retval True Address removed from the list. - * @retval False Address not found in the list. - */ -bool nrf_802154_ack_data_clear(const uint8_t * p_addr, bool extended, uint8_t data_type); - -/** - * @brief Enables or disables setting a pending bit in automatically transmitted ACK frames. - * - * @note Setting a pending bit in automatically transmitted ACK frames is enabled by default. - * - * The radio driver automatically sends ACK frames in response frames destined for this node with - * the ACK Request bit set. The pending bit in the ACK frame can be set or cleared regarding data - * in the indirect queue destined for the ACK destination. - * - * If setting a pending bit in ACK frames is disabled, the pending bit in every ACK frame is set. - * If setting a pending bit in ACK frames is enabled, the radio driver checks if there is data - * in the indirect queue destined for the ACK destination. If there is no such data, - * the pending bit is cleared. - * - * @note Due to the ISR latency, the radio driver might not be able to verify if there is data - * in the indirect queue before ACK is sent. In this case, the pending bit is set. - * - * @param[in] enabled If setting a pending bit in ACK frames is enabled. - */ -void nrf_802154_auto_pending_bit_set(bool enabled); - -/** - * @brief Adds address of a peer node for which there is pending data in the buffer. - * - * @note This function makes a copy of the given address. - * - * @param[in] p_addr Array of bytes containing the address of the node (little-endian). - * @param[in] extended If the given address is an extended MAC address or a short MAC address. - * - * @retval True The address is successfully added to the list. - * @retval False Not enough memory to store the address in the list. - */ -bool nrf_802154_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended); - -/** - * @brief Removes address of a peer node for which there is no more pending data in the buffer. - * - * @param[in] p_addr Array of bytes containing the address of the node (little-endian). - * @param[in] extended If the given address is an extended MAC address or a short MAC address. - * - * @retval True The address is successfully removed from the list. - * @retval False No such address in the list. - */ -bool nrf_802154_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended); - -/** - * @brief Removes all addresses of a given type from the pending bit list. - * - * @param[in] extended If the function is to remove all extended MAC addresses or all short - * addresses. - */ -void nrf_802154_pending_bit_for_addr_reset(bool extended); - -/** - * @} - * @defgroup nrf_802154_cca CCA configuration management - * @{ - */ - -/** - * @brief Configures the radio CCA mode and threshold. - * - * @param[in] p_cca_cfg Pointer to the CCA configuration structure. Only fields relevant to - * the selected mode are updated. - */ -void nrf_802154_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cca_cfg); - -/** - * @brief Gets the current radio CCA configuration. - * - * @param[out] p_cca_cfg Pointer to the structure for the current CCA configuration. - */ -void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg); - -/** - * @} - * @defgroup nrf_802154_csma CSMA-CA procedure - * @{ - */ -#if NRF_802154_CSMA_CA_ENABLED -#if NRF_802154_USE_RAW_API - -/** - * @brief Performs the CSMA-CA procedure and transmits a frame in case of success. - * - * The end of the CSMA-CA procedure is notified by @ref nrf_802154_transmitted_raw or - * @ref nrf_802154_transmit_failed. - * - * @note The driver may be configured to automatically time out waiting for an ACK frame depending - * on @ref NRF_802154_ACK_TIMEOUT_ENABLED. If the automatic ACK timeout is disabled, - * the CSMA-CA procedure does not time out waiting for an ACK frame if a frame - * with the ACK request bit set was transmitted. The MAC layer is expected to manage the timer - * to time out waiting for the ACK frame. This timer can be started - * by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected - * to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame. - * - * @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw. - */ -void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data); - -#else // NRF_802154_USE_RAW_API - -/** - * @brief Performs the CSMA-CA procedure and transmits a frame in case of success. - * - * The end of the CSMA-CA procedure is notified by @ref nrf_802154_transmitted or - * @ref nrf_802154_transmit_failed. - * - * @note The driver may be configured to automatically time out waiting for an ACK frame depending - * on @ref NRF_802154_ACK_TIMEOUT_ENABLED. If the automatic ACK timeout is disabled, - * the CSMA-CA procedure does not time out waiting for an ACK frame if a frame - * with the ACK request bit set was transmitted. The MAC layer is expected to manage the timer - * to time out waiting for the ACK frame. This timer can be started - * by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected - * to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame. - * - * @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit. - * @param[in] length Length of the given frame. See also @ref nrf_802154_transmit. - */ -void nrf_802154_transmit_csma_ca(const uint8_t * p_data, uint8_t length); - -#endif // NRF_802154_USE_RAW_API -#endif // NRF_802154_CSMA_CA_ENABLED - -/** - * @} - * @defgroup nrf_802154_timeout ACK timeout procedure - * @{ - */ -#if NRF_802154_ACK_TIMEOUT_ENABLED - -/** - * @brief Sets timeout for the ACK timeout feature. - * - * A timeout is notified by @ref nrf_802154_transmit_failed. - * - * @param[in] time Timeout in microseconds (us). - * A default value is defined in nrf_802154_config.h. - */ -void nrf_802154_ack_timeout_set(uint32_t time); - -#endif // NRF_802154_ACK_TIMEOUT_ENABLED - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* NRF_802154_H_ */ - -/** @} */ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @defgroup nrf_802154 802.15.4 radio driver + * @{ + * + */ + +#ifndef NRF_802154_H_ +#define NRF_802154_H_ + +#include +#include + +#include "nrf_802154_config.h" +#include "nrf_802154_types.h" + +#if ENABLE_FEM +#include "fem/nrf_fem_control_api.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Timestamp value indicating that the timestamp is inaccurate. + */ +#define NRF_802154_NO_TIMESTAMP 0 + +/** + * @brief Initializes the 802.15.4 driver. + * + * This function initializes the RADIO peripheral in the @ref RADIO_STATE_SLEEP state. + * + * @note This function is to be called once, before any other functions from this module. + */ +void nrf_802154_init(void); + +/** + * @brief Deinitializes the 802.15.4 driver. + * + * This function deinitializes the RADIO peripheral and resets it to the default state. + */ +void nrf_802154_deinit(void); + +#if !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING +/** + * @brief Handles the interrupt request from the RADIO peripheral. + * + * @note If NRF_802154_INTERNAL_RADIO_IRQ_HANDLING is enabled, the driver internally handles the + * RADIO IRQ, and this function must not be called. + * + * This function is intended for use in an operating system environment, where the OS handles IRQ + * and indirectly passes it to the driver, or with a RAAL implementation that indirectly passes + * radio IRQ to the driver (that is, SoftDevice). + */ +void nrf_802154_radio_irq_handler(void); +#endif // !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING + +/** + * @brief Sets the channel on which the radio is to operate. + * + * @param[in] channel Channel number (11-26). + */ +void nrf_802154_channel_set(uint8_t channel); + +/** + * @brief Gets the channel on which the radio operates. + * + * @returns Channel number (11-26). + */ +uint8_t nrf_802154_channel_get(void); + +/** + * @brief Sets the transmit power. + * + * @note The driver recalculates the requested value to the nearest value accepted by the hardware. + * The calculation result is rounded up. + * + * @param[in] power Transmit power in dBm. + */ +void nrf_802154_tx_power_set(int8_t power); + +/** + * @brief Gets the currently set transmit power. + * + * @returns Currently used transmit power, in dBm. + */ +int8_t nrf_802154_tx_power_get(void); + +/** + * @defgroup nrf_802154_frontend Frontend Module management + * @{ + */ + +#if ENABLE_FEM + +/** Structure that contains the run-time configuration of the Frontend Module. */ +typedef nrf_fem_control_cfg_t nrf_802154_fem_control_cfg_t; + +/** Macro with the default configuration of the Frontend Module. */ +#define NRF_802154_FEM_DEFAULT_SETTINGS \ + ((nrf_802154_fem_control_cfg_t) { \ + .pa_cfg = { \ + .enable = 1, \ + .active_high = 1, \ + .gpio_pin = NRF_FEM_CONTROL_DEFAULT_PA_PIN, \ + }, \ + .lna_cfg = { \ + .enable = 1, \ + .active_high = 1, \ + .gpio_pin = NRF_FEM_CONTROL_DEFAULT_LNA_PIN, \ + }, \ + .pa_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL, \ + .lna_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL, \ + .ppi_ch_id_set = NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL, \ + .ppi_ch_id_clr = NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL, \ + }) + +/** + * @brief Sets the PA & LNA GPIO toggle configuration. + * + * @note This function must not be called when the radio is in use. + * + * @param[in] p_cfg Pointer to the PA & LNA GPIO toggle configuration. + * + */ +void nrf_802154_fem_control_cfg_set(const nrf_802154_fem_control_cfg_t * p_cfg); + +/** + * @brief Get the PA & LNA GPIO toggle configuration. + * + * @param[out] p_cfg Pointer to the structure for the PA & LNA GPIO toggle configuration. + * + */ +void nrf_802154_fem_control_cfg_get(nrf_802154_fem_control_cfg_t * p_cfg); + +#endif // ENABLE_FEM + +/** + * @} + * @defgroup nrf_802154_addresses Setting addresses and PAN ID of the device + * @{ + */ + +/** + * @brief Sets the PAN ID used by the device. + * + * @param[in] p_pan_id Pointer to the PAN ID (2 bytes, little-endian). + * + * This function makes a copy of the PAN ID. + */ +void nrf_802154_pan_id_set(const uint8_t * p_pan_id); + +/** + * @brief Sets the extended address of the device. + * + * @param[in] p_extended_address Pointer to the extended address (8 bytes, little-endian). + * + * This function makes a copy of the address. + */ +void nrf_802154_extended_address_set(const uint8_t * p_extended_address); + +/** + * @brief Sets the short address of the device. + * + * @param[in] p_short_address Pointer to the short address (2 bytes, little-endian). + * + * This function makes a copy of the address. + */ +void nrf_802154_short_address_set(const uint8_t * p_short_address); + +/** + * @} + * @defgroup nrf_802154_data Functions to calculate data given by the driver + * @{ + */ + +/** + * @brief Converts the energy level received during the energy detection procedure to a dBm value. + * + * @param[in] energy_level Energy level passed by @ref nrf_802154_energy_detected. + * + * @return Result of the energy detection procedure in dBm. + */ +int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level); + +/** + * @brief Converts a given dBm level to a CCA energy detection threshold value. + * + * @param[in] dbm Energy level in dBm used to calculate the CCAEDTHRES value. + * + * @return Energy level value corresponding to the given dBm level that is to be written to + * the CCACTRL register. + */ +uint8_t nrf_802154_ccaedthres_from_dbm_calculate(int8_t dbm); + +/** + * @brief Calculates the timestamp of the first symbol of the preamble in a received frame. + * + * @param[in] end_timestamp Timestamp of the end of the last symbol in the frame, + * in microseconds. + * @param[in] psdu_length Number of bytes in the frame PSDU. + * + * @return Timestamp of the beginning of the first preamble symbol of a given frame, + * in microseconds. + */ +uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t psdu_length); + +/** + * @} + * @defgroup nrf_802154_transitions Functions to request FSM transitions and check current state + * @{ + */ + +/** + * @brief Gets the current state of the radio. + */ +nrf_802154_state_t nrf_802154_state_get(void); + +/** + * @brief Changes the radio state to the @ref RADIO_STATE_SLEEP state. + * + * The sleep state is the lowest power state. In this state, the radio cannot transmit or receive + * frames. It is the only state in which the driver releases the high-frequency clock and does not + * request timeslots from a radio arbiter. + * + * @note If another module requests it, the high-frequency clock may be enabled even in the radio + * sleep state. + * + * @retval true The radio changes its state to the low power mode. + * @retval false The driver could not schedule changing state. + */ +bool nrf_802154_sleep(void); + +/** + * @brief Changes the radio state to the @ref RADIO_STATE_SLEEP state if the radio is idle. + * + * The sleep state is the lowest power state. In this state, the radio cannot transmit or receive + * frames. It is the only state in which the driver releases the high-frequency clock and does not + * request timeslots from a radio arbiter. + * + * @note If another module requests it, the high-frequency clock may be enabled even in the radio + * sleep state. + * + * @retval NRF_802154_SLEEP_ERROR_NONE The radio changes its state to the low power mode. + * @retval NRF_802154_SLEEP_ERROR_BUSY The driver could not schedule changing state. + */ +nrf_802154_sleep_error_t nrf_802154_sleep_if_idle(void); + +/** + * @brief Changes the radio state to @ref RADIO_STATE_RX. + * + * In the receive state, the radio receives frames and may automatically send ACK frames when + * appropriate. The received frame is reported to the higher layer by a call to + * @ref nrf_802154_received. + * + * @retval true The radio enters the receive state. + * @retval false The driver could not enter the receive state. + */ +bool nrf_802154_receive(void); + +/** + * @brief Requests reception at the specified time. + * + * This function works as a delayed version of @ref nrf_802154_receive. It is asynchronous. + * It queues the delayed reception using the Radio Scheduler module. + * If the delayed reception cannot be performed (@ref nrf_802154_receive_at would return false) + * or the requested reception timeslot is denied, @ref nrf_drv_radio802154_receive_failed is called + * with the @ref NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED argument. + * + * If the requested reception time is in the past, the function returns false and does not + * schedule reception. + * + * A scheduled reception can be cancelled by a call to @ref nrf_802154_receive_at_cancel. + * + * @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler, + * in microseconds (us). + * @param[in] dt Delta of delay time from @p t0, in microseconds (us). + * @param[in] timeout Reception timeout (counted from @p t0 + @p dt), in microseconds (us). + * @param[in] channel Radio channel on which the frame is to be received. + * + * @retval true The reception procedure was scheduled. + * @retval false The driver could not schedule the reception procedure. + */ +bool nrf_802154_receive_at(uint32_t t0, + uint32_t dt, + uint32_t timeout, + uint8_t channel); + +/** + * @brief Cancels a delayed reception scheduled by a call to @ref nrf_802154_receive_at. + * + * If the receive window has been scheduled but has not started yet, this function prevents + * entering the receive window. If the receive window has been scheduled and has already started, + * the radio remains in the receive state, but a window timeout will not be reported. + * + * @retval true The delayed reception was scheduled and successfully cancelled. + * @retval false No delayed reception was scheduled. + */ +bool nrf_802154_receive_at_cancel(void); + +#if NRF_802154_USE_RAW_API +/** + * @brief Changes the radio state to @ref RADIO_STATE_TX. + * + * @note If the CPU is halted or interrupted while this function is executed, + * @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed can be called before this + * function returns a result. + * + * @note This function is implemented in zero-copy fashion. It passes the given buffer pointer to + * the RADIO peripheral. + * + * In the transmit state, the radio transmits a given frame. If requested, it waits for + * an ACK frame. Depending on @ref NRF_802154_ACK_TIMEOUT_ENABLED, the radio driver automatically + * stops waiting for an ACK frame or waits indefinitely for an ACK frame. If it is configured to + * wait, the MAC layer is responsible for calling @ref nrf_802154_receive or + * @ref nrf_802154_sleep after the ACK timeout. + * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted + * or @ref nrf_802154_transmit_failed. + * + * @verbatim + * p_data + * v + * +-----+-----------------------------------------------------------+------------+ + * | PHR | MAC header and payload | FCS | + * +-----+-----------------------------------------------------------+------------+ + * | | + * | <---------------------------- PHR -----------------------------------> | + * @endverbatim + * + * @param[in] p_data Pointer to the array with data to transmit. The first byte must contain frame + * length (including PHR and FCS). The following bytes contain data. The CRC is + * computed automatically by the radio hardware. Therefore, the FCS field can + * contain any bytes. + * @param[in] cca If the driver is to perform a CCA procedure before transmission. + * + * @retval true The transmission procedure was scheduled. + * @retval false The driver could not schedule the transmission procedure. + */ +bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Changes the radio state to transmit. + * + * @note If the CPU is halted or interrupted while this function is executed, + * @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed must be called before this + * function returns a result. + * + * @note This function copies the given buffer. It maintains an internal buffer, which is used to + * make a frame copy. To prevent unnecessary memory consumption and to perform zero-copy + * transmission, use @ref nrf_802154_transmit_raw instead. + * + * In the transmit state, the radio transmits a given frame. If requested, it waits for + * an ACK frame. Depending on @ref NRF_802154_ACK_TIMEOUT_ENABLED, the radio driver automatically + * stops waiting for an ACK frame or waits indefinitely for an ACK frame. If it is configured to + * wait, the MAC layer is responsible for calling @ref nrf_802154_receive or + * @ref nrf_802154_sleep after the ACK timeout. + * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted + * or @ref nrf_802154_transmit_failed. + * + * @verbatim + * p_data + * v + * +-----+-----------------------------------------------------------+------------+ + * | PHR | MAC header and payload | FCS | + * +-----+-----------------------------------------------------------+------------+ + * | | + * | <------------------ length -----------------------------> | + * @endverbatim + * + * @param[in] p_data Pointer to the array with the payload of data to transmit. The array should + * exclude PHR or FCS fields of the 802.15.4 frame. + * @param[in] length Length of the given frame. This value must exclude PHR and FCS fields from + * the given frame (exact size of buffer pointed to by @p p_data). + * @param[in] cca If the driver is to perform a CCA procedure before transmission. + * + * @retval true The transmission procedure was scheduled. + * @retval false The driver could not schedule the transmission procedure. + */ +bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca); + +#endif // NRF_802154_USE_RAW_API + +/** + * @brief Requests transmission at the specified time. + * + * @note This function is implemented in a zero-copy fashion. It passes the given buffer pointer to + * the RADIO peripheral. + * + * This function works as a delayed version of @ref nrf_802154_transmit_raw. It is asynchronous. + * It queues the delayed transmission using the Radio Scheduler module and performs it + * at the specified time. + * + * If the delayed transmission is successfully performed, @ref nrf_802154_transmitted is called. + * If the delayed transmission cannot be performed (@ref nrf_802154_transmit_raw would return false) + * or the requested transmission timeslot is denied, @ref nrf_802154_transmit_failed with the + * @ref NRF_802154_TX_ERROR_TIMESLOT_DENIED argument is called. + * + * This function is designed to transmit the first symbol of SHR at the given time. + * + * If the requested transmission time is in the past, the function returns false and does not + * schedule transmission. + * + * A successfully scheduled transmission can be cancelled by a call + * to @ref nrf_802154_transmit_at_cancel. + * + * @param[in] p_data Pointer to the array with data to transmit. The first byte must contain + * the frame length (including PHR and FCS). The following bytes contain data. + * The CRC is computed automatically by the radio hardware. Therefore, the FCS + * field can contain any bytes. + * @param[in] cca If the driver is to perform a CCA procedure before transmission. + * @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler, + * in microseconds (us). + * @param[in] dt Delta of delay time from @p t0, in microseconds (us). + * @param[in] channel Radio channel on which the frame is to be transmitted. + * + * @retval true The transmission procedure was scheduled. + * @retval false The driver could not schedule the transmission procedure. + */ +bool nrf_802154_transmit_raw_at(const uint8_t * p_data, + bool cca, + uint32_t t0, + uint32_t dt, + uint8_t channel); + +/** + * @brief Cancels a delayed transmission scheduled by a call to @ref nrf_802154_transmit_raw_at. + * + * If a delayed transmission has been scheduled but the transmission has not been started yet, + * a call to this function prevents the transmission. If the transmission is ongoing, + * it will not be aborted. + * + * If a delayed transmission has not been scheduled (or has already finished), this function does + * not change state and returns false. + * + * @retval true The delayed transmission was scheduled and successfully cancelled. + * @retval false No delayed transmission was scheduled. + */ +bool nrf_802154_transmit_at_cancel(void); + +/** + * @brief Changes the radio state to energy detection. + * + * In the energy detection state, the radio detects the maximum energy for a given time. + * The result of the detection is reported to the higher layer by @ref nrf_802154_energy_detected. + * + * @note @ref nrf_802154_energy_detected can be called before this function returns a result. + * @note Performing the energy detection procedure can take longer than requested in @p time_us. + * The procedure is performed only during the timeslots granted by a radio arbiter. + * It can be interrupted by other protocols using the radio hardware. If the procedure is + * interrupted, it is automatically continued and the sum of time periods during which the + * procedure is carried out is not less than the requested @p time_us. + * + * @param[in] time_us Duration of energy detection procedure. The given value is rounded up to + * multiplication of 8 symbols (128 us). + * + * @retval true The energy detection procedure was scheduled. + * @retval false The driver could not schedule the energy detection procedure. + */ +bool nrf_802154_energy_detection(uint32_t time_us); + +/** + * @brief Changes the radio state to @ref RADIO_STATE_CCA. + * + * @note @ref nrf_802154_cca_done can be called before this function returns a result. + * + * In the CCA state, the radio verifies if the channel is clear. The result of the verification is + * reported to the higher layer by @ref nrf_802154_cca_done. + * + * @retval true The CCA procedure was scheduled. + * @retval false The driver could not schedule the CCA procedure. + */ +bool nrf_802154_cca(void); + +/** + * @brief Changes the radio state to continuous carrier. + * + * @note When the radio is emitting continuous carrier signals, it blocks all transmissions on the + * selected channel. This function is to be called only during radio tests. Do not + * use it during normal device operation. + * + * @retval true The continuous carrier procedure was scheduled. + * @retval false The driver could not schedule the continuous carrier procedure. + */ +bool nrf_802154_continuous_carrier(void); + +/** + * @} + * @defgroup nrf_802154_calls Calls to higher layer + * @{ + */ + +/** + * @brief Notifies about the start of the ACK frame transmission. + * + * @note This function must be very short to prevent dropping frames by the driver. + * + * @param[in] p_data Pointer to a buffer with PHR and PSDU of the ACK frame. + */ +extern void nrf_802154_tx_ack_started(const uint8_t * p_data); + +#if NRF_802154_USE_RAW_API + +/** + * @brief Notifies that a frame was received. + * + * @note The buffer pointed to by @p p_data is not modified by the radio driver (and cannot be used + * to receive a frame) until @ref nrf_802154_buffer_free_raw is called. + * @note The buffer pointed to by @p p_data may be modified by the function handler (and other + * modules) until @ref nrf_802154_buffer_free_raw is called. + * + * @verbatim + * p_data + * v + * +-----+-----------------------------------------------------------+------------+ + * | PHR | MAC Header and payload | FCS | + * +-----+-----------------------------------------------------------+------------+ + * | | + * | <---------------------------- PHR -----------------------------------> | + * @endverbatim + * + * @param[in] p_data Pointer to a buffer that contains PHR and PSDU of the received frame. + * The first byte in the buffer is the length of the frame (PHR). The following + * bytes contain the frame itself (PSDU). The length byte (PHR) includes FCS. + * FCS is already verified by the hardware and may be modified by the hardware. + * @param[in] power RSSI of the received frame. + * @param[in] lqi LQI of the received frame. + */ +extern void nrf_802154_received_raw(uint8_t * p_data, int8_t power, uint8_t lqi); + +/** + * @brief Notifies that a frame was received at a given time. + * + * This function works like @ref nrf_802154_received_raw and adds a timestamp to the parameter + * list. + * + * @note The received frame usually contains a timestamp. However, due to a race condition, + * the timestamp may be invalid. This erroneous situation is indicated by + * the @ref NRF_802154_NO_TIMESTAMP value of the @p time parameter. + * + * @param[in] p_data Pointer to a buffer that contains PHR and PSDU of the received frame. + * The first byte in the buffer is the length of the frame (PHR). The following + * bytes contain the frame itself (PSDU). The length byte (PHR) includes FCS. + * FCS is already verified by the hardware and may be modified by the hardware. + * @param[in] power RSSI of the received frame. + * @param[in] lqi LQI of the received frame. + * @param[in] time Timestamp taken when the last symbol of the frame was received, in + * microseconds (us), or @ref NRF_802154_NO_TIMESTAMP if the timestamp + * is invalid. + */ +extern void nrf_802154_received_timestamp_raw(uint8_t * p_data, + int8_t power, + uint8_t lqi, + uint32_t time); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Notifies that a frame was received. + * + * @note The buffer pointed to by @p p_data is not modified by the radio driver (and cannot + * be used to receive a frame) until @ref nrf_802154_buffer_free is called. + * @note The buffer pointed to by @p p_data can be modified by the function handler (and other + * modules) until @ref nrf_802154_buffer_free is called. + * + * @verbatim + * p_data + * v + * +-----+-----------------------------------------------------------+------------+ + * | PHR | MAC Header and payload | FCS | + * +-----+-----------------------------------------------------------+------------+ + * | | + * | <------------------ length -----------------------------> | + * @endverbatim + * + * @param[in] p_data Pointer to a buffer that contains only the payload of the received frame + * (PSDU without FCS). + * @param[in] length Length of the received payload. + * @param[in] power RSSI of the received frame. + * @param[in] lqi LQI of the received frame. + */ +extern void nrf_802154_received(uint8_t * p_data, uint8_t length, int8_t power, uint8_t lqi); + +/** + * @brief Notifies that a frame was received at a given time. + * + * This function works like @ref nrf_802154_received and adds a timestamp to the parameter list. + * + * @note The received frame usually contains a timestamp. However, due to a race condition, + * the timestamp may be invalid. This erroneous situation is indicated by + * the @ref NRF_802154_NO_TIMESTAMP value of the @p time parameter. + * + * @param[in] p_data Pointer to a buffer that contains only the payload of the received frame + * (PSDU without FCS). + * @param[in] length Length of the received payload. + * @param[in] power RSSI of the received frame. + * @param[in] lqi LQI of the received frame. + * @param[in] time Timestamp taken when the last symbol of the frame was received, + * in microseconds (us), or @ref NRF_802154_NO_TIMESTAMP if the timestamp + * is invalid. + */ +extern void nrf_802154_received_timestamp(uint8_t * p_data, + uint8_t length, + int8_t power, + uint8_t lqi, + uint32_t time); + +#endif // !NRF_802154_USE_RAW_API + +/** + * @brief Notifies that the reception of a frame failed. + * + * @param[in] error Error code that indicates the reason of the failure. + */ +extern void nrf_802154_receive_failed(nrf_802154_rx_error_t error); + +/** + * @brief Notifies that transmitting a frame has started. + * + * @note Usually, @ref nrf_802154_transmitted is called shortly after this function. + * However, if the transmit procedure is interrupted, it might happen that + * @ref nrf_802154_transmitted is not called. + * @note This function should be very short to prevent dropping frames by the driver. + * + * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame being + * transmitted. + */ +extern void nrf_802154_tx_started(const uint8_t * p_frame); + +#if NRF_802154_USE_RAW_API + +/** + * @brief Notifies that a frame was transmitted. + * + * @note If ACK was requested for the transmitted frame, this function is called after a proper ACK + * is received. If ACK was not requested, this function is called just after transmission has + * ended. + * @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot be used + * to receive a frame) until @ref nrf_802154_buffer_free_raw is called. + * @note The buffer pointed to by @p p_ack may be modified by the function handler (and other + * modules) until @ref nrf_802154_buffer_free_raw is called. + * + * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame. + * @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of the received ACK. + * The first byte in the buffer is the length of the frame (PHR). The following + * bytes contain the ACK frame itself (PSDU). The length byte (PHR) includes + * FCS. FCS is already verified by the hardware and may be modified by the + * hardware. If ACK was not requested, @p p_ack is set to NULL. + * @param[in] power RSSI of the received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of the received frame or 0 if ACK was not requested. + */ +extern void nrf_802154_transmitted_raw(const uint8_t * p_frame, + uint8_t * p_ack, + int8_t power, + uint8_t lqi); + +/** + * @brief Notifies that a frame was transmitted. + * + * This function works like @ref nrf_802154_transmitted_raw and adds a timestamp to the parameter + * list. + * + * @note @p timestamp may be inaccurate due to software latency (IRQ handling). + * @note @p timestamp granularity depends on the granularity of the timer driver in the + * platform/timer directory. + * @note Including a timestamp for received frames uses resources like CPU time and memory. If the + * timestamp is not required, use @ref nrf_802154_received instead. + * + * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame. + * @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of the received ACK. + * The first byte in the buffer is the length of the frame (PHR). The following + * bytes contain the ACK frame itself (PSDU). The length byte (PHR) includes + * FCS. FCS is already verified by the hardware and may be modified by the + * hardware. If ACK was not requested, @p p_ack is set to NULL. + * @param[in] power RSSI of the received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of the received frame or 0 if ACK was not requested. + * @param[in] time Timestamp taken when the last symbol of ACK is received or 0 if ACK was not + * requested. + */ +extern void nrf_802154_transmitted_timestamp_raw(const uint8_t * p_frame, + uint8_t * p_ack, + int8_t power, + uint8_t lqi, + uint32_t time); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Notifies that a frame was transmitted. + * + * @note If ACK was requested for the transmitted frame, this function is called after a proper ACK + * is received. If ACK was not requested, this function is called just after transmission has + * ended. + * @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot + * be used to receive a frame) until @ref nrf_802154_buffer_free is + * called. + * @note The buffer pointed to by @p p_ack may be modified by the function handler (and other + * modules) until @ref nrf_802154_buffer_free is called. + * @note The next higher layer must handle either @ref nrf_802154_transmitted or + * @ref nrf_802154_transmitted_raw. It should not handle both functions. + * + * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame. + * @param[in] p_ack Pointer to a buffer that contains only the received ACK payload (PSDU + * excluding FCS). + * If ACK was not requested, @p p_ack is set to NULL. + * @param[in] length Length of the received ACK payload or 0 if ACK was not requested. + * @param[in] power RSSI of the received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of the received frame or 0 if ACK was not requested. + */ +extern void nrf_802154_transmitted(const uint8_t * p_frame, + uint8_t * p_ack, + uint8_t length, + int8_t power, + uint8_t lqi); + +/** + * @brief Notifies that a frame was transmitted. + * + * This function works like @ref nrf_802154_transmitted and adds a timestamp to the parameter + * list. + * + * @note @p timestamp may be inaccurate due to software latency (IRQ handling). + * @note @p timestamp granularity depends on the granularity of the timer driver + * in the platform/timer directory. + * @note Including a timestamp for received frames uses resources like CPU time and memory. If the + * timestamp is not required, use @ref nrf_802154_received instead. + * + * @param[in] p_frame Pointer to the buffer containing PHR and PSDU of the transmitted frame. + * @param[in] p_ack Pointer to the buffer containing only the received ACK payload (PSDU + * excluding FCS). + * If ACK was not requested, @p p_ack is set to NULL. + * @param[in] length Length of the received ACK payload. + * @param[in] power RSSI of the received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of the received frame or 0 if ACK was not requested. + * @param[in] time Timestamp taken when the last symbol of ACK is received or 0 if ACK was not + * requested. + */ +extern void nrf_802154_transmitted_timestamp(const uint8_t * p_frame, + uint8_t * p_ack, + uint8_t length, + int8_t power, + uint8_t lqi, + uint32_t time); + +#endif // !NRF_802154_USE_RAW_API + +/** + * @brief Notifies that a frame was not transmitted due to a busy channel. + * + * This function is called if the transmission procedure fails. + * + * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that was not + * transmitted. + * @param[in] error Reason of the failure. + */ +extern void nrf_802154_transmit_failed(const uint8_t * p_frame, + nrf_802154_tx_error_t error); + +/** + * @brief Notifies that the energy detection procedure finished. + * + * @note This function passes the EnergyLevel defined in the 802.15.4-2006 specification: + * 0x00 - 0xff, proportionally to the detected energy level (dBm above receiver sensitivity). + * To calculate the result in dBm, use @ref nrf_802154_dbm_from_energy_level_calculate. + * + * @param[in] result Maximum energy detected during the energy detection procedure. + */ +extern void nrf_802154_energy_detected(uint8_t result); + +/** + * @brief Notifies that the energy detection procedure failed. + * + * @param[in] error Reason of the failure. + */ +extern void nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error); + +/** + * @brief Notifies that the CCA procedure has finished. + * + * @param[in] channel_free Indication if the channel is free. + */ +extern void nrf_802154_cca_done(bool channel_free); + +/** + * @brief Notifies that the CCA procedure failed. + * + * @param[in] error Reason of the failure. + */ +extern void nrf_802154_cca_failed(nrf_802154_cca_error_t error); + +/** + * @} + * @defgroup nrf_802154_memman Driver memory management + * @{ + */ + +#if NRF_802154_USE_RAW_API + +/** + * @brief Notifies the driver that the buffer containing the received frame is not used anymore. + * + * @note The buffer pointed to by @p p_data may be modified by this function. + * @note This function can be safely called only from the main context. To free the buffer from + * a callback or the IRQ context, use @ref nrf_802154_buffer_free_immediately_raw. + * + * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed + * by the higher layer. + */ +void nrf_802154_buffer_free_raw(uint8_t * p_data); + +/** + * @brief Notifies the driver that the buffer containing the received frame is not used anymore. + * + * @note The buffer pointed to by @p p_data may be modified by this function. + * @note This function can be safely called from any context. If the driver is busy processing + * a request called from a context with lower priority, this function returns false and + * the caller should free the buffer later. + * + * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed + * by the higher layer. + * + * @retval true Buffer was freed successfully. + * @retval false Buffer cannot be freed right now due to ongoing operation. + */ +bool nrf_802154_buffer_free_immediately_raw(uint8_t * p_data); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Notifies the driver that the buffer containing the received frame is not used anymore. + * + * @note The buffer pointed to by @p p_data may be modified by this function. + * @note This function can be safely called only from the main context. To free the buffer from + * a callback or IRQ context, use @ref nrf_802154_buffer_free_immediately. + * + * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed + * by the higher layer. + */ +void nrf_802154_buffer_free(uint8_t * p_data); + +/** + * @brief Notifies the driver that the buffer containing the received frame is not used anymore. + * + * @note The buffer pointed to by @p p_data may be modified by this function. + * @note This function can be safely called from any context. If the driver is busy processing + * a request called from a context with lower priority, this function returns false and + * the caller should free the buffer later. + * + * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed + * by the higher layer. + * + * @retval true Buffer was freed successfully. + * @retval false Buffer cannot be freed right now due to ongoing operation. + */ +bool nrf_802154_buffer_free_immediately(uint8_t * p_data); + +#endif // NRF_802154_USE_RAW_API + +/** + * @} + * @defgroup nrf_802154_rssi RSSI measurement function + * @{ + */ + +/** + * @brief Begins the RSSI measurement. + * + * @note This function is to be called in the @ref RADIO_STATE_RX state. + * + * The result will be available after the measurement process is finished. The result can be read by + * @ref nrf_802154_rssi_last_get. Check the documentation of the RADIO peripheral to check + * the duration of the RSSI measurement procedure. + * + * @retval true RSSI measurement successfully requested. + * @retval false RSSI measurement cannot be scheduled at the moment. + */ +bool nrf_802154_rssi_measure_begin(void); + +/** + * @brief Gets the result of the last RSSI measurement. + * + * @returns RSSI measurement result, in dBm. + */ +int8_t nrf_802154_rssi_last_get(void); + +/** + * @} + * @defgroup nrf_802154_prom Promiscuous mode + * @{ + */ + +/** + * @brief Enables or disables the promiscuous radio mode. + * + * @note The promiscuous mode is disabled by default. + * + * In the promiscuous mode, the driver notifies the higher layer that it received any frame + * (regardless frame type or destination address). + * In normal mode (not promiscuous), the higher layer is not notified about ACK frames and frames + * with unknown type. Also, frames with a destination address not matching the device address are + * ignored. + * + * @param[in] enabled If the promiscuous mode is to be enabled. + */ +void nrf_802154_promiscuous_set(bool enabled); + +/** + * @brief Checks if the radio is in the promiscuous mode. + * + * @retval True Radio is in the promiscuous mode. + * @retval False Radio is not in the promiscuous mode. + */ +bool nrf_802154_promiscuous_get(void); + +/** + * @} + * @defgroup nrf_802154_autoack Auto ACK management + * @{ + */ + +/** + * @brief Enables or disables the automatic acknowledgments (auto ACK). + * + * @note The auto ACK is enabled by default. + * + * If the auto ACK is enabled, the driver prepares and sends ACK frames automatically + * aTurnaroundTime (192 us) after the proper frame is received. The driver prepares an ACK frame + * according to the data provided by @ref nrf_802154_ack_data_set. + * When the auto ACK is enabled, the driver notifies the next higher layer about the received frame + * after the ACK frame is transmitted. + * If the auto ACK is disabled, the driver does not transmit ACK frames. It notifies the next higher + * layer about the received frames when a frame is received. In this mode, the next higher layer is + * responsible for sending the ACK frame. ACK frames should be sent using @ref nrf_802154_transmit. + * + * @param[in] enabled If the auto ACK should be enabled. + */ +void nrf_802154_auto_ack_set(bool enabled); + +/** + * @brief Checks if the auto ACK is enabled. + * + * @retval True Auto ACK is enabled. + * @retval False Auto ACK is disabled. + */ +bool nrf_802154_auto_ack_get(void); + +/** + * @brief Configures the device as the PAN coordinator. + * + * @note That information is used for packet filtering. + * + * @param[in] enabled The radio is configured as the PAN coordinator. + */ +void nrf_802154_pan_coord_set(bool enabled); + +/** + * @brief Checks if the radio is configured as the PAN coordinator. + * + * @retval true The radio is configured as the PAN coordinator. + * @retval false The radio is not configured as the PAN coordinator. + */ +bool nrf_802154_pan_coord_get(void); + +/** + * @brief Adds the address of a peer node for which the provided ACK data is to be set. + * + * @param[in] p_addr Array of bytes containing the address of the node (little-endian). + * @param[in] extended If the given address is an extended MAC address or a short MAC address. + * @param[in] p_data Pointer to the buffer containing data to be set. + * @param[in] length Length of @p p_data. + * @param[in] data_type Type of data to be set. Refer to the @ref nrf_802154_ack_data_t type. + * + * @retval True Address successfully added to the list. + * @retval False Not enough memory to store this address in the list. + */ +bool nrf_802154_ack_data_set(const uint8_t * p_addr, + bool extended, + const void * p_data, + uint16_t length, + uint8_t data_type); + +/** + * @brief Removes the address of a peer node for which the ACK data is set. + * + * The ACK data that was previously set for the given address is automatically removed. + * + * @param[in] p_addr Array of bytes containing the address of the node (little-endian). + * @param[in] extended If the given address is an extended MAC address or a short MAC address. + * @param[in] data_type Type of data to be removed. Refer to the @ref nrf_802154_ack_data_t type. + * + * @retval True Address removed from the list. + * @retval False Address not found in the list. + */ +bool nrf_802154_ack_data_clear(const uint8_t * p_addr, bool extended, uint8_t data_type); + +/** + * @brief Enables or disables setting a pending bit in automatically transmitted ACK frames. + * + * @note Setting a pending bit in automatically transmitted ACK frames is enabled by default. + * + * The radio driver automatically sends ACK frames in response frames destined for this node with + * the ACK Request bit set. The pending bit in the ACK frame can be set or cleared regarding data + * in the indirect queue destined for the ACK destination. + * + * If setting a pending bit in ACK frames is disabled, the pending bit in every ACK frame is set. + * If setting a pending bit in ACK frames is enabled, the radio driver checks if there is data + * in the indirect queue destined for the ACK destination. If there is no such data, + * the pending bit is cleared. + * + * @note Due to the ISR latency, the radio driver might not be able to verify if there is data + * in the indirect queue before ACK is sent. In this case, the pending bit is set. + * + * @param[in] enabled If setting a pending bit in ACK frames is enabled. + */ +void nrf_802154_auto_pending_bit_set(bool enabled); + +/** + * @brief Adds address of a peer node for which there is pending data in the buffer. + * + * @note This function makes a copy of the given address. + * + * @param[in] p_addr Array of bytes containing the address of the node (little-endian). + * @param[in] extended If the given address is an extended MAC address or a short MAC address. + * + * @retval True The address is successfully added to the list. + * @retval False Not enough memory to store the address in the list. + */ +bool nrf_802154_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended); + +/** + * @brief Removes address of a peer node for which there is no more pending data in the buffer. + * + * @param[in] p_addr Array of bytes containing the address of the node (little-endian). + * @param[in] extended If the given address is an extended MAC address or a short MAC address. + * + * @retval True The address is successfully removed from the list. + * @retval False No such address in the list. + */ +bool nrf_802154_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended); + +/** + * @brief Removes all addresses of a given type from the pending bit list. + * + * @param[in] extended If the function is to remove all extended MAC addresses or all short + * addresses. + */ +void nrf_802154_pending_bit_for_addr_reset(bool extended); + +/** + * @} + * @defgroup nrf_802154_cca CCA configuration management + * @{ + */ + +/** + * @brief Configures the radio CCA mode and threshold. + * + * @param[in] p_cca_cfg Pointer to the CCA configuration structure. Only fields relevant to + * the selected mode are updated. + */ +void nrf_802154_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cca_cfg); + +/** + * @brief Gets the current radio CCA configuration. + * + * @param[out] p_cca_cfg Pointer to the structure for the current CCA configuration. + */ +void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg); + +/** + * @} + * @defgroup nrf_802154_csma CSMA-CA procedure + * @{ + */ +#if NRF_802154_CSMA_CA_ENABLED +#if NRF_802154_USE_RAW_API + +/** + * @brief Performs the CSMA-CA procedure and transmits a frame in case of success. + * + * The end of the CSMA-CA procedure is notified by @ref nrf_802154_transmitted_raw or + * @ref nrf_802154_transmit_failed. + * + * @note The driver may be configured to automatically time out waiting for an ACK frame depending + * on @ref NRF_802154_ACK_TIMEOUT_ENABLED. If the automatic ACK timeout is disabled, + * the CSMA-CA procedure does not time out waiting for an ACK frame if a frame + * with the ACK request bit set was transmitted. The MAC layer is expected to manage the timer + * to time out waiting for the ACK frame. This timer can be started + * by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected + * to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame. + * + * @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw. + */ +void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Performs the CSMA-CA procedure and transmits a frame in case of success. + * + * The end of the CSMA-CA procedure is notified by @ref nrf_802154_transmitted or + * @ref nrf_802154_transmit_failed. + * + * @note The driver may be configured to automatically time out waiting for an ACK frame depending + * on @ref NRF_802154_ACK_TIMEOUT_ENABLED. If the automatic ACK timeout is disabled, + * the CSMA-CA procedure does not time out waiting for an ACK frame if a frame + * with the ACK request bit set was transmitted. The MAC layer is expected to manage the timer + * to time out waiting for the ACK frame. This timer can be started + * by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected + * to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame. + * + * @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit. + * @param[in] length Length of the given frame. See also @ref nrf_802154_transmit. + */ +void nrf_802154_transmit_csma_ca(const uint8_t * p_data, uint8_t length); + +#endif // NRF_802154_USE_RAW_API +#endif // NRF_802154_CSMA_CA_ENABLED + +/** + * @} + * @defgroup nrf_802154_timeout ACK timeout procedure + * @{ + */ +#if NRF_802154_ACK_TIMEOUT_ENABLED + +/** + * @brief Sets timeout for the ACK timeout feature. + * + * A timeout is notified by @ref nrf_802154_transmit_failed. + * + * @param[in] time Timeout in microseconds (us). + * A default value is defined in nrf_802154_config.h. + */ +void nrf_802154_ack_timeout_set(uint32_t time); + +#endif // NRF_802154_ACK_TIMEOUT_ENABLED + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_802154_H_ */ + +/** @} */ diff --git a/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.h b/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.h index 6dc8832e9..d037fd37d 100644 --- a/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.h +++ b/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.h @@ -1,80 +1,80 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef NRF_DRV_SYSTICK_H__ -#define NRF_DRV_SYSTICK_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup nrf_drv_systick ARM(R) SysTick driver - legacy layer - * @{ - * @ingroup nrf_systick - * - * @brief Layer providing compatibility with the former API. - */ - -/** @brief Type definition for forwarding the new implementation. */ -typedef nrfx_systick_state_t nrf_drv_systick_state_t; - -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_systick_init nrfx_systick_init -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_systick_get nrfx_systick_get -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_systick_test nrfx_systick_test -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_systick_delay_ticks nrfx_systick_delay_ticks -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_systick_delay_us nrfx_systick_delay_us -/** @brief Macro for forwarding the new implementation. */ -#define nrf_drv_systick_delay_ms nrfx_systick_delay_ms - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif // NRF_DRV_SYSTICK_H__ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_SYSTICK_H__ +#define NRF_DRV_SYSTICK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_systick ARM(R) SysTick driver - legacy layer + * @{ + * @ingroup nrf_systick + * + * @brief Layer providing compatibility with the former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_systick_state_t nrf_drv_systick_state_t; + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_systick_init nrfx_systick_init +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_systick_get nrfx_systick_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_systick_test nrfx_systick_test +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_systick_delay_ticks nrfx_systick_delay_ticks +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_systick_delay_us nrfx_systick_delay_us +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_systick_delay_ms nrfx_systick_delay_ms + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_SYSTICK_H__ diff --git a/third_party/NordicSemiconductor/libraries/app_error/app_error.c b/third_party/NordicSemiconductor/libraries/app_error/app_error.c index d4069d597..97b2eed36 100644 --- a/third_party/NordicSemiconductor/libraries/app_error/app_error.c +++ b/third_party/NordicSemiconductor/libraries/app_error/app_error.c @@ -1,139 +1,139 @@ -/** - * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup app_error Common application error handler - * @{ - * @ingroup app_common - * - * @brief Common application error handler. - */ - -#include "nrf.h" -#include -#include "app_error.h" -#include "nordic_common.h" -#include "sdk_errors.h" - -/**@brief Function for error handling, which is called when an error has occurred. - * - * @warning This handler is an example only and does not fit a final product. You need to analyze - * how your product is supposed to react in case of error. - * - * @param[in] error_code Error code supplied to the handler. - * @param[in] line_num Line number where the handler is called. - * @param[in] p_file_name Pointer to the file name. - */ -void app_error_handler_bare(ret_code_t error_code) -{ - error_info_t error_info = - { - .line_num = 0, - .p_file_name = NULL, - .err_code = error_code, - }; - - app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); - - UNUSED_VARIABLE(error_info); -} - -/**@brief Function for error handling, which is called when an error has occurred. - * - * @param[in] error_code Error code supplied to the handler. - * @param[in] line_num Line number where the handler is called. - * @param[in] p_file_name Pointer to the file name. - */ -void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) -{ - UNUSED_VARIABLE(line_num); - UNUSED_VARIABLE(p_file_name); - - app_error_handler_bare(error_code); -} - -void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info) -{ - /* static error variables - in order to prevent removal by optimizers */ - static volatile struct - { - uint32_t fault_id; - uint32_t pc; - uint32_t error_info; - assert_info_t * p_assert_info; - error_info_t * p_error_info; - ret_code_t err_code; - uint32_t line_num; - const uint8_t * p_file_name; - } m_error_data = {0}; - - // The following variable helps Keil keep the call stack visible, in addition, it can be set to - // 0 in the debugger to continue executing code after the error check. - volatile bool loop = true; - UNUSED_VARIABLE(loop); - - m_error_data.fault_id = id; - m_error_data.pc = pc; - m_error_data.error_info = info; - - switch (id) - { - case NRF_FAULT_ID_SDK_ASSERT: - m_error_data.p_assert_info = (assert_info_t *)info; - m_error_data.line_num = m_error_data.p_assert_info->line_num; - m_error_data.p_file_name = m_error_data.p_assert_info->p_file_name; - break; - - case NRF_FAULT_ID_SDK_ERROR: - m_error_data.p_error_info = (error_info_t *)info; - m_error_data.err_code = m_error_data.p_error_info->err_code; - m_error_data.line_num = m_error_data.p_error_info->line_num; - m_error_data.p_file_name = m_error_data.p_error_info->p_file_name; - break; - } - - UNUSED_VARIABLE(m_error_data); - - // If printing is disrupted, remove the irq calls, or set the loop variable to 0 in the debugger. - __disable_irq(); - while (loop); - - __enable_irq(); -} +/** + * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler. + */ + +#include "nrf.h" +#include +#include "app_error.h" +#include "nordic_common.h" +#include "sdk_errors.h" + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @warning This handler is an example only and does not fit a final product. You need to analyze + * how your product is supposed to react in case of error. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ +void app_error_handler_bare(ret_code_t error_code) +{ + error_info_t error_info = + { + .line_num = 0, + .p_file_name = NULL, + .err_code = error_code, + }; + + app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); + + UNUSED_VARIABLE(error_info); +} + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ +void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + UNUSED_VARIABLE(line_num); + UNUSED_VARIABLE(p_file_name); + + app_error_handler_bare(error_code); +} + +void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info) +{ + /* static error variables - in order to prevent removal by optimizers */ + static volatile struct + { + uint32_t fault_id; + uint32_t pc; + uint32_t error_info; + assert_info_t * p_assert_info; + error_info_t * p_error_info; + ret_code_t err_code; + uint32_t line_num; + const uint8_t * p_file_name; + } m_error_data = {0}; + + // The following variable helps Keil keep the call stack visible, in addition, it can be set to + // 0 in the debugger to continue executing code after the error check. + volatile bool loop = true; + UNUSED_VARIABLE(loop); + + m_error_data.fault_id = id; + m_error_data.pc = pc; + m_error_data.error_info = info; + + switch (id) + { + case NRF_FAULT_ID_SDK_ASSERT: + m_error_data.p_assert_info = (assert_info_t *)info; + m_error_data.line_num = m_error_data.p_assert_info->line_num; + m_error_data.p_file_name = m_error_data.p_assert_info->p_file_name; + break; + + case NRF_FAULT_ID_SDK_ERROR: + m_error_data.p_error_info = (error_info_t *)info; + m_error_data.err_code = m_error_data.p_error_info->err_code; + m_error_data.line_num = m_error_data.p_error_info->line_num; + m_error_data.p_file_name = m_error_data.p_error_info->p_file_name; + break; + } + + UNUSED_VARIABLE(m_error_data); + + // If printing is disrupted, remove the irq calls, or set the loop variable to 0 in the debugger. + __disable_irq(); + while (loop); + + __enable_irq(); +} diff --git a/third_party/NordicSemiconductor/libraries/app_error/app_error.h b/third_party/NordicSemiconductor/libraries/app_error/app_error.h index b1498d2e1..ff8b2a890 100644 --- a/third_party/NordicSemiconductor/libraries/app_error/app_error.h +++ b/third_party/NordicSemiconductor/libraries/app_error/app_error.h @@ -1,192 +1,192 @@ -/** - * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup app_error Common application error handler - * @{ - * @ingroup app_common - * - * @brief Common application error handler and macros for utilizing a common error handler. - */ - -#ifndef APP_ERROR_H__ -#define APP_ERROR_H__ - - -#include -#include -#include -#include "nrf.h" -#include "sdk_errors.h" -#include "nordic_common.h" -#include "app_error_weak.h" -#ifdef ANT_STACK_SUPPORT_REQD -#include "ant_error.h" -#endif // ANT_STACK_SUPPORT_REQD - - - -#ifdef __cplusplus -extern "C" { -#endif - -#define NRF_FAULT_ID_SDK_RANGE_START (0x00004000) /**< The start of the range of error IDs defined in the SDK. */ - -/**@defgroup APP_ERROR_FAULT_IDS Fault ID types - * @{ */ -#define NRF_FAULT_ID_SDK_ERROR (NRF_FAULT_ID_SDK_RANGE_START + 1) /**< An error stemming from a call to @ref APP_ERROR_CHECK or @ref APP_ERROR_CHECK_BOOL. The info parameter is a pointer to an @ref error_info_t variable. */ -#define NRF_FAULT_ID_SDK_ASSERT (NRF_FAULT_ID_SDK_RANGE_START + 2) /**< An error stemming from a call to ASSERT (nrf_assert.h). The info parameter is a pointer to an @ref assert_info_t variable. */ -/**@} */ - -/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ERROR. - */ -typedef struct -{ - uint32_t line_num; /**< The line number where the error occurred. */ - uint8_t const * p_file_name; /**< The file in which the error occurred. */ - uint32_t err_code; /**< The error code representing the error that occurred. */ -} error_info_t; - -/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ASSERT. - */ -typedef struct -{ - uint16_t line_num; /**< The line number where the error occurred. */ - uint8_t const * p_file_name; /**< The file in which the error occurred. */ -} assert_info_t; - -/**@brief Defines required by app_error_handler assembler intructions. - */ -#define APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM (offsetof(error_info_t, line_num)) -#define APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME (offsetof(error_info_t, p_file_name)) -#define APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE (offsetof(error_info_t, err_code)) -#define APP_ERROR_ERROR_INFO_SIZE (sizeof(error_info_t)) -#define APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE \ - ALIGN_NUM(APP_ERROR_ERROR_INFO_SIZE, sizeof(uint64_t)) - - -/**@brief Function for error handling, which is called when an error has occurred. - * - * @param[in] error_code Error code supplied to the handler. - * @param[in] line_num Line number where the handler is called. - * @param[in] p_file_name Pointer to the file name. - */ -void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name); - -/**@brief Function for error handling, which is called when an error has occurred. - * - * @param[in] error_code Error code supplied to the handler. - */ -void app_error_handler_bare(ret_code_t error_code); - -/**@brief Function for saving the parameters and entering an eternal loop, for debug purposes. - * - * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. - * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if - * unavailable. - * @param[in] info Optional additional information regarding the fault. Refer to each fault - * identifier for details. - */ -void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info); - -/**@brief Function for logging details of error and flushing logs. - * - * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. - * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if - * unavailable. - * @param[in] info Optional additional information regarding the fault. Refer to each fault - * identifier for details. - */ -void app_error_log_handle(uint32_t id, uint32_t pc, uint32_t info); - - -/**@brief Macro for calling error handler function. - * - * @param[in] ERR_CODE Error code supplied to the error handler. - */ -#ifdef DEBUG -#define APP_ERROR_HANDLER(ERR_CODE) \ - do \ - { \ - app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__); \ - } while (0) -#else -#define APP_ERROR_HANDLER(ERR_CODE) \ - do \ - { \ - app_error_handler_bare((ERR_CODE)); \ - } while (0) -#endif -/**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS. - * - * @param[in] ERR_CODE Error code supplied to the error handler. - */ -#define APP_ERROR_CHECK(ERR_CODE) \ - do \ - { \ - const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \ - if (LOCAL_ERR_CODE != NRF_SUCCESS) \ - { \ - APP_ERROR_HANDLER(LOCAL_ERR_CODE); \ - } \ - } while (0) - -/**@brief Macro for calling error handler function if supplied boolean value is false. - * - * @param[in] BOOLEAN_VALUE Boolean value to be evaluated. - */ -#define APP_ERROR_CHECK_BOOL(BOOLEAN_VALUE) \ - do \ - { \ - const uint32_t LOCAL_BOOLEAN_VALUE = (BOOLEAN_VALUE); \ - if (!LOCAL_BOOLEAN_VALUE) \ - { \ - APP_ERROR_HANDLER(0); \ - } \ - } while (0) - - -#ifdef __cplusplus -} -#endif - -#endif // APP_ERROR_H__ - -/** @} */ +/** + * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler and macros for utilizing a common error handler. + */ + +#ifndef APP_ERROR_H__ +#define APP_ERROR_H__ + + +#include +#include +#include +#include "nrf.h" +#include "sdk_errors.h" +#include "nordic_common.h" +#include "app_error_weak.h" +#ifdef ANT_STACK_SUPPORT_REQD +#include "ant_error.h" +#endif // ANT_STACK_SUPPORT_REQD + + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_FAULT_ID_SDK_RANGE_START (0x00004000) /**< The start of the range of error IDs defined in the SDK. */ + +/**@defgroup APP_ERROR_FAULT_IDS Fault ID types + * @{ */ +#define NRF_FAULT_ID_SDK_ERROR (NRF_FAULT_ID_SDK_RANGE_START + 1) /**< An error stemming from a call to @ref APP_ERROR_CHECK or @ref APP_ERROR_CHECK_BOOL. The info parameter is a pointer to an @ref error_info_t variable. */ +#define NRF_FAULT_ID_SDK_ASSERT (NRF_FAULT_ID_SDK_RANGE_START + 2) /**< An error stemming from a call to ASSERT (nrf_assert.h). The info parameter is a pointer to an @ref assert_info_t variable. */ +/**@} */ + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ERROR. + */ +typedef struct +{ + uint32_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ + uint32_t err_code; /**< The error code representing the error that occurred. */ +} error_info_t; + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ASSERT. + */ +typedef struct +{ + uint16_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ +} assert_info_t; + +/**@brief Defines required by app_error_handler assembler intructions. + */ +#define APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM (offsetof(error_info_t, line_num)) +#define APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME (offsetof(error_info_t, p_file_name)) +#define APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE (offsetof(error_info_t, err_code)) +#define APP_ERROR_ERROR_INFO_SIZE (sizeof(error_info_t)) +#define APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE \ + ALIGN_NUM(APP_ERROR_ERROR_INFO_SIZE, sizeof(uint64_t)) + + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ +void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name); + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + */ +void app_error_handler_bare(ret_code_t error_code); + +/**@brief Function for saving the parameters and entering an eternal loop, for debug purposes. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info); + +/**@brief Function for logging details of error and flushing logs. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +void app_error_log_handle(uint32_t id, uint32_t pc, uint32_t info); + + +/**@brief Macro for calling error handler function. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + */ +#ifdef DEBUG +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__); \ + } while (0) +#else +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler_bare((ERR_CODE)); \ + } while (0) +#endif +/**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + */ +#define APP_ERROR_CHECK(ERR_CODE) \ + do \ + { \ + const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \ + if (LOCAL_ERR_CODE != NRF_SUCCESS) \ + { \ + APP_ERROR_HANDLER(LOCAL_ERR_CODE); \ + } \ + } while (0) + +/**@brief Macro for calling error handler function if supplied boolean value is false. + * + * @param[in] BOOLEAN_VALUE Boolean value to be evaluated. + */ +#define APP_ERROR_CHECK_BOOL(BOOLEAN_VALUE) \ + do \ + { \ + const uint32_t LOCAL_BOOLEAN_VALUE = (BOOLEAN_VALUE); \ + if (!LOCAL_BOOLEAN_VALUE) \ + { \ + APP_ERROR_HANDLER(0); \ + } \ + } while (0) + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_H__ + +/** @} */ diff --git a/third_party/NordicSemiconductor/libraries/app_error/app_error_weak.c b/third_party/NordicSemiconductor/libraries/app_error/app_error_weak.c index 9a5f3e6f8..f101410f0 100644 --- a/third_party/NordicSemiconductor/libraries/app_error/app_error_weak.c +++ b/third_party/NordicSemiconductor/libraries/app_error/app_error_weak.c @@ -1,60 +1,60 @@ -/** - * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "app_error.h" - -/*lint -save -e14 */ -/** - * Function is implemented as weak so that it can be overwritten by custom application error handler - * when needed. - */ -__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) -{ - (void)id; - (void)pc; - (void)info; - -#ifndef DEBUG - NVIC_SystemReset(); -#else - app_error_save_and_stop(id, pc, info); -#endif // DEBUG -} -/*lint -restore */ +/** + * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "app_error.h" + +/*lint -save -e14 */ +/** + * Function is implemented as weak so that it can be overwritten by custom application error handler + * when needed. + */ +__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) +{ + (void)id; + (void)pc; + (void)info; + +#ifndef DEBUG + NVIC_SystemReset(); +#else + app_error_save_and_stop(id, pc, info); +#endif // DEBUG +} +/*lint -restore */ diff --git a/third_party/NordicSemiconductor/libraries/app_error/app_error_weak.h b/third_party/NordicSemiconductor/libraries/app_error/app_error_weak.h index e64fc218a..4476ae1bd 100644 --- a/third_party/NordicSemiconductor/libraries/app_error/app_error_weak.h +++ b/third_party/NordicSemiconductor/libraries/app_error/app_error_weak.h @@ -1,87 +1,87 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef APP_ERROR_WEAK_H__ -#define APP_ERROR_WEAK_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** @file - * - * @defgroup app_error Common application error handler - * @{ - * @ingroup app_common - * - * @brief Common application error handler. - */ - -/**@brief Callback function for errors, asserts, and faults. - * - * @details This function is called every time an error is raised in app_error, nrf_assert, or - * in the SoftDevice. Information about the error can be found in the @p info - * parameter. - * - * See also @ref nrf_fault_handler_t for more details. - * - * @note The function is implemented as weak so that it can be redefined by a custom error - * handler when needed. - * - * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. - * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if - * unavailable. - * @param[in] info Optional additional information regarding the fault. The value of the @p id - * parameter dictates how to interpret this parameter. Refer to the documentation - * for each fault identifier (@ref NRF_FAULT_IDS and @ref APP_ERROR_FAULT_IDS) for - * details about interpreting @p info. - */ -void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info); - - -/** @} */ - - -#ifdef __cplusplus -} -#endif - -#endif // APP_ERROR_WEAK_H__ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef APP_ERROR_WEAK_H__ +#define APP_ERROR_WEAK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler. + */ + +/**@brief Callback function for errors, asserts, and faults. + * + * @details This function is called every time an error is raised in app_error, nrf_assert, or + * in the SoftDevice. Information about the error can be found in the @p info + * parameter. + * + * See also @ref nrf_fault_handler_t for more details. + * + * @note The function is implemented as weak so that it can be redefined by a custom error + * handler when needed. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. The value of the @p id + * parameter dictates how to interpret this parameter. Refer to the documentation + * for each fault identifier (@ref NRF_FAULT_IDS and @ref APP_ERROR_FAULT_IDS) for + * details about interpreting @p info. + */ +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info); + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_WEAK_H__ diff --git a/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.c b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.c index 3227cee5a..ff852d649 100644 --- a/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.c +++ b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.c @@ -1,189 +1,189 @@ -/** - * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -#include -#include -#include "app_util.h" -#include "nrf_atfifo.h" -#include "nrf_atfifo_internal.h" - -#if NRF_ATFIFO_CONFIG_LOG_ENABLED - #define NRF_LOG_LEVEL NRF_ATFIFO_CONFIG_LOG_LEVEL - #define NRF_LOG_INIT_FILTER_LEVEL NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL - #define NRF_LOG_INFO_COLOR NRF_ATFIFO_CONFIG_INFO_COLOR - #define NRF_LOG_DEBUG_COLOR NRF_ATFIFO_CONFIG_DEBUG_COLOR -#else - #define NRF_LOG_LEVEL 0 -#endif // NRF_ATFIFO_CONFIG_LOG_ENABLED -#include "nrf_log.h" - -/* Unions testing */ -STATIC_ASSERT(sizeof(nrf_atfifo_postag_t) == sizeof(uint32_t)); - - -ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size) -{ - if (NULL == p_buf) - { - NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. p_buf == NULL"); - return NRF_ERROR_NULL; - } - if (0 != (buf_size % item_size)) - { - NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. Buf_size not multiple of item_size"); - return NRF_ERROR_INVALID_LENGTH; - } - - p_fifo->p_buf = p_buf; - p_fifo->tail.tag = 0; - p_fifo->head.tag = 0; - p_fifo->buf_size = buf_size; - p_fifo->item_size = item_size; - - NRF_LOG_INST_INFO(p_fifo->p_log, "Initialized."); - return NRF_SUCCESS; -} - - -ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo) -{ - bool released = nrf_atfifo_space_clear(p_fifo); - NRF_LOG_INST_INFO(p_fifo->p_log, "Cleared result:%s", released ? "success" : "busy"); - return released ? NRF_SUCCESS : NRF_ERROR_BUSY; -} - - -ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * p_var, size_t size, bool * const p_visible) -{ - nrf_atfifo_item_put_t context; - bool visible; - void * p_data = nrf_atfifo_item_alloc(p_fifo, &context); - if (NULL == p_data) - { - NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying in element (0x%08X) failed - no space.", p_var); - return NRF_ERROR_NO_MEM; - } - - memcpy(p_data, p_var, size); - - visible = nrf_atfifo_item_put(p_fifo, &context); - if (NULL != p_visible) - { - *p_visible = visible; - } - NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied in.", p_var); - return NRF_SUCCESS; -} - - -void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) -{ - if (nrf_atfifo_wspace_req(p_fifo, &(p_context->last_tail))) - { - void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_tail.pos.wr; - NRF_LOG_INST_DEBUG(p_fifo->p_log, "Allocated element (0x%08X).", p_item); - return p_item; - } - NRF_LOG_INST_WARNING(p_fifo->p_log, "Allocation failed - no space."); - return NULL; -} - - -bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) -{ - if ((p_context->last_tail.pos.wr) == (p_context->last_tail.pos.rd)) - { - NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (uninterrupted)"); - nrf_atfifo_wspace_close(p_fifo); - return true; - } - NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (interrupted!)"); - return false; -} - - -ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released) -{ - nrf_atfifo_item_get_t context; - bool released; - void const * p_s = nrf_atfifo_item_get(p_fifo, &context); - if (NULL == p_s) - { - NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying out failed - no item in the FIFO."); - return NRF_ERROR_NOT_FOUND; - } - - memcpy(p_var, p_s, size); - - released = nrf_atfifo_item_free(p_fifo, &context); - if (NULL != p_released) - { - *p_released = released; - } - NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied out.", p_var); - return NRF_SUCCESS; -} - - -void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) -{ - if (nrf_atfifo_rspace_req(p_fifo, &(p_context->last_head))) - { - void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_head.pos.rd; - NRF_LOG_INST_DEBUG(p_fifo->p_log, "Get element: 0x%08X", p_item); - return p_item; - } - NRF_LOG_INST_WARNING(p_fifo->p_log, "Get failed - no item in the FIFO."); - return NULL; -} - - -bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) -{ - if ((p_context->last_head.pos.wr) == (p_context->last_head.pos.rd)) - { - NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (uninterrupted)"); - nrf_atfifo_rspace_close(p_fifo); - return true; - } - NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (interrupted)"); - return false; -} +/** + * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include "app_util.h" +#include "nrf_atfifo.h" +#include "nrf_atfifo_internal.h" + +#if NRF_ATFIFO_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_ATFIFO_CONFIG_LOG_LEVEL + #define NRF_LOG_INIT_FILTER_LEVEL NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL + #define NRF_LOG_INFO_COLOR NRF_ATFIFO_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_ATFIFO_CONFIG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_ATFIFO_CONFIG_LOG_ENABLED +#include "nrf_log.h" + +/* Unions testing */ +STATIC_ASSERT(sizeof(nrf_atfifo_postag_t) == sizeof(uint32_t)); + + +ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size) +{ + if (NULL == p_buf) + { + NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. p_buf == NULL"); + return NRF_ERROR_NULL; + } + if (0 != (buf_size % item_size)) + { + NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. Buf_size not multiple of item_size"); + return NRF_ERROR_INVALID_LENGTH; + } + + p_fifo->p_buf = p_buf; + p_fifo->tail.tag = 0; + p_fifo->head.tag = 0; + p_fifo->buf_size = buf_size; + p_fifo->item_size = item_size; + + NRF_LOG_INST_INFO(p_fifo->p_log, "Initialized."); + return NRF_SUCCESS; +} + + +ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo) +{ + bool released = nrf_atfifo_space_clear(p_fifo); + NRF_LOG_INST_INFO(p_fifo->p_log, "Cleared result:%s", released ? "success" : "busy"); + return released ? NRF_SUCCESS : NRF_ERROR_BUSY; +} + + +ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * p_var, size_t size, bool * const p_visible) +{ + nrf_atfifo_item_put_t context; + bool visible; + void * p_data = nrf_atfifo_item_alloc(p_fifo, &context); + if (NULL == p_data) + { + NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying in element (0x%08X) failed - no space.", p_var); + return NRF_ERROR_NO_MEM; + } + + memcpy(p_data, p_var, size); + + visible = nrf_atfifo_item_put(p_fifo, &context); + if (NULL != p_visible) + { + *p_visible = visible; + } + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied in.", p_var); + return NRF_SUCCESS; +} + + +void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) +{ + if (nrf_atfifo_wspace_req(p_fifo, &(p_context->last_tail))) + { + void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_tail.pos.wr; + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Allocated element (0x%08X).", p_item); + return p_item; + } + NRF_LOG_INST_WARNING(p_fifo->p_log, "Allocation failed - no space."); + return NULL; +} + + +bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) +{ + if ((p_context->last_tail.pos.wr) == (p_context->last_tail.pos.rd)) + { + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (uninterrupted)"); + nrf_atfifo_wspace_close(p_fifo); + return true; + } + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (interrupted!)"); + return false; +} + + +ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released) +{ + nrf_atfifo_item_get_t context; + bool released; + void const * p_s = nrf_atfifo_item_get(p_fifo, &context); + if (NULL == p_s) + { + NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying out failed - no item in the FIFO."); + return NRF_ERROR_NOT_FOUND; + } + + memcpy(p_var, p_s, size); + + released = nrf_atfifo_item_free(p_fifo, &context); + if (NULL != p_released) + { + *p_released = released; + } + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied out.", p_var); + return NRF_SUCCESS; +} + + +void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) +{ + if (nrf_atfifo_rspace_req(p_fifo, &(p_context->last_head))) + { + void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_head.pos.rd; + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Get element: 0x%08X", p_item); + return p_item; + } + NRF_LOG_INST_WARNING(p_fifo->p_log, "Get failed - no item in the FIFO."); + return NULL; +} + + +bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) +{ + if ((p_context->last_head.pos.wr) == (p_context->last_head.pos.rd)) + { + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (uninterrupted)"); + nrf_atfifo_rspace_close(p_fifo); + return true; + } + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (interrupted)"); + return false; +} diff --git a/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.h b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.h index 376d0d880..934f9acd0 100644 --- a/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.h +++ b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.h @@ -1,424 +1,424 @@ -/** - * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef NRF_ATFIFO_H__ -#define NRF_ATFIFO_H__ - -#include -#include -#include "sdk_config.h" -#include "nordic_common.h" -#include "nrf_assert.h" -#include "sdk_errors.h" -#include "nrf_log_instance.h" -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup nrf_atfifo Atomic FIFO - * @ingroup app_common - * - * @brief @tagAPI52 FIFO implementation that allows for making atomic transactions without - * locking interrupts. - * - * @details There are two types of functions to prepare the FIFO writing: - * - Single function for simple access: - * @code - * if (NRF_SUCCESS != nrf_atfifo_simple_put(my_fifo, &data, NULL)) - * { - * // Error handling - * } - * @endcode - * - Function pair to limit data copying: - * @code - * struct point3d - * { - * int x, y, z; - * }point3d_t; - * nrf_atfifo_context_t context; - * point3d_t * point; - * - * if (NULL != (point = nrf_atfifo_item_alloc(my_fifo, &context))) - * { - * point->x = a; - * point->y = b; - * point->z = c; - * if (nrf_atfifo_item_put(my_fifo, &context)) - * { - * // Send information to the rest of the system - * // that there is new data in the FIFO available for reading. - * } - * } - * else - * { - * // Error handling - * } - * - * @endcode - * @note - * This atomic FIFO implementation requires that the operation that is - * opened last is finished (committed/flushed) first. - * This is typical for operations performed from the interrupt runtime - * when the other operation is performed from the main thread. - * - * This implementation does not support typical multithreading operating system - * access where operations can be started and finished in totally unrelated order. - * - * @{ - */ - -/** - * @brief Read and write position structure. - * - * A structure that holds the read and write position used by the FIFO head and tail. - */ -typedef struct nrf_atfifo_postag_pos_s -{ - uint16_t wr; //!< First free space to write the data - uint16_t rd; //!< A place after the last data to read -}nrf_atfifo_postag_pos_t; - -/** - * @brief End data index tag. - * - * A tag used to mark the end of data. - * To properly realize atomic data committing, the whole variable has to be - * accessed atomically. - */ -typedef union nrf_atfifo_postag_u -{ - uint32_t tag; //!< Whole tag, used for atomic, 32-bit access - nrf_atfifo_postag_pos_t pos; //!< Structure that holds reading and writing position separately -}nrf_atfifo_postag_t; - -/** - * @brief The FIFO instance. - * - * The instance of atomic FIFO. - * Used with all FIFO functions. - */ -typedef struct nrf_atfifo_s -{ - void * p_buf; //!< Pointer to the data buffer - nrf_atfifo_postag_t tail; //!< Read and write tail position tag - nrf_atfifo_postag_t head; //!< Read and write head position tag - uint16_t buf_size; //!< FIFO size in number of bytes (has to be divisible by @c item_size) - uint16_t item_size; //!< Size of a single FIFO item - NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled). -}nrf_atfifo_t; - -/** - * @brief FIFO write operation item context. - * - * Context structure used to mark an allocated space in FIFO that is ready for put. - * All the data required to properly put allocated and written data. - */ -typedef struct nrf_atfifo_item_put_s -{ - nrf_atfifo_postag_t last_tail; //!< Tail tag value that was here when opening the FIFO to write -}nrf_atfifo_item_put_t; - - -/** - * @brief FIFO read operation item context. - * - * Context structure used to mark an opened get operation to properly free an item after reading. - */ -typedef struct nrf_atfifo_rcontext_s -{ - nrf_atfifo_postag_t last_head; //!< Head tag value that was here when opening the FIFO to read -}nrf_atfifo_item_get_t; - - -/** @brief Name of the module used for logger messaging. - */ -#define NRF_ATFIFO_LOG_NAME atfifo - -/** - * @defgroup nrf_atfifo_instmacros FIFO instance macros - * - * A group of macros helpful for FIFO instance creation and initialization. - * They may be used to create and initialize instances for most use cases. - * - * FIFO may also be created and initialized directly using - * @ref nrf_atfifo_init function. - * @{ - */ - /** - * @brief Macro for generating the name for a data buffer. - * - * The name of the data buffer that would be created by - * @ref NRF_ATFIFO_DEF macro. - * - * @param[in] fifo_id Identifier of the FIFO object. - * - * @return Name of the buffer variable. - * - * @note This is auxiliary internal macro and in normal usage - * it should not be called. - */ - #define NRF_ATFIFO_BUF_NAME(fifo_id) CONCAT_2(fifo_id, _data) - - /** - * @brief Macro for generating the name for a FIFO instance. - * - * The name of the instance variable that will be created by the - * @ref NRF_ATFIFO_DEF macro. - * - * @param[in] fifo_id Identifier of the FIFO object. - * - * @return Name of the instance variable. - * - * @note This is auxiliary internal macro and in normal usage - * it should not be called. - */ - #define NRF_ATFIFO_INST_NAME(fifo_id) CONCAT_2(fifo_id, _inst) - - /** - * @brief Macro for creating an instance. - * - * Creates the FIFO object variable itself. - * - * Usage example: - * @code - * NRF_ATFIFO_DEF(my_fifo, uint16_t, 12); - * NRF_ATFIFO_INIT(my_fifo); - * - * uint16_t some_val = 45; - * nrf_atfifo_item_put(my_fifo, &some_val, sizeof(some_val), NULL); - * nrf_atfifo_item_get(my_fifo, &some_val, sizeof(some_val), NULL); - * @endcode - * - * @param[in] fifo_id Identifier of a FIFO object. - * This identifier will be a pointer to the instance. - * It makes it possible to use this directly for the functions - * that operate on the FIFO. - * Because it is a static const object, it should be optimized by the compiler. - * @param[in] storage_type Type of data that will be stored in the FIFO. - * @param[in] item_cnt Capacity of the created FIFO in maximum number of items that may be stored. - * The phisical size of the buffer will be 1 element bigger. - */ - #define NRF_ATFIFO_DEF(fifo_id, storage_type, item_cnt) \ - static storage_type NRF_ATFIFO_BUF_NAME(fifo_id)[(item_cnt)+1]; \ - NRF_LOG_INSTANCE_REGISTER(NRF_ATFIFO_LOG_NAME, fifo_id, \ - NRF_ATFIFO_CONFIG_INFO_COLOR, \ - NRF_ATFIFO_CONFIG_DEBUG_COLOR, \ - NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL, \ - NRF_ATFIFO_CONFIG_LOG_ENABLED ? \ - NRF_ATFIFO_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \ - static nrf_atfifo_t NRF_ATFIFO_INST_NAME(fifo_id) = { \ - .p_buf = NULL, \ - NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_ATFIFO_LOG_NAME, fifo_id) \ - }; \ - static nrf_atfifo_t * const fifo_id = &NRF_ATFIFO_INST_NAME(fifo_id) - - /** - * @brief Macro for initializing the FIFO that was previously declared by the macro. - * - * Use this macro to simplify FIFO initialization. - * - * @note - * This macro can be only used on a FIFO object defined by @ref NRF_ATFIFO_DEF macro. - * - * @param[in] fifo_id Identifier of the FIFO object. - * - * @return Value from the @ref nrf_atfifo_init function. - */ - #define NRF_ATFIFO_INIT(fifo_id) \ - nrf_atfifo_init( \ - fifo_id, \ - NRF_ATFIFO_BUF_NAME(fifo_id), \ - sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)), \ - sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)[0]) \ - ) - -/** @} */ - -/** - * @brief Function for initializing the FIFO. - * - * Preparing the FIFO instance to work. - * - * @param[out] p_fifo FIFO object to initialize. - * @param[in,out] p_buf FIFO buffer for storing data. - * @param[in] buf_size Total buffer size (has to be divisible by @c item_size). - * @param[in] item_size Size of a single item held inside the FIFO. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_NULL If a NULL pointer is provided as the buffer. - * @retval NRF_ERROR_INVALID_LENGTH If size of the buffer provided is not divisible by @c item_size. - * - * @note - * Buffer size must be able to hold one element more than the designed FIFO capacity. - * This one, empty element is used for overflow checking. - */ -ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size); - -/** - * @brief Function for clearing the FIFO. - * - * Function for clearing the FIFO. - * - * If this function is called during an opened and uncommitted write operation, - * the FIFO is cleared up to the currently ongoing commit. - * There is no possibility to cancel an ongoing commit. - * - * If this function is called during an opened and unflushed read operation, - * the read position in the head is set, but copying it into the write head position - * is left to read closing operation. - * - * This way, there is no more data to read, but the memory is released - * in the moment when it is safe. - * - * @param[in,out] p_fifo FIFO object. - * - * @retval NRF_SUCCESS FIFO totally cleared. - * @retval NRF_ERROR_BUSY Function called in the middle of writing or reading operation. - * If it is called in the middle of writing operation, - * FIFO was cleared up to the already started and uncommitted write. - * If it is called in the middle of reading operation, - * write head was only moved. It will be copied into read tail when the reading operation - * is flushed. - */ -ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo); - -/** - * @brief Function for atomically putting data into the FIFO. - * - * It uses memcpy function inside and in most situations, it is more suitable to - * use @ref nrf_atfifo_item_alloc, write the data, and @ref nrf_atfifo_item_put to store a new value - * in a FIFO. - * - * @param[in,out] p_fifo FIFO object. - * @param[in] p_var Variable to copy. - * @param[in] size Size of the variable to copy. - * Can be smaller or equal to the FIFO item size. - * @param[out] p_visible See value returned by @ref nrf_atfifo_item_put. - * It may be NULL if the caller does not require the current operation status. - * - * @retval NRF_SUCCESS If an element has been successfully added to the FIFO. - * @retval NRF_ERROR_NO_MEM If the FIFO is full. - * - * @note - * To avoid data copying, you can use the @ref nrf_atfifo_item_alloc and @ref nrf_atfifo_item_put - * functions pair. - */ -ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * const p_var, size_t size, bool * const p_visible); - -/** - * @brief Function for opening the FIFO for writing. - * - * Function called to start the FIFO write operation and access the given FIFO buffer directly. - * - * @param[in,out] p_fifo FIFO object. - * @param[out] p_context Operation context, required by @ref nrf_atfifo_item_put. - * - * @return Pointer to the space where variable data can be stored. - * NULL if there is no space in the buffer. - */ -void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); - -/** - * @brief Function for closing the writing operation. - * - * Puts a previously allocated context into FIFO. - * This function must be called to commit an opened write operation. - * It sets all the buffers and marks the data, so that it is visible to read. - * - * @param[in,out] p_fifo FIFO object. - * @param[in] p_context Operation context, filled by the @ref nrf_atfifo_item_alloc function. - * - * @retval true Data is currently ready and will be visible to read. - * @retval false The internal commit was marked, but the writing operation interrupted another writing operation. - * The data will be available to read when the interrupted operation is committed. - */ -bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); - -/** - * @brief Function for getting a single value from the FIFO. - * - * This function gets the value from the top of the FIFO. - * The value is removed from the FIFO memory. - * - * @param[in,out] p_fifo FIFO object. - * @param[out] p_var Pointer to the variable to store the data. - * @param[in] size Size of the data to be loaded. - * @param[out] p_released See the values returned by @ref nrf_atfifo_item_free. - * - * @retval NRF_SUCCESS Element was successfully copied from the FIFO memory. - * @retval NRF_ERROR_NOT_FOUND No data in the FIFO. - */ -ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released); - -/** - * @brief Function for opening the FIFO for reading. - * - * Function called to start the FIFO read operation and access the given FIFO buffer directly. - * - * @param[in,out] p_fifo FIFO object. - * @param[out] p_context The operation context, required by @ref nrf_atfifo_item_free - * - * @return Pointer to data buffer or NULL if there is no data in the FIFO. - */ -void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); - -/** - * @brief Function for closing the reading operation. - * - * Function used to finish the reading operation. - * If this reading operation does not interrupt another reading operation, the head write buffer is moved. - * If this reading operation is placed in the middle of another reading, only the new read pointer is written. - * - * @param[in,out] p_fifo FIFO object. - * @param[in] p_context Context of the reading operation to be closed. - * - * @retval true This operation is not generated in the middle of another read operation and the write head will be updated to the read head (space is released). - * @retval false This operation was performed in the middle of another read operation and the write buffer head was not moved (no space is released). - */ -bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); - - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* NRF_ATFIFO_H__ */ +/** + * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_ATFIFO_H__ +#define NRF_ATFIFO_H__ + +#include +#include +#include "sdk_config.h" +#include "nordic_common.h" +#include "nrf_assert.h" +#include "sdk_errors.h" +#include "nrf_log_instance.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_atfifo Atomic FIFO + * @ingroup app_common + * + * @brief @tagAPI52 FIFO implementation that allows for making atomic transactions without + * locking interrupts. + * + * @details There are two types of functions to prepare the FIFO writing: + * - Single function for simple access: + * @code + * if (NRF_SUCCESS != nrf_atfifo_simple_put(my_fifo, &data, NULL)) + * { + * // Error handling + * } + * @endcode + * - Function pair to limit data copying: + * @code + * struct point3d + * { + * int x, y, z; + * }point3d_t; + * nrf_atfifo_context_t context; + * point3d_t * point; + * + * if (NULL != (point = nrf_atfifo_item_alloc(my_fifo, &context))) + * { + * point->x = a; + * point->y = b; + * point->z = c; + * if (nrf_atfifo_item_put(my_fifo, &context)) + * { + * // Send information to the rest of the system + * // that there is new data in the FIFO available for reading. + * } + * } + * else + * { + * // Error handling + * } + * + * @endcode + * @note + * This atomic FIFO implementation requires that the operation that is + * opened last is finished (committed/flushed) first. + * This is typical for operations performed from the interrupt runtime + * when the other operation is performed from the main thread. + * + * This implementation does not support typical multithreading operating system + * access where operations can be started and finished in totally unrelated order. + * + * @{ + */ + +/** + * @brief Read and write position structure. + * + * A structure that holds the read and write position used by the FIFO head and tail. + */ +typedef struct nrf_atfifo_postag_pos_s +{ + uint16_t wr; //!< First free space to write the data + uint16_t rd; //!< A place after the last data to read +}nrf_atfifo_postag_pos_t; + +/** + * @brief End data index tag. + * + * A tag used to mark the end of data. + * To properly realize atomic data committing, the whole variable has to be + * accessed atomically. + */ +typedef union nrf_atfifo_postag_u +{ + uint32_t tag; //!< Whole tag, used for atomic, 32-bit access + nrf_atfifo_postag_pos_t pos; //!< Structure that holds reading and writing position separately +}nrf_atfifo_postag_t; + +/** + * @brief The FIFO instance. + * + * The instance of atomic FIFO. + * Used with all FIFO functions. + */ +typedef struct nrf_atfifo_s +{ + void * p_buf; //!< Pointer to the data buffer + nrf_atfifo_postag_t tail; //!< Read and write tail position tag + nrf_atfifo_postag_t head; //!< Read and write head position tag + uint16_t buf_size; //!< FIFO size in number of bytes (has to be divisible by @c item_size) + uint16_t item_size; //!< Size of a single FIFO item + NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled). +}nrf_atfifo_t; + +/** + * @brief FIFO write operation item context. + * + * Context structure used to mark an allocated space in FIFO that is ready for put. + * All the data required to properly put allocated and written data. + */ +typedef struct nrf_atfifo_item_put_s +{ + nrf_atfifo_postag_t last_tail; //!< Tail tag value that was here when opening the FIFO to write +}nrf_atfifo_item_put_t; + + +/** + * @brief FIFO read operation item context. + * + * Context structure used to mark an opened get operation to properly free an item after reading. + */ +typedef struct nrf_atfifo_rcontext_s +{ + nrf_atfifo_postag_t last_head; //!< Head tag value that was here when opening the FIFO to read +}nrf_atfifo_item_get_t; + + +/** @brief Name of the module used for logger messaging. + */ +#define NRF_ATFIFO_LOG_NAME atfifo + +/** + * @defgroup nrf_atfifo_instmacros FIFO instance macros + * + * A group of macros helpful for FIFO instance creation and initialization. + * They may be used to create and initialize instances for most use cases. + * + * FIFO may also be created and initialized directly using + * @ref nrf_atfifo_init function. + * @{ + */ + /** + * @brief Macro for generating the name for a data buffer. + * + * The name of the data buffer that would be created by + * @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Name of the buffer variable. + * + * @note This is auxiliary internal macro and in normal usage + * it should not be called. + */ + #define NRF_ATFIFO_BUF_NAME(fifo_id) CONCAT_2(fifo_id, _data) + + /** + * @brief Macro for generating the name for a FIFO instance. + * + * The name of the instance variable that will be created by the + * @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Name of the instance variable. + * + * @note This is auxiliary internal macro and in normal usage + * it should not be called. + */ + #define NRF_ATFIFO_INST_NAME(fifo_id) CONCAT_2(fifo_id, _inst) + + /** + * @brief Macro for creating an instance. + * + * Creates the FIFO object variable itself. + * + * Usage example: + * @code + * NRF_ATFIFO_DEF(my_fifo, uint16_t, 12); + * NRF_ATFIFO_INIT(my_fifo); + * + * uint16_t some_val = 45; + * nrf_atfifo_item_put(my_fifo, &some_val, sizeof(some_val), NULL); + * nrf_atfifo_item_get(my_fifo, &some_val, sizeof(some_val), NULL); + * @endcode + * + * @param[in] fifo_id Identifier of a FIFO object. + * This identifier will be a pointer to the instance. + * It makes it possible to use this directly for the functions + * that operate on the FIFO. + * Because it is a static const object, it should be optimized by the compiler. + * @param[in] storage_type Type of data that will be stored in the FIFO. + * @param[in] item_cnt Capacity of the created FIFO in maximum number of items that may be stored. + * The phisical size of the buffer will be 1 element bigger. + */ + #define NRF_ATFIFO_DEF(fifo_id, storage_type, item_cnt) \ + static storage_type NRF_ATFIFO_BUF_NAME(fifo_id)[(item_cnt)+1]; \ + NRF_LOG_INSTANCE_REGISTER(NRF_ATFIFO_LOG_NAME, fifo_id, \ + NRF_ATFIFO_CONFIG_INFO_COLOR, \ + NRF_ATFIFO_CONFIG_DEBUG_COLOR, \ + NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL, \ + NRF_ATFIFO_CONFIG_LOG_ENABLED ? \ + NRF_ATFIFO_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \ + static nrf_atfifo_t NRF_ATFIFO_INST_NAME(fifo_id) = { \ + .p_buf = NULL, \ + NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_ATFIFO_LOG_NAME, fifo_id) \ + }; \ + static nrf_atfifo_t * const fifo_id = &NRF_ATFIFO_INST_NAME(fifo_id) + + /** + * @brief Macro for initializing the FIFO that was previously declared by the macro. + * + * Use this macro to simplify FIFO initialization. + * + * @note + * This macro can be only used on a FIFO object defined by @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Value from the @ref nrf_atfifo_init function. + */ + #define NRF_ATFIFO_INIT(fifo_id) \ + nrf_atfifo_init( \ + fifo_id, \ + NRF_ATFIFO_BUF_NAME(fifo_id), \ + sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)), \ + sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)[0]) \ + ) + +/** @} */ + +/** + * @brief Function for initializing the FIFO. + * + * Preparing the FIFO instance to work. + * + * @param[out] p_fifo FIFO object to initialize. + * @param[in,out] p_buf FIFO buffer for storing data. + * @param[in] buf_size Total buffer size (has to be divisible by @c item_size). + * @param[in] item_size Size of a single item held inside the FIFO. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If a NULL pointer is provided as the buffer. + * @retval NRF_ERROR_INVALID_LENGTH If size of the buffer provided is not divisible by @c item_size. + * + * @note + * Buffer size must be able to hold one element more than the designed FIFO capacity. + * This one, empty element is used for overflow checking. + */ +ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size); + +/** + * @brief Function for clearing the FIFO. + * + * Function for clearing the FIFO. + * + * If this function is called during an opened and uncommitted write operation, + * the FIFO is cleared up to the currently ongoing commit. + * There is no possibility to cancel an ongoing commit. + * + * If this function is called during an opened and unflushed read operation, + * the read position in the head is set, but copying it into the write head position + * is left to read closing operation. + * + * This way, there is no more data to read, but the memory is released + * in the moment when it is safe. + * + * @param[in,out] p_fifo FIFO object. + * + * @retval NRF_SUCCESS FIFO totally cleared. + * @retval NRF_ERROR_BUSY Function called in the middle of writing or reading operation. + * If it is called in the middle of writing operation, + * FIFO was cleared up to the already started and uncommitted write. + * If it is called in the middle of reading operation, + * write head was only moved. It will be copied into read tail when the reading operation + * is flushed. + */ +ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo); + +/** + * @brief Function for atomically putting data into the FIFO. + * + * It uses memcpy function inside and in most situations, it is more suitable to + * use @ref nrf_atfifo_item_alloc, write the data, and @ref nrf_atfifo_item_put to store a new value + * in a FIFO. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_var Variable to copy. + * @param[in] size Size of the variable to copy. + * Can be smaller or equal to the FIFO item size. + * @param[out] p_visible See value returned by @ref nrf_atfifo_item_put. + * It may be NULL if the caller does not require the current operation status. + * + * @retval NRF_SUCCESS If an element has been successfully added to the FIFO. + * @retval NRF_ERROR_NO_MEM If the FIFO is full. + * + * @note + * To avoid data copying, you can use the @ref nrf_atfifo_item_alloc and @ref nrf_atfifo_item_put + * functions pair. + */ +ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * const p_var, size_t size, bool * const p_visible); + +/** + * @brief Function for opening the FIFO for writing. + * + * Function called to start the FIFO write operation and access the given FIFO buffer directly. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_context Operation context, required by @ref nrf_atfifo_item_put. + * + * @return Pointer to the space where variable data can be stored. + * NULL if there is no space in the buffer. + */ +void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); + +/** + * @brief Function for closing the writing operation. + * + * Puts a previously allocated context into FIFO. + * This function must be called to commit an opened write operation. + * It sets all the buffers and marks the data, so that it is visible to read. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_context Operation context, filled by the @ref nrf_atfifo_item_alloc function. + * + * @retval true Data is currently ready and will be visible to read. + * @retval false The internal commit was marked, but the writing operation interrupted another writing operation. + * The data will be available to read when the interrupted operation is committed. + */ +bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); + +/** + * @brief Function for getting a single value from the FIFO. + * + * This function gets the value from the top of the FIFO. + * The value is removed from the FIFO memory. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_var Pointer to the variable to store the data. + * @param[in] size Size of the data to be loaded. + * @param[out] p_released See the values returned by @ref nrf_atfifo_item_free. + * + * @retval NRF_SUCCESS Element was successfully copied from the FIFO memory. + * @retval NRF_ERROR_NOT_FOUND No data in the FIFO. + */ +ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released); + +/** + * @brief Function for opening the FIFO for reading. + * + * Function called to start the FIFO read operation and access the given FIFO buffer directly. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_context The operation context, required by @ref nrf_atfifo_item_free + * + * @return Pointer to data buffer or NULL if there is no data in the FIFO. + */ +void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); + +/** + * @brief Function for closing the reading operation. + * + * Function used to finish the reading operation. + * If this reading operation does not interrupt another reading operation, the head write buffer is moved. + * If this reading operation is placed in the middle of another reading, only the new read pointer is written. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_context Context of the reading operation to be closed. + * + * @retval true This operation is not generated in the middle of another read operation and the write head will be updated to the read head (space is released). + * @retval false This operation was performed in the middle of another read operation and the write buffer head was not moved (no space is released). + */ +bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); + + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATFIFO_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo_internal.h b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo_internal.h index d2edabf0a..eeb0aaa1e 100644 --- a/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo_internal.h +++ b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo_internal.h @@ -1,577 +1,577 @@ -/** - * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * @brief Atomic FIFO internal file - * - * This file should be included only by nrf_atfifo internally. - * Needs nrf_atfifo.h included first. - */ -#ifndef NRF_ATFIFO_H__ -#error This is internal file. Do not include this file in your program. -#endif - -#ifndef NRF_ATFIFO_INTERNAL_H__ -#define NRF_ATFIFO_INTERNAL_H__ -#include -#include "nrf.h" -#include "app_util.h" -#include "nordic_common.h" - -#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 -#error Unsupported core version -#endif - -/* - * Make sure that rd and wr pos in a tag are aligned like expected - * Changing this would require changes inside assembly code! - */ -STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, wr) == 0); -STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, rd) == 2); - -/** - * @brief Atomically reserve space for a new write. - * - * @param[in,out] p_fifo FIFO object. - * @param[out] old_tail Tail position tag before new space is reserved. - * - * @retval true Space available. - * @retval false Memory full. - * - * @sa nrf_atfifo_wspace_close - */ -static bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail); - -/** - * @brief Atomically mark all written data available. - * - * This function marks all data available for reading. - * This marking is done by copying tail.pos.wr into tail.pos.rd. - * - * It must be called only when closing the first write. - * It cannot be called if any write access was interrupted. - * See the code below: - * @code - * if (old_tail.pos.wr == old_tail.pos.rd) - * { - * nrf_atfifo_wspace_close(my_fifo); - * return true; - * } - * return false; - * @endcode - * - * @param[in,out] p_fifo FIFO object. - * - * @sa nrf_atfifo_wspace_req - */ -static void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo); - -/** - * @brief Atomically get a part of a buffer to read data. - * - * @param[in,out] p_fifo FIFO object. - * @param[out] old_head Head position tag before the data buffer is read. - * - * @retval true Data available for reading. - * @retval false No data in the buffer. - * - * @sa nrf_atfifo_rspace_close - */ -static bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head); - -/** - * @brief Atomically release all read data. - * - * This function marks all data that was read as free space, - * which is available for writing. - * This marking is done by copying head.pos.rd into head.pos.wr. - * - * It must be called only when closing the first read. - * It cannot be called when the current read access interrupted any other read access. - * See code below: - * @code - * if (old_head.pos.wr == old_head.pos.rd) - * { - * nrf_atfifo_rspace_close(my_fifo); - * return true; - * } - * return false; - * @endcode - * - * @param[in,out] p_fifo FIFO object. - * - * @sa nrf_atfifo_rspace_req - */ -static void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo); - -/** - * @brief Safely clear the FIFO, internal function. - * - * This function realizes the functionality required by @ref nrf_atfifo_clear. - * - * @param[in,out] p_fifo FIFO object. - * - * @retval true All the data was released. - * @retval false All the data available for releasing was released, but there is some pending transfer. - */ -static bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo); - - -/* --------------------------------------------------------------------------- - * Implementation starts here - */ - -#if defined ( __CC_ARM ) - - -__ASM bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) -{ - /* Registry usage: - * R0 - p_fifo - * R1 - p_old_tail - * R2 - internal variable old_tail (saved by caller) - * R3 - internal variable new_tail (saved by caller) - * R4 - internal temporary register (saved by this function) - * R5 - not used stored to keep the stack aligned to 8 bytes - * Returned value: - * R0 (bool - 32 bits) - */ - push {r4, r5} -nrf_atfifo_wspace_req_repeat - /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ - ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] - /* Extract write position !!! R3 !!! */ - uxth r3, r2 - /* Increment address with overload support !!! R4 used temporary !!! */ - ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] - add r3, r4 - ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] - cmp r3, r4 - it hs - subhs r3, r3, r4 - - /* Check if FIFO would overload after making this increment !!! R4 used temporary !!! */ - ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr))] - cmp r3, r4 - ittt eq - clrexeq - moveq r0, #__cpp(false) - beq nrf_atfifo_wspace_req_exit - - /* Pack everything back !!! R3 - new tail !!! */ - /* Copy lower byte from new_tail, and higher byte is a value from the top of old_tail */ - pkhbt r3, r3, r2 - - /* Store new value clearing memory monitor !!! R4 used temporary !!! */ - strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] - cmp r4, #0 - bne nrf_atfifo_wspace_req_repeat - - /* Return true */ - mov r0, #__cpp(true) -nrf_atfifo_wspace_req_exit - /* Save old tail */ - str r2, [r1] - pop {r4, r5} - bx lr -} - - -__ASM void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) -{ - /* Registry usage: - * R0 - p_fifo - * R1 - internal temporary register - * R2 - new_tail - */ -nrf_atfifo_wspace_close_repeat - ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] - /* Copy from lower byte to higher */ - pkhbt r2, r2, r2, lsl #16 - - strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] - cmp r1, #0 - bne nrf_atfifo_wspace_close_repeat - bx lr -} - - -__ASM bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) -{ - /* Registry usage: - * R0 - p_fifo - * R1 - p_old_head - * R2 - internal variable old_head (saved by caller) - * R3 - internal variable new_head (saved by caller) - * R4 - internal temporary register (saved by this function) - * R5 - not used stored to keep the stack aligned to 8 bytes - * Returned value: - * R0 (bool - 32 bits) - */ - push {r4, r5} -nrf_atfifo_rspace_req_repeat - /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ - ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] - /* Extract read position !!! R3 !!! */ - uxth r3, r2, ror #16 - - /* Check if we have any data !!! R4 used temporary !!! */ - ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] - cmp r3, r4 - ittt eq - clrexeq - moveq r0, #__cpp(false) - beq nrf_atfifo_rspace_req_exit - - /* Increment address with overload support !!! R4 used temporary !!! */ - ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] - add r3, r4 - ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] - cmp r3, r4 - it hs - subhs r3, r3, r4 - - /* Pack everything back !!! R3 - new tail !!! */ - /* Copy lower byte from old_head, and higher byte is a value from write_pos */ - pkhbt r3, r2, r3, lsl #16 - - /* Store new value clearing memory monitor !!! R4 used temporary !!! */ - strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] - cmp r4, #0 - bne nrf_atfifo_rspace_req_repeat - - /* Return true */ - mov r0, #__cpp(true) -nrf_atfifo_rspace_req_exit - /* Save old head */ - str r2, [r1] - pop {r4, r5} - bx lr -} - - -__ASM void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) -{ - /* Registry usage: - * R0 - p_fifo - * R1 - internal temporary register - * R2 - new_tail - */ -nrf_atfifo_rspace_close_repeat - ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] - /* Copy from higher byte to lower */ - pkhtb r2, r2, r2, asr #16 - - strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] - cmp r1, #0 - bne nrf_atfifo_rspace_close_repeat - bx lr -} - - -__ASM bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) -{ - /* Registry usage: - * R0 - p_fifo as input, bool output after - * R1 - tail, rd pointer, new_head - * R2 - head_old, destroyed when creating new_head - * R3 - p_fifo - copy - */ - mov r3, r0 -nrf_atfifo_space_clear_repeat - /* Load old head in !!! R2 register !!! and read pointer of tail in !!! R1 register !!! */ - ldrex r2, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] - ldrh r1, [r3, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] - cmp r2, r2, ror #16 - /* Return false as default */ - mov r0, #__cpp(false) - /* Create new head in !!! R1 register !!! Data in !!! R2 register broken !!! */ - itett ne - uxthne r2, r2 - orreq r1, r1, r1, lsl #16 - orrne r1, r2, r1, lsl #16 - - /* Skip header test */ - bne nrf_atfifo_space_clear_head_test_skip - - /* Load whole tail and test it !!! R2 used !!! */ - ldr r2, [r3, #__cpp(offsetof(nrf_atfifo_t, tail))] - cmp r2, r2, ror #16 - /* Return true if equal */ - it eq - moveq r0, #__cpp(true) - -nrf_atfifo_space_clear_head_test_skip - /* Store and test if success !!! R2 used temporary !!! */ - strex r2, r1, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] - cmp r2, #0 - bne nrf_atfifo_space_clear_repeat - bx lr -} - -#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) - -bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) -{ - volatile bool ret; - volatile uint32_t old_tail; - uint32_t new_tail; - uint32_t temp; - - __ASM volatile( - /* For more comments see Keil version above */ - "1: \n" - " ldrex %[old_tail], [%[p_fifo], %[offset_tail]] \n" - " uxth %[new_tail], %[old_tail] \n" - " \n" - " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" - " add %[new_tail], %[temp] \n" - " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" - " cmp %[new_tail], %[temp] \n" - " it hs \n" - " subhs %[new_tail], %[new_tail], %[temp] \n" - " \n" - " ldrh %[temp], [%[p_fifo], %[offset_head_wr]] \n" - " cmp %[new_tail], %[temp] \n" - " ittt eq \n" - " clrexeq \n" - " moveq %[ret], %[false_val] \n" - " beq.n 2f \n" - " \n" - " pkhbt %[new_tail], %[new_tail], %[old_tail] \n" - " \n" - " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" - " cmp %[temp], #0 \n" - " bne.n 1b \n" - " \n" - " mov %[ret], %[true_val] \n" - "2: \n" - : /* Output operands */ - [ret] "=r"(ret), - [temp] "=&r"(temp), - [old_tail]"=&r"(old_tail), - [new_tail]"=&r"(new_tail) - : /* Input operands */ - [p_fifo] "r"(p_fifo), - [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), - [offset_head_wr] "J"(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr)), - [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), - [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), - [true_val] "I"(true), - [false_val] "I"(false) - : /* Clobbers */ - "cc"); - - p_old_tail->tag = old_tail; - UNUSED_VARIABLE(new_tail); - UNUSED_VARIABLE(temp); - return ret; -} - - -void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) -{ - uint32_t temp; - uint32_t new_tail; - - __ASM volatile( - /* For more comments see Keil version above */ - "1: \n" - " ldrex %[new_tail], [%[p_fifo], %[offset_tail]] \n" - " pkhbt %[new_tail],%[new_tail], %[new_tail], lsl #16 \n" - " \n" - " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" - " cmp %[temp], #0 \n" - " bne.n 1b \n" - : /* Output operands */ - [temp] "=&r"(temp), - [new_tail] "=&r"(new_tail) - : /* Input operands */ - [p_fifo] "r"(p_fifo), - [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)) - : /* Clobbers */ - "cc"); - - UNUSED_VARIABLE(temp); - UNUSED_VARIABLE(new_tail); -} - - -bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) -{ - volatile bool ret; - volatile uint32_t old_head; - uint32_t new_head; - uint32_t temp; - - __ASM volatile( - /* For more comments see Keil version above */ - "1: \n" - " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" - " uxth %[new_head], %[old_head], ror #16 \n" - " \n" - " ldrh %[temp], [%[p_fifo], %[offset_tail_rd]] \n" - " cmp %[new_head], %[temp] \n" - " ittt eq \n" - " clrexeq \n" - " moveq %[ret], %[false_val] \n" - " beq.n 2f \n" - " \n" - " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" - " add %[new_head], %[temp] \n" - " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" - " cmp %[new_head], %[temp] \n" - " it hs \n" - " subhs %[new_head], %[new_head], %[temp] \n" - " \n" - " pkhbt %[new_head], %[old_head], %[new_head], lsl #16 \n" - " \n" - " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" - " cmp %[temp], #0 \n" - " bne.n 1b \n" - " \n" - " mov %[ret], %[true_val] \n" - "2: \n" - : /* Output operands */ - [ret] "=r"(ret), - [temp] "=&r"(temp), - [old_head]"=&r"(old_head), - [new_head]"=&r"(new_head) - : /* Input operands */ - [p_fifo] "r"(p_fifo), - [offset_head] "J"(offsetof(nrf_atfifo_t, head)), - [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), - [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), - [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), - [true_val] "I"(true), - [false_val] "I"(false) - : /* Clobbers */ - "cc"); - - p_old_head->tag = old_head; - UNUSED_VARIABLE(new_head); - UNUSED_VARIABLE(temp); - return ret; -} - - -void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) -{ - uint32_t temp; - uint32_t new_head; - - __ASM volatile( - /* For more comments see Keil version above */ - "1: \n" - " ldrex %[new_head], [%[p_fifo], %[offset_head]] \n" - " pkhtb %[new_head],%[new_head], %[new_head], asr #16 \n" - " \n" - " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" - " cmp %[temp], #0 \n" - " bne.n 1b \n" - : /* Output operands */ - [temp] "=&r"(temp), - [new_head] "=&r"(new_head) - : /* Input operands */ - [p_fifo] "r"(p_fifo), - [offset_head] "J"(offsetof(nrf_atfifo_t, head)) - : /* Clobbers */ - "cc"); - - UNUSED_VARIABLE(temp); - UNUSED_VARIABLE(new_head); -} - - -bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) -{ - volatile bool ret; - uint32_t old_head; /* This variable is left broken after assembly code finishes */ - uint32_t new_head; - - __ASM volatile( - "1: \n" - " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" - " ldrh %[new_head], [%[p_fifo], %[offset_tail_rd]] \n" - " cmp %[old_head], %[old_head], ror #16 \n" - " \n" - " mov %[ret], %[false_val] \n" - " \n" - " itett ne \n" - " uxthne %[old_head], %[old_head] \n" - " orreq %[new_head], %[new_head], %[new_head], lsl #16 \n" - " orrne %[new_head], %[old_head], %[new_head], lsl #16 \n" - " \n" - " bne.n 2f \n" - " \n" - " ldr %[old_head], [%[p_fifo], %[offset_tail]] \n" - " cmp %[old_head], %[old_head], ror #16 \n" - " it eq \n" - " moveq %[ret], %[true_val] \n" - " \n" - "2: \n" - " strex %[old_head], %[new_head], [%[p_fifo], %[offset_head]] \n" - " cmp %[old_head], #0 \n" - " bne.n 1b \n" - : /* Output operands */ - [ret] "=&r"(ret), - [old_head] "=&r"(old_head), - [new_head] "=&r"(new_head) - : /* Input operands */ - [p_fifo] "r"(p_fifo), - [offset_head] "J"(offsetof(nrf_atfifo_t, head)), - [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), - [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), - [true_val] "I"(true), - [false_val] "I"(false) - : /* Clobbers */ - "cc"); - - UNUSED_VARIABLE(old_head); - UNUSED_VARIABLE(new_head); - return ret; -} - -#else -#error Unsupported compiler -#endif - -#endif /* NRF_ATFIFO_INTERNAL_H__ */ +/** + * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * @brief Atomic FIFO internal file + * + * This file should be included only by nrf_atfifo internally. + * Needs nrf_atfifo.h included first. + */ +#ifndef NRF_ATFIFO_H__ +#error This is internal file. Do not include this file in your program. +#endif + +#ifndef NRF_ATFIFO_INTERNAL_H__ +#define NRF_ATFIFO_INTERNAL_H__ +#include +#include "nrf.h" +#include "app_util.h" +#include "nordic_common.h" + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error Unsupported core version +#endif + +/* + * Make sure that rd and wr pos in a tag are aligned like expected + * Changing this would require changes inside assembly code! + */ +STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, wr) == 0); +STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, rd) == 2); + +/** + * @brief Atomically reserve space for a new write. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] old_tail Tail position tag before new space is reserved. + * + * @retval true Space available. + * @retval false Memory full. + * + * @sa nrf_atfifo_wspace_close + */ +static bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail); + +/** + * @brief Atomically mark all written data available. + * + * This function marks all data available for reading. + * This marking is done by copying tail.pos.wr into tail.pos.rd. + * + * It must be called only when closing the first write. + * It cannot be called if any write access was interrupted. + * See the code below: + * @code + * if (old_tail.pos.wr == old_tail.pos.rd) + * { + * nrf_atfifo_wspace_close(my_fifo); + * return true; + * } + * return false; + * @endcode + * + * @param[in,out] p_fifo FIFO object. + * + * @sa nrf_atfifo_wspace_req + */ +static void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo); + +/** + * @brief Atomically get a part of a buffer to read data. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] old_head Head position tag before the data buffer is read. + * + * @retval true Data available for reading. + * @retval false No data in the buffer. + * + * @sa nrf_atfifo_rspace_close + */ +static bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head); + +/** + * @brief Atomically release all read data. + * + * This function marks all data that was read as free space, + * which is available for writing. + * This marking is done by copying head.pos.rd into head.pos.wr. + * + * It must be called only when closing the first read. + * It cannot be called when the current read access interrupted any other read access. + * See code below: + * @code + * if (old_head.pos.wr == old_head.pos.rd) + * { + * nrf_atfifo_rspace_close(my_fifo); + * return true; + * } + * return false; + * @endcode + * + * @param[in,out] p_fifo FIFO object. + * + * @sa nrf_atfifo_rspace_req + */ +static void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo); + +/** + * @brief Safely clear the FIFO, internal function. + * + * This function realizes the functionality required by @ref nrf_atfifo_clear. + * + * @param[in,out] p_fifo FIFO object. + * + * @retval true All the data was released. + * @retval false All the data available for releasing was released, but there is some pending transfer. + */ +static bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo); + + +/* --------------------------------------------------------------------------- + * Implementation starts here + */ + +#if defined ( __CC_ARM ) + + +__ASM bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - p_old_tail + * R2 - internal variable old_tail (saved by caller) + * R3 - internal variable new_tail (saved by caller) + * R4 - internal temporary register (saved by this function) + * R5 - not used stored to keep the stack aligned to 8 bytes + * Returned value: + * R0 (bool - 32 bits) + */ + push {r4, r5} +nrf_atfifo_wspace_req_repeat + /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + /* Extract write position !!! R3 !!! */ + uxth r3, r2 + /* Increment address with overload support !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] + add r3, r4 + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] + cmp r3, r4 + it hs + subhs r3, r3, r4 + + /* Check if FIFO would overload after making this increment !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr))] + cmp r3, r4 + ittt eq + clrexeq + moveq r0, #__cpp(false) + beq nrf_atfifo_wspace_req_exit + + /* Pack everything back !!! R3 - new tail !!! */ + /* Copy lower byte from new_tail, and higher byte is a value from the top of old_tail */ + pkhbt r3, r3, r2 + + /* Store new value clearing memory monitor !!! R4 used temporary !!! */ + strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r4, #0 + bne nrf_atfifo_wspace_req_repeat + + /* Return true */ + mov r0, #__cpp(true) +nrf_atfifo_wspace_req_exit + /* Save old tail */ + str r2, [r1] + pop {r4, r5} + bx lr +} + + +__ASM void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - internal temporary register + * R2 - new_tail + */ +nrf_atfifo_wspace_close_repeat + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + /* Copy from lower byte to higher */ + pkhbt r2, r2, r2, lsl #16 + + strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r1, #0 + bne nrf_atfifo_wspace_close_repeat + bx lr +} + + +__ASM bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - p_old_head + * R2 - internal variable old_head (saved by caller) + * R3 - internal variable new_head (saved by caller) + * R4 - internal temporary register (saved by this function) + * R5 - not used stored to keep the stack aligned to 8 bytes + * Returned value: + * R0 (bool - 32 bits) + */ + push {r4, r5} +nrf_atfifo_rspace_req_repeat + /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + /* Extract read position !!! R3 !!! */ + uxth r3, r2, ror #16 + + /* Check if we have any data !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] + cmp r3, r4 + ittt eq + clrexeq + moveq r0, #__cpp(false) + beq nrf_atfifo_rspace_req_exit + + /* Increment address with overload support !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] + add r3, r4 + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] + cmp r3, r4 + it hs + subhs r3, r3, r4 + + /* Pack everything back !!! R3 - new tail !!! */ + /* Copy lower byte from old_head, and higher byte is a value from write_pos */ + pkhbt r3, r2, r3, lsl #16 + + /* Store new value clearing memory monitor !!! R4 used temporary !!! */ + strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r4, #0 + bne nrf_atfifo_rspace_req_repeat + + /* Return true */ + mov r0, #__cpp(true) +nrf_atfifo_rspace_req_exit + /* Save old head */ + str r2, [r1] + pop {r4, r5} + bx lr +} + + +__ASM void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - internal temporary register + * R2 - new_tail + */ +nrf_atfifo_rspace_close_repeat + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + /* Copy from higher byte to lower */ + pkhtb r2, r2, r2, asr #16 + + strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r1, #0 + bne nrf_atfifo_rspace_close_repeat + bx lr +} + + +__ASM bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo as input, bool output after + * R1 - tail, rd pointer, new_head + * R2 - head_old, destroyed when creating new_head + * R3 - p_fifo - copy + */ + mov r3, r0 +nrf_atfifo_space_clear_repeat + /* Load old head in !!! R2 register !!! and read pointer of tail in !!! R1 register !!! */ + ldrex r2, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] + ldrh r1, [r3, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] + cmp r2, r2, ror #16 + /* Return false as default */ + mov r0, #__cpp(false) + /* Create new head in !!! R1 register !!! Data in !!! R2 register broken !!! */ + itett ne + uxthne r2, r2 + orreq r1, r1, r1, lsl #16 + orrne r1, r2, r1, lsl #16 + + /* Skip header test */ + bne nrf_atfifo_space_clear_head_test_skip + + /* Load whole tail and test it !!! R2 used !!! */ + ldr r2, [r3, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r2, r2, ror #16 + /* Return true if equal */ + it eq + moveq r0, #__cpp(true) + +nrf_atfifo_space_clear_head_test_skip + /* Store and test if success !!! R2 used temporary !!! */ + strex r2, r1, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r2, #0 + bne nrf_atfifo_space_clear_repeat + bx lr +} + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) +{ + volatile bool ret; + volatile uint32_t old_tail; + uint32_t new_tail; + uint32_t temp; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[old_tail], [%[p_fifo], %[offset_tail]] \n" + " uxth %[new_tail], %[old_tail] \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" + " add %[new_tail], %[temp] \n" + " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" + " cmp %[new_tail], %[temp] \n" + " it hs \n" + " subhs %[new_tail], %[new_tail], %[temp] \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_head_wr]] \n" + " cmp %[new_tail], %[temp] \n" + " ittt eq \n" + " clrexeq \n" + " moveq %[ret], %[false_val] \n" + " beq.n 2f \n" + " \n" + " pkhbt %[new_tail], %[new_tail], %[old_tail] \n" + " \n" + " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + " \n" + " mov %[ret], %[true_val] \n" + "2: \n" + : /* Output operands */ + [ret] "=r"(ret), + [temp] "=&r"(temp), + [old_tail]"=&r"(old_tail), + [new_tail]"=&r"(new_tail) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), + [offset_head_wr] "J"(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr)), + [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), + [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + p_old_tail->tag = old_tail; + UNUSED_VARIABLE(new_tail); + UNUSED_VARIABLE(temp); + return ret; +} + + +void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) +{ + uint32_t temp; + uint32_t new_tail; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " pkhbt %[new_tail],%[new_tail], %[new_tail], lsl #16 \n" + " \n" + " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [temp] "=&r"(temp), + [new_tail] "=&r"(new_tail) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(temp); + UNUSED_VARIABLE(new_tail); +} + + +bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) +{ + volatile bool ret; + volatile uint32_t old_head; + uint32_t new_head; + uint32_t temp; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" + " uxth %[new_head], %[old_head], ror #16 \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_tail_rd]] \n" + " cmp %[new_head], %[temp] \n" + " ittt eq \n" + " clrexeq \n" + " moveq %[ret], %[false_val] \n" + " beq.n 2f \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" + " add %[new_head], %[temp] \n" + " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" + " cmp %[new_head], %[temp] \n" + " it hs \n" + " subhs %[new_head], %[new_head], %[temp] \n" + " \n" + " pkhbt %[new_head], %[old_head], %[new_head], lsl #16 \n" + " \n" + " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + " \n" + " mov %[ret], %[true_val] \n" + "2: \n" + : /* Output operands */ + [ret] "=r"(ret), + [temp] "=&r"(temp), + [old_head]"=&r"(old_head), + [new_head]"=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)), + [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), + [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), + [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + p_old_head->tag = old_head; + UNUSED_VARIABLE(new_head); + UNUSED_VARIABLE(temp); + return ret; +} + + +void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) +{ + uint32_t temp; + uint32_t new_head; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[new_head], [%[p_fifo], %[offset_head]] \n" + " pkhtb %[new_head],%[new_head], %[new_head], asr #16 \n" + " \n" + " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [temp] "=&r"(temp), + [new_head] "=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(temp); + UNUSED_VARIABLE(new_head); +} + + +bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) +{ + volatile bool ret; + uint32_t old_head; /* This variable is left broken after assembly code finishes */ + uint32_t new_head; + + __ASM volatile( + "1: \n" + " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" + " ldrh %[new_head], [%[p_fifo], %[offset_tail_rd]] \n" + " cmp %[old_head], %[old_head], ror #16 \n" + " \n" + " mov %[ret], %[false_val] \n" + " \n" + " itett ne \n" + " uxthne %[old_head], %[old_head] \n" + " orreq %[new_head], %[new_head], %[new_head], lsl #16 \n" + " orrne %[new_head], %[old_head], %[new_head], lsl #16 \n" + " \n" + " bne.n 2f \n" + " \n" + " ldr %[old_head], [%[p_fifo], %[offset_tail]] \n" + " cmp %[old_head], %[old_head], ror #16 \n" + " it eq \n" + " moveq %[ret], %[true_val] \n" + " \n" + "2: \n" + " strex %[old_head], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[old_head], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [ret] "=&r"(ret), + [old_head] "=&r"(old_head), + [new_head] "=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), + [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(old_head); + UNUSED_VARIABLE(new_head); + return ret; +} + +#else +#error Unsupported compiler +#endif + +#endif /* NRF_ATFIFO_INTERNAL_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic.c b/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic.c index a4fdc23f9..ce091cae9 100644 --- a/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic.c +++ b/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic.c @@ -1,449 +1,449 @@ -/** - * Copyright (c) 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "nrf_atomic.h" - -#ifndef NRF_ATOMIC_USE_BUILD_IN -#if (defined(__GNUC__) && defined(WIN32)) - #define NRF_ATOMIC_USE_BUILD_IN 1 -#else - #define NRF_ATOMIC_USE_BUILD_IN 0 -#endif -#endif // NRF_ATOMIC_USE_BUILD_IN - -#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) -#define STREX_LDREX_PRESENT -#else -#include "app_util_platform.h" -#endif - - -#if (NRF_ATOMIC_USE_BUILD_IN == 0) && defined(STREX_LDREX_PRESENT) -#include "nrf_atomic_internal.h" -#endif - -uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_exchange_n(p_data, value, __ATOMIC_SEQ_CST); - -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); - - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return old_val; -#else - CRITICAL_REGION_ENTER(); - uint32_t old_val = *p_data; - *p_data = value; - CRITICAL_REGION_EXIT(); - return old_val; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - __atomic_store_n(p_data, value, __ATOMIC_SEQ_CST); - return value; -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); - - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return new_val; -#else - CRITICAL_REGION_ENTER(); - *p_data = value; - CRITICAL_REGION_EXIT(); - return value; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_fetch_or(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return old_val; -#else - CRITICAL_REGION_ENTER(); - uint32_t old_val = *p_data; - *p_data |= value; - CRITICAL_REGION_EXIT(); - return old_val; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_or_fetch(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return new_val; -#else - CRITICAL_REGION_ENTER(); - *p_data |= value; - uint32_t new_value = *p_data; - CRITICAL_REGION_EXIT(); - return new_value; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_fetch_and(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return old_val; -#else - CRITICAL_REGION_ENTER(); - uint32_t old_val = *p_data; - *p_data &= value; - CRITICAL_REGION_EXIT(); - return old_val; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_and_fetch(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return new_val; -#else - CRITICAL_REGION_ENTER(); - *p_data &= value; - uint32_t new_value = *p_data; - CRITICAL_REGION_EXIT(); - return new_value; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_fetch_xor(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return old_val; -#else - CRITICAL_REGION_ENTER(); - uint32_t old_val = *p_data; - *p_data ^= value; - CRITICAL_REGION_EXIT(); - return old_val; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_xor_fetch(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return new_val; -#else - CRITICAL_REGION_ENTER(); - *p_data ^= value; - uint32_t new_value = *p_data; - CRITICAL_REGION_EXIT(); - return new_value; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_fetch_add(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return old_val; -#else - CRITICAL_REGION_ENTER(); - uint32_t old_val = *p_data; - *p_data += value; - CRITICAL_REGION_EXIT(); - return old_val; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_add_fetch(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return new_val; -#else - CRITICAL_REGION_ENTER(); - *p_data += value; - uint32_t new_value = *p_data; - CRITICAL_REGION_EXIT(); - return new_value; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_fetch_sub(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return old_val; -#else - CRITICAL_REGION_ENTER(); - uint32_t old_val = *p_data; - *p_data -= value; - CRITICAL_REGION_EXIT(); - return old_val; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_sub_fetch(p_data, value, __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return new_val; -#else - CRITICAL_REGION_ENTER(); - *p_data -= value; - uint32_t new_value = *p_data; - CRITICAL_REGION_EXIT(); - return new_value; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, - uint32_t * p_expected, - uint32_t desired) -{ -#if NRF_ATOMIC_USE_BUILD_IN - return __atomic_compare_exchange(p_data, - p_expected, - &desired, - 1, - __ATOMIC_SEQ_CST, - __ATOMIC_SEQ_CST); -#elif defined(STREX_LDREX_PRESENT) - return nrf_atomic_internal_cmp_exch(p_data, p_expected, desired); -#else - bool ret; - CRITICAL_REGION_ENTER(); - if (*p_data == *p_expected) - { - *p_data = desired; - ret = true; - } - else - { - *p_expected = *p_data; - ret = false; - } - CRITICAL_REGION_EXIT(); - return ret; -#endif -} - -uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - uint32_t expected = *p_data; - uint32_t new_val; - bool success; - - do - { - if (expected >= value) - { - new_val = expected - value; - } - else - { - new_val = expected; - } - success = __atomic_compare_exchange(p_data, - &expected, - &new_val, - 1, - __ATOMIC_SEQ_CST, - __ATOMIC_SEQ_CST); - } while(!success); - return expected; -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return old_val; -#else - CRITICAL_REGION_ENTER(); - uint32_t old_val = *p_data; - *p_data -= value; - CRITICAL_REGION_EXIT(); - return old_val; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) -{ -#if NRF_ATOMIC_USE_BUILD_IN - uint32_t expected = *p_data; - uint32_t new_val; - bool success; - - do - { - if (expected >= value) - { - new_val = expected - value; - } - else - { - new_val = expected; - } - success = __atomic_compare_exchange(p_data, - &expected, - &new_val, - 1, - __ATOMIC_SEQ_CST, - __ATOMIC_SEQ_CST); - } while(!success); - return new_val; -#elif defined(STREX_LDREX_PRESENT) - uint32_t old_val; - uint32_t new_val; - - NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); - UNUSED_PARAMETER(old_val); - UNUSED_PARAMETER(new_val); - return new_val; -#else - CRITICAL_REGION_ENTER(); - *p_data -= value; - uint32_t new_value = *p_data; - CRITICAL_REGION_EXIT(); - return new_value; -#endif //NRF_ATOMIC_USE_BUILD_IN -} - -uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data) -{ - return nrf_atomic_u32_fetch_or(p_data, 1); -} - -uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data) -{ - return nrf_atomic_u32_or(p_data, 1); -} - -uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data) -{ - return nrf_atomic_u32_fetch_and(p_data, 0); -} - -uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data) -{ - return nrf_atomic_u32_and(p_data, 0); -} - +/** + * Copyright (c) 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_atomic.h" + +#ifndef NRF_ATOMIC_USE_BUILD_IN +#if (defined(__GNUC__) && defined(WIN32)) + #define NRF_ATOMIC_USE_BUILD_IN 1 +#else + #define NRF_ATOMIC_USE_BUILD_IN 0 +#endif +#endif // NRF_ATOMIC_USE_BUILD_IN + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) +#define STREX_LDREX_PRESENT +#else +#include "app_util_platform.h" +#endif + + +#if (NRF_ATOMIC_USE_BUILD_IN == 0) && defined(STREX_LDREX_PRESENT) +#include "nrf_atomic_internal.h" +#endif + +uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_exchange_n(p_data, value, __ATOMIC_SEQ_CST); + +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data = value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + __atomic_store_n(p_data, value, __ATOMIC_SEQ_CST); + return value; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data = value; + CRITICAL_REGION_EXIT(); + return value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_or(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data |= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_or_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data |= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_and(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data &= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_and_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data &= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_xor(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data ^= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_xor_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data ^= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_add(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data += value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_add_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data += value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_sub(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_sub_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t desired) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_compare_exchange(p_data, + p_expected, + &desired, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + return nrf_atomic_internal_cmp_exch(p_data, p_expected, desired); +#else + bool ret; + CRITICAL_REGION_ENTER(); + if (*p_data == *p_expected) + { + *p_data = desired; + ret = true; + } + else + { + *p_expected = *p_data; + ret = false; + } + CRITICAL_REGION_EXIT(); + return ret; +#endif +} + +uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + uint32_t expected = *p_data; + uint32_t new_val; + bool success; + + do + { + if (expected >= value) + { + new_val = expected - value; + } + else + { + new_val = expected; + } + success = __atomic_compare_exchange(p_data, + &expected, + &new_val, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + } while(!success); + return expected; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + uint32_t expected = *p_data; + uint32_t new_val; + bool success; + + do + { + if (expected >= value) + { + new_val = expected - value; + } + else + { + new_val = expected; + } + success = __atomic_compare_exchange(p_data, + &expected, + &new_val, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + } while(!success); + return new_val; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_or(p_data, 1); +} + +uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_or(p_data, 1); +} + +uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_and(p_data, 0); +} + +uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_and(p_data, 0); +} + diff --git a/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic.h b/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic.h index c2c905c5c..7493197a5 100644 --- a/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic.h +++ b/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic.h @@ -1,274 +1,274 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup nrf_atomic Atomic operations API - * @ingroup app_common - * @{ - * - * @brief @tagAPI52 This module implements C11 stdatomic.h simplified API. - At this point only Cortex-M3/M4 cores are supported (LDREX/STREX instructions). - * Atomic types are limited to @ref nrf_atomic_u32_t and @ref nrf_atomic_flag_t. - */ - -#ifndef NRF_ATOMIC_H__ -#define NRF_ATOMIC_H__ - -#include "sdk_common.h" - -/** - * @brief Atomic 32 bit unsigned type - * */ -typedef volatile uint32_t nrf_atomic_u32_t; - -/** - * @brief Atomic 1 bit flag type (technically 32 bit) - * */ -typedef volatile uint32_t nrf_atomic_flag_t; - - - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Stores value to an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value to store - * - * @return Old value stored into atomic object - * */ -uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Stores value to an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value to store - * - * @return New value stored into atomic object - * */ -uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Logical OR operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand OR operation - * - * @return Old value stored into atomic object - * */ -uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Logical OR operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand OR operation - * - * @return New value stored into atomic object - * */ -uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Logical AND operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand AND operation - * - * @return Old value stored into atomic object - * */ -uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Logical AND operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand AND operation - * - * @return New value stored into atomic object - * */ -uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Logical XOR operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand XOR operation - * - * @return Old value stored into atomic object - * */ -uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Logical XOR operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand XOR operation - * - * @return New value stored into atomic object - * */ -uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Arithmetic ADD operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand ADD operation - * - * @return Old value stored into atomic object - * */ -uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Arithmetic ADD operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand ADD operation - * - * @return New value stored into atomic object - * */ -uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Arithmetic SUB operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand SUB operation - * - * @return Old value stored into atomic object - * */ -uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Arithmetic SUB operation on an atomic object - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand SUB operation - * - * @return New value stored into atomic object - * */ -uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief If value at pointer is equal to expected value, changes value at pointer to desired - * - * Atomically compares the value pointed to by p_data with the value pointed to by p_expected, - * and if those are equal, replaces the former with desired. Otherwise, loads the actual value - * pointed to by p_data into *p_expected. - * - * @param p_data Atomic memory pointer to test and modify. - * @param p_expected Pointer to test value. - * @param desired Value to be stored to atomic memory. - * - * @retval true *p_data was equal to *p_expected - * @retval false *p_data was not equal to *p_expected - */ -bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, - uint32_t * p_expected, - uint32_t desired); - -/** - * @brief Arithmetic SUB operation on an atomic object performed if object >= value. - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand SUB operation - * - * @return Old value stored into atomic object - * */ -uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); - -/** - * @brief Arithmetic SUB operation on an atomic object performed if object >= value. - * - * @param[in] p_data Atomic memory pointer - * @param[in] value Value of second operand SUB operation - * - * @return New value stored into atomic object - * */ -uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); - -/**************************************************************************************************/ - -/** - * @brief Logic one bit flag set operation on an atomic object - * - * @param[in] p_data Atomic flag memory pointer - * - * @return Old flag value - * */ -uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data); - -/** - * @brief Logic one bit flag set operation on an atomic object - * - * @param[in] p_data Atomic flag memory pointer - * - * @return New flag value - * */ -uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data); - -/** - * @brief Logic one bit flag clear operation on an atomic object - * - * @param[in] p_data Atomic flag memory pointer - * - * @return Old flag value - * */ -uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data); - -/** - * @brief Logic one bit flag clear operation on an atomic object - * - * @param[in] p_data Atomic flag memory pointer - * - * @return New flag value - * */ -uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data); - -#ifdef __cplusplus -} -#endif - -#endif /* NRF_ATOMIC_H__ */ - -/** @} */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_atomic Atomic operations API + * @ingroup app_common + * @{ + * + * @brief @tagAPI52 This module implements C11 stdatomic.h simplified API. + At this point only Cortex-M3/M4 cores are supported (LDREX/STREX instructions). + * Atomic types are limited to @ref nrf_atomic_u32_t and @ref nrf_atomic_flag_t. + */ + +#ifndef NRF_ATOMIC_H__ +#define NRF_ATOMIC_H__ + +#include "sdk_common.h" + +/** + * @brief Atomic 32 bit unsigned type + * */ +typedef volatile uint32_t nrf_atomic_u32_t; + +/** + * @brief Atomic 1 bit flag type (technically 32 bit) + * */ +typedef volatile uint32_t nrf_atomic_flag_t; + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief If value at pointer is equal to expected value, changes value at pointer to desired + * + * Atomically compares the value pointed to by p_data with the value pointed to by p_expected, + * and if those are equal, replaces the former with desired. Otherwise, loads the actual value + * pointed to by p_data into *p_expected. + * + * @param p_data Atomic memory pointer to test and modify. + * @param p_expected Pointer to test value. + * @param desired Value to be stored to atomic memory. + * + * @retval true *p_data was equal to *p_expected + * @retval false *p_data was not equal to *p_expected + */ +bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t desired); + +/** + * @brief Arithmetic SUB operation on an atomic object performed if object >= value. + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object performed if object >= value. + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); + +/**************************************************************************************************/ + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data); + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_H__ */ + +/** @} */ diff --git a/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic_internal.h b/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic_internal.h index 5df87aa04..7ed7bb18e 100644 --- a/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic_internal.h +++ b/third_party/NordicSemiconductor/libraries/atomic/nrf_atomic_internal.h @@ -1,343 +1,343 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef NRF_ATOMIC_INTERNAL_H__ -#define NRF_ATOMIC_INTERNAL_H__ - -#include "sdk_common.h" -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * - * @defgroup nrf_atomic_internal Atomic operations internals - * @ingroup nrf_atomic - * @{ - * - */ - -/* Only Cortex M cores > 3 support LDREX/STREX instructions*/ -#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 -#error "Unsupported core version" -#endif - -#if defined ( __CC_ARM ) -static __asm uint32_t nrf_atomic_internal_mov(nrf_atomic_u32_t * p_ptr, - uint32_t value, - uint32_t * p_new) -{ - /* The base standard provides for passing arguments in core registers (r0-r3) and on the stack. - * Registers r4 and r5 have to be saved on stack. Note that only even number of register push are - * allowed. This is a requirement of the Procedure Call Standard for the ARM Architecture [AAPCS]. - * */ - push {r4, r5} - mov r4, r0 - -loop_mov - ldrex r0, [r4] - mov r5, r1 - strex r3, r5, [r4] - cmp r3, #0 - bne loop_mov - - str r5, [r2] - pop {r4, r5} - bx lr -} - - -static __asm uint32_t nrf_atomic_internal_orr(nrf_atomic_u32_t * p_ptr, - uint32_t value, - uint32_t * p_new) -{ - push {r4, r5} - mov r4, r0 - -loop_orr - ldrex r0, [r4] - orr r5, r0, r1 - strex r3, r5, [r4] - cmp r3, #0 - bne loop_orr - - str r5, [r2] - pop {r4, r5} - bx lr -} - -static __asm uint32_t nrf_atomic_internal_and(nrf_atomic_u32_t * p_ptr, - uint32_t value, - uint32_t * p_new) -{ - push {r4, r5} - mov r4, r0 - -loop_and - ldrex r0, [r4] - and r5, r0, r1 - strex r3, r5, [r4] - cmp r3, #0 - bne loop_and - - str r5, [r2] - pop {r4, r5} - bx lr -} - -static __asm uint32_t nrf_atomic_internal_eor(nrf_atomic_u32_t * p_ptr, - uint32_t value, - uint32_t * p_new) -{ - push {r4, r5} - mov r4, r0 - -loop_eor - ldrex r0, [r4] - eor r5, r0, r1 - strex r3, r5, [r4] - cmp r3, #0 - bne loop_eor - - str r5, [r2] - pop {r4, r5} - bx lr -} - -static __asm uint32_t nrf_atomic_internal_add(nrf_atomic_u32_t * p_ptr, - uint32_t value, - uint32_t * p_new) -{ - push {r4, r5} - mov r4, r0 - -loop_add - ldrex r0, [r4] - add r5, r0, r1 - strex r3, r5, [r4] - cmp r3, #0 - bne loop_add - - str r5, [r2] - pop {r4, r5} - bx lr -} - -static __asm uint32_t nrf_atomic_internal_sub(nrf_atomic_u32_t * p_ptr, - uint32_t value, - uint32_t * p_new) -{ - push {r4, r5} - mov r4, r0 - -loop_sub - ldrex r0, [r4] - sub r5, r0, r1 - strex r3, r5, [r4] - cmp r3, #0 - bne loop_sub - - str r5, [r2] - pop {r4, r5} - bx lr -} - -static __asm bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, - uint32_t * p_expected, - uint32_t value) -{ -#define RET_REG r0 -#define P_EXPC r1 -#define VALUE r2 -#define STR_RES r3 -#define P_DATA r4 -#define EXPC_VAL r5 -#define ACT_VAL r6 - - push {r4-r6} - mov P_DATA, r0 - mov RET_REG, #0 - -loop_cmp_exch - ldrex ACT_VAL, [P_DATA] - ldr EXPC_VAL, [P_EXPC] - cmp ACT_VAL, EXPC_VAL - ittee eq - strexeq STR_RES, VALUE, [P_DATA] - moveq RET_REG, #1 - strexne STR_RES, ACT_VAL, [P_DATA] - strne ACT_VAL, [P_EXPC] - cmp STR_RES, #0 - itt ne - movne RET_REG, #0 - bne loop_cmp_exch - - pop {r4-r6} - bx lr - -#undef RET_REG -#undef P_EXPC -#undef VALUE -#undef STR_RES -#undef P_DATA -#undef EXPC_VAL -#undef ACT_VAL -} - -static __asm uint32_t nrf_atomic_internal_sub_hs(nrf_atomic_u32_t * p_ptr, - uint32_t value, - uint32_t * p_new) -{ - push {r4, r5} - mov r4, r0 - -loop_sub_ge - ldrex r0, [r4] - cmp r0, r1 - ite hs - subhs r5, r0, r1 - movlo r5, r0 - strex r3, r5, [r4] - cmp r3, #0 - bne loop_sub_ge - - str r5, [r2] - pop {r4, r5} - bx lr -} - - -#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ - old_val = nrf_atomic_internal_##asm_op(ptr, value, &new_val) - -#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) - -/** - * @brief Atomic operation generic macro - * @param[in] asm_op operation: mov, orr, and, eor, add, sub - * @param[out] old_val atomic object output (uint32_t), value before operation - * @param[out] new_val atomic object output (uint32_t), value after operation - * @param[in] value atomic operation operand - * */ -#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ -{ \ - uint32_t str_res; \ - __ASM volatile( \ - "1: ldrex %["#old_val"], [%["#ptr"]]\n" \ - NRF_ATOMIC_OP_##asm_op(new_val, old_val, value) \ - " strex %[str_res], %["#new_val"], [%["#ptr"]]\n" \ - " teq %[str_res], #0\n" \ - " bne.n 1b" \ - : \ - [old_val]"=&r" (old_val), \ - [new_val]"=&r" (new_val), \ - [str_res]"=&r" (str_res) \ - : \ - [ptr]"r" (ptr), \ - [value]"r" (value) \ - : "cc"); \ - UNUSED_PARAMETER(str_res); \ -} - -#define NRF_ATOMIC_OP_mov(new_val, old_val, value) "mov %["#new_val"], %["#value"]\n" -#define NRF_ATOMIC_OP_orr(new_val, old_val, value) "orr %["#new_val"], %["#old_val"], %["#value"]\n" -#define NRF_ATOMIC_OP_and(new_val, old_val, value) "and %["#new_val"], %["#old_val"], %["#value"]\n" -#define NRF_ATOMIC_OP_eor(new_val, old_val, value) "eor %["#new_val"], %["#old_val"], %["#value"]\n" -#define NRF_ATOMIC_OP_add(new_val, old_val, value) "add %["#new_val"], %["#old_val"], %["#value"]\n" -#define NRF_ATOMIC_OP_sub(new_val, old_val, value) "sub %["#new_val"], %["#old_val"], %["#value"]\n" -#define NRF_ATOMIC_OP_sub_hs(new_val, old_val, value) \ - "cmp %["#old_val"], %["#value"]\n " \ - "ite hs\n" \ - "subhs %["#new_val"], %["#old_val"], %["#value"]\n" \ - "movlo %["#new_val"], %["#old_val"]\n" - -static inline bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, - uint32_t * p_expected, - uint32_t value) -{ - bool res = false; - uint32_t str_res = 0; - uint32_t act_val = 0; - uint32_t exp_val = 0; - UNUSED_VARIABLE(str_res); - UNUSED_VARIABLE(act_val); - UNUSED_VARIABLE(exp_val); - __ASM volatile( - "1: ldrex %[act_val], [%[ptr]]\n" - " ldr %[exp_val], [%[expc]]\n" - " cmp %[act_val], %[exp_val]\n" - " ittee eq\n" - " strexeq %[str_res], %[value], [%[ptr]]\n" - " moveq %[res], #1\n" - " strexne %[str_res], %[act_val], [%[ptr]]\n" - " strne %[act_val], [%[expc]]\n" - " cmp %[str_res], #0\n" - " itt ne\n" - " movne %[res], #0\n" - " bne.n 1b" - : - [res] "=&r" (res), - [exp_val] "=&r" (exp_val), - [act_val] "=&r" (act_val), - [str_res] "=&r" (str_res) - : - "0" (res), - "1" (exp_val), - "2" (act_val), - [expc] "r" (p_expected), - [ptr] "r" (p_data), - [value] "r" (value) - : "cc"); - return res; -} - -#else -#error "Unsupported compiler" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* NRF_ATOMIC_INTERNAL_H__ */ - -/** @} */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_ATOMIC_INTERNAL_H__ +#define NRF_ATOMIC_INTERNAL_H__ + +#include "sdk_common.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @defgroup nrf_atomic_internal Atomic operations internals + * @ingroup nrf_atomic + * @{ + * + */ + +/* Only Cortex M cores > 3 support LDREX/STREX instructions*/ +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error "Unsupported core version" +#endif + +#if defined ( __CC_ARM ) +static __asm uint32_t nrf_atomic_internal_mov(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + /* The base standard provides for passing arguments in core registers (r0-r3) and on the stack. + * Registers r4 and r5 have to be saved on stack. Note that only even number of register push are + * allowed. This is a requirement of the Procedure Call Standard for the ARM Architecture [AAPCS]. + * */ + push {r4, r5} + mov r4, r0 + +loop_mov + ldrex r0, [r4] + mov r5, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_mov + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +static __asm uint32_t nrf_atomic_internal_orr(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_orr + ldrex r0, [r4] + orr r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_orr + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_and(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_and + ldrex r0, [r4] + and r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_and + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_eor(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_eor + ldrex r0, [r4] + eor r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_eor + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_add(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_add + ldrex r0, [r4] + add r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_add + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_sub(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub + ldrex r0, [r4] + sub r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t value) +{ +#define RET_REG r0 +#define P_EXPC r1 +#define VALUE r2 +#define STR_RES r3 +#define P_DATA r4 +#define EXPC_VAL r5 +#define ACT_VAL r6 + + push {r4-r6} + mov P_DATA, r0 + mov RET_REG, #0 + +loop_cmp_exch + ldrex ACT_VAL, [P_DATA] + ldr EXPC_VAL, [P_EXPC] + cmp ACT_VAL, EXPC_VAL + ittee eq + strexeq STR_RES, VALUE, [P_DATA] + moveq RET_REG, #1 + strexne STR_RES, ACT_VAL, [P_DATA] + strne ACT_VAL, [P_EXPC] + cmp STR_RES, #0 + itt ne + movne RET_REG, #0 + bne loop_cmp_exch + + pop {r4-r6} + bx lr + +#undef RET_REG +#undef P_EXPC +#undef VALUE +#undef STR_RES +#undef P_DATA +#undef EXPC_VAL +#undef ACT_VAL +} + +static __asm uint32_t nrf_atomic_internal_sub_hs(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub_ge + ldrex r0, [r4] + cmp r0, r1 + ite hs + subhs r5, r0, r1 + movlo r5, r0 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub_ge + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ + old_val = nrf_atomic_internal_##asm_op(ptr, value, &new_val) + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +/** + * @brief Atomic operation generic macro + * @param[in] asm_op operation: mov, orr, and, eor, add, sub + * @param[out] old_val atomic object output (uint32_t), value before operation + * @param[out] new_val atomic object output (uint32_t), value after operation + * @param[in] value atomic operation operand + * */ +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ +{ \ + uint32_t str_res; \ + __ASM volatile( \ + "1: ldrex %["#old_val"], [%["#ptr"]]\n" \ + NRF_ATOMIC_OP_##asm_op(new_val, old_val, value) \ + " strex %[str_res], %["#new_val"], [%["#ptr"]]\n" \ + " teq %[str_res], #0\n" \ + " bne.n 1b" \ + : \ + [old_val]"=&r" (old_val), \ + [new_val]"=&r" (new_val), \ + [str_res]"=&r" (str_res) \ + : \ + [ptr]"r" (ptr), \ + [value]"r" (value) \ + : "cc"); \ + UNUSED_PARAMETER(str_res); \ +} + +#define NRF_ATOMIC_OP_mov(new_val, old_val, value) "mov %["#new_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_orr(new_val, old_val, value) "orr %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_and(new_val, old_val, value) "and %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_eor(new_val, old_val, value) "eor %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_add(new_val, old_val, value) "add %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub(new_val, old_val, value) "sub %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub_hs(new_val, old_val, value) \ + "cmp %["#old_val"], %["#value"]\n " \ + "ite hs\n" \ + "subhs %["#new_val"], %["#old_val"], %["#value"]\n" \ + "movlo %["#new_val"], %["#old_val"]\n" + +static inline bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t value) +{ + bool res = false; + uint32_t str_res = 0; + uint32_t act_val = 0; + uint32_t exp_val = 0; + UNUSED_VARIABLE(str_res); + UNUSED_VARIABLE(act_val); + UNUSED_VARIABLE(exp_val); + __ASM volatile( + "1: ldrex %[act_val], [%[ptr]]\n" + " ldr %[exp_val], [%[expc]]\n" + " cmp %[act_val], %[exp_val]\n" + " ittee eq\n" + " strexeq %[str_res], %[value], [%[ptr]]\n" + " moveq %[res], #1\n" + " strexne %[str_res], %[act_val], [%[ptr]]\n" + " strne %[act_val], [%[expc]]\n" + " cmp %[str_res], #0\n" + " itt ne\n" + " movne %[res], #0\n" + " bne.n 1b" + : + [res] "=&r" (res), + [exp_val] "=&r" (exp_val), + [act_val] "=&r" (act_val), + [str_res] "=&r" (str_res) + : + "0" (res), + "1" (exp_val), + "2" (act_val), + [expc] "r" (p_expected), + [ptr] "r" (p_data), + [value] "r" (value) + : "cc"); + return res; +} + +#else +#error "Unsupported compiler" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_INTERNAL_H__ */ + +/** @} */ diff --git a/third_party/NordicSemiconductor/libraries/delay/nrf_delay.h b/third_party/NordicSemiconductor/libraries/delay/nrf_delay.h index 89639f82b..1b58a587b 100644 --- a/third_party/NordicSemiconductor/libraries/delay/nrf_delay.h +++ b/third_party/NordicSemiconductor/libraries/delay/nrf_delay.h @@ -1,80 +1,80 @@ -/** - * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _NRF_DELAY_H -#define _NRF_DELAY_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Function for delaying execution for a number of microseconds. - * - * @param us_time Number of microseconds to wait. - */ -#define nrf_delay_us(us_time) NRFX_DELAY_US(us_time) - - -/** - * @brief Function for delaying execution for a number of milliseconds. - * - * @param ms_time Number of milliseconds to wait. - */ - -__STATIC_INLINE void nrf_delay_ms(uint32_t ms_time) -{ - if (ms_time == 0) - { - return; - } - - do { - nrf_delay_us(1000); - } while (--ms_time); -} - -#ifdef __cplusplus -} -#endif - -#endif +/** + * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _NRF_DELAY_H +#define _NRF_DELAY_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for delaying execution for a number of microseconds. + * + * @param us_time Number of microseconds to wait. + */ +#define nrf_delay_us(us_time) NRFX_DELAY_US(us_time) + + +/** + * @brief Function for delaying execution for a number of milliseconds. + * + * @param ms_time Number of milliseconds to wait. + */ + +__STATIC_INLINE void nrf_delay_ms(uint32_t ms_time) +{ + if (ms_time == 0) + { + return; + } + + do { + nrf_delay_us(1000); + } while (--ms_time); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd.c b/third_party/NordicSemiconductor/libraries/usb/app_usbd.c index 34dfe94a2..998cb7b1f 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd.c +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd.c @@ -1,1919 +1,1919 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(APP_USBD) - -#include "app_usbd.h" -#include "app_usbd_core.h" -#include "app_usbd_request.h" -#include "nrf_power.h" -#include "nrf_drv_clock.h" -#include "nrf_drv_power.h" -#if APP_USBD_CONFIG_EVENT_QUEUE_ENABLE -#include "nrf_atfifo.h" -#include "nrf_atomic.h" -#endif - -#define NRF_LOG_MODULE_NAME app_usbd - -#if APP_USBD_CONFIG_LOG_ENABLED -#define NRF_LOG_LEVEL APP_USBD_CONFIG_LOG_LEVEL -#define NRF_LOG_INFO_COLOR APP_USBD_CONFIG_INFO_COLOR -#define NRF_LOG_DEBUG_COLOR APP_USBD_CONFIG_DEBUG_COLOR -#else //APP_USBD_CONFIG_LOG_ENABLED -#define NRF_LOG_LEVEL 0 -#endif //APP_USBD_CONFIG_LOG_ENABLED -#include "nrf_log.h" -NRF_LOG_MODULE_REGISTER(); - - -/* Base variables tests */ - -/* Check event of app_usbd_event_type_t enumerator */ -STATIC_ASSERT((int32_t)APP_USBD_EVT_FIRST_POWER == (int32_t)NRF_DRV_USBD_EVT_CNT); -STATIC_ASSERT(sizeof(app_usbd_event_type_t) == sizeof(nrf_drv_usbd_event_type_t)); - -STATIC_ASSERT(sizeof(app_usbd_descriptor_header_t) == 2); -STATIC_ASSERT(sizeof(app_usbd_descriptor_device_t) == 18); -STATIC_ASSERT(sizeof(app_usbd_descriptor_configuration_t) == 9); -STATIC_ASSERT(sizeof(app_usbd_descriptor_iface_t) == 9); -STATIC_ASSERT(sizeof(app_usbd_descriptor_ep_t) == 7); -STATIC_ASSERT(sizeof(app_usbd_descriptor_iad_t) == 8); - -STATIC_ASSERT(sizeof(app_usbd_setup_t) == sizeof(nrf_drv_usbd_setup_t)); - -/** - * @internal - * @defgroup app_usbd_internals USBD library internals - * @ingroup app_usbd - * - * Internal variables, auxiliary macros and functions of USBD library. - * @{ - */ - -#if (APP_USBD_PROVIDE_SOF_TIMESTAMP) || defined(__SDK_DOXYGEN__) -/** - * @brief The last received frame number. - */ -static uint16_t m_last_frame; -#endif - -/** - * @brief Variable type for endpoint configuration. - * - * Each endpoint would have assigned this type of configuration structure. - */ -typedef struct -{ - /** - * @brief The class instance. - * - * The pointer to the class instance that is connected to the endpoint. - */ - app_usbd_class_inst_t const * p_cinst; - - /** - * @brief Endpoint event handler. - * - * Event handler for the endpoint. - * It is set to event handler for the class instance during connection by default, - * but it can be then updated for as a reaction for @ref APP_USBD_EVT_ATTACHED event. - * This way we can speed up the interpretation of endpoint related events. - */ - app_usbd_ep_event_handler_t event_handler; -}app_usbd_ep_conf_t; - - -/** - * @brief Internal event with SOF counter. - */ -typedef struct -{ - app_usbd_internal_evt_t evt; //!< Internal event type - -#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) \ - || defined(__SDK_DOXYGEN__) - uint16_t sof_cnt; //!< Number of the SOF events that appears before current event - uint16_t start_frame; //!< Number of the SOF frame that starts this event -#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - -} app_usbd_internal_queue_evt_t; - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) -/** - * @brief Event queue. - * - * The queue with events to be processed. - */ -NRF_ATFIFO_DEF(m_event_queue, app_usbd_internal_queue_evt_t, APP_USBD_CONFIG_EVENT_QUEUE_SIZE); - -#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) \ - || defined(__SDK_DOXYGEN__) - -/** @brief SOF events counter */ -static nrf_atomic_u32_t m_sof_events_cnt; - -/** @brief SOF Frame counter */ -static uint16_t m_event_frame; - -/* Limit of SOF events stacked until warning message. */ -#define APP_USBD_SOF_WARNING_LIMIT 500 -#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - // || defined(__SDK_DOXYGEN__) - -#endif - -/** - * @brief Instances connected with IN endpoints. - * - * Array of instance pointers connected with every IN endpoint. - * @sa m_epout_instances - */ -static app_usbd_ep_conf_t m_epin_conf[NRF_USBD_EPIN_CNT]; - -/** - * @brief Instances connected with OUT endpoints. - * - * Array of instance pointers connected with every OUT endpoint. - * @sa m_epin_instances - */ -static app_usbd_ep_conf_t m_epout_conf[NRF_USBD_EPIN_CNT]; - -/** - * @brief Beginning of classes list. - * - * All enabled in current configuration instances are connected into - * a single linked list chain. - * This variable points to first element. - * Core class instance (connected to endpoint 0) is not listed here. - */ -static app_usbd_class_inst_t const * m_p_first_cinst; - -/** - * @brief Classes list that requires SOF events. - * - * Pointer to first class that requires SOF events. - */ -static app_usbd_class_inst_t const * m_p_first_sof_cinst; - -/** - * @brief Classes list that require SOF events in interrupt. - * - * Pointer to first class that requires SOF events in interrupt. - */ -static app_usbd_class_inst_t const * m_p_first_sof_interrupt_cinst; - -/** - * @brief Default configuration (when NULL is passed to @ref app_usbd_init). - */ -static const app_usbd_config_t m_default_conf = { -#if (!(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)) || defined(__SDK_DOXYGEN__) - .ev_handler = app_usbd_event_execute, -#endif -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) - .ev_isr_handler = NULL, -#endif - .ev_state_proc = NULL, - .enable_sof = false -}; - -/** - * @brief SUSPEND state machine states. - * - * The enumeration of internal SUSPEND state machine states. - */ -typedef enum -{ - SUSTATE_STOPPED, /**< The USB driver was not started */ - SUSTATE_STARTED, /**< The USB driver was started - waiting for USB RESET */ - SUSTATE_ACTIVE, /**< Active state */ - SUSTATE_SUSPENDING, /**< Suspending - waiting for the user to acknowledge */ - SUSTATE_SUSPEND, /**< Suspended */ - SUSTATE_RESUMING, /**< Resuming - waiting for clock */ - SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ, /**< Waking up - waiting for clock and WUREQ from driver */ - SUSTATE_WAKINGUP_WAITING_HFCLK, /**< Waking up - waiting for HFCLK (WUREQ detected) */ - SUSTATE_WAKINGUP_WAITING_WREQ, /**< Waking up - waiting for WREQ (HFCLK active) */ -}app_usbd_sustate_t; - -/** - * @brief Current suspend state. - * - * The state of the suspend state machine. - */ -static app_usbd_sustate_t m_sustate; - -/** - * @brief Remote wake-up register/unregister. - * - * Counter incremented when appended instance required remote wake-up functionality. - * It should be decremented when the class is removed. - * When this counter is not zero, remote wake-up functionality is activated inside core. - */ -static uint8_t m_rwu_registered_counter; - -/** - * @brief Current configuration. - */ -static app_usbd_config_t m_current_conf; - -/** - * @brief Class interface call: event handler - * - * @ref app_usbd_class_interface_t::event_handler - * - * @param[in] p_cinst Class instance. - * @param[in] p_event Event passed to class instance. - * - * @return Standard error code @ref ret_code_t - * @retval NRF_SUCCESS event handled successfully. - * @retval NRF_ERROR_NOT_SUPPORTED unsupported event. - * */ -static inline ret_code_t class_event_handler(app_usbd_class_inst_t const * const p_cinst, - app_usbd_complex_evt_t const * const p_event) -{ - ASSERT(p_cinst != NULL); - ASSERT(p_cinst->p_class_methods != NULL); - ASSERT(p_cinst->p_class_methods->event_handler != NULL); - return p_cinst->p_class_methods->event_handler(p_cinst, p_event); -} - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) -static inline void class_sof_interrupt_handler(app_usbd_class_inst_t const * const p_cinst, - app_usbd_complex_evt_t const * const p_event) -{ - ASSERT(p_cinst != NULL); - ASSERT(p_cinst->p_data != NULL); - ASSERT(p_cinst->p_data->sof_handler != NULL); - p_cinst->p_data->sof_handler(p_event->drv_evt.data.sof.framecnt); -} - -/** - * @brief User event handler call (passed via configuration). - * - * @param p_event Handler of an event that is going to be added into queue. - * @param queued The event is visible in the queue. - */ -static inline void user_event_handler(app_usbd_internal_evt_t const * const p_event, bool queued) -{ - if ((m_current_conf.ev_isr_handler) != NULL) - { - m_current_conf.ev_isr_handler(p_event, queued); - } -} -#endif - -/** - * @brief User event processor call (passed via configuration). - * - * @param event Event type. - */ -static inline void user_event_state_proc(app_usbd_event_type_t event) -{ - if ((m_current_conf.ev_state_proc) != NULL) - { - m_current_conf.ev_state_proc(event); - } -} - -/** - * @brief Find a specified descriptor. - * - * @param[in] p_cinst Class instance. - * @param[in] desc_type Descriptor type @ref app_usbd_descriptor_t - * @param[in] desc_index Descriptor index. - * @param[out] p_desc Pointer to escriptor. - * @param[out] p_desc_len Length of descriptor. - * - * @return Standard error code @ref ret_code_t - * @retval NRF_SUCCESS Descriptor successfully found. - * @retval NRF_ERROR_NOT_FOUND Descriptor not found. - * */ -ret_code_t app_usbd_class_descriptor_find(app_usbd_class_inst_t const * const p_cinst, - uint8_t desc_type, - uint8_t desc_index, - uint8_t * p_desc, - size_t * p_desc_len) -{ - app_usbd_class_descriptor_ctx_t siz; - APP_USBD_CLASS_DESCRIPTOR_INIT(&siz); - uint32_t total_size = 0; - while(p_cinst->p_class_methods->feed_descriptors(&siz, p_cinst, NULL, sizeof(uint8_t))) - { - total_size++; - } - - uint8_t cur_len = 0; - uint32_t cur_size = 0; - - uint8_t index = 0; - app_usbd_class_descriptor_ctx_t descr; - APP_USBD_CLASS_DESCRIPTOR_INIT(&descr); - - while(cur_size < total_size) - { - /* First byte of a descriptor is its size */ - UNUSED_RETURN_VALUE(p_cinst->p_class_methods->feed_descriptors(&descr, - p_cinst, - &cur_len, - sizeof(uint8_t))); - - /* Second byte is type of the descriptor */ - uint8_t type; - UNUSED_RETURN_VALUE(p_cinst->p_class_methods->feed_descriptors(&descr, - p_cinst, - &type, - sizeof(uint8_t))); - - if(type == desc_type) - { - if(index == desc_index) - { - /* Copy the length of descriptor to *p_desc_len */ - *p_desc_len = cur_len; - /* Two first bytes of descriptor have already been fed - copy them to *p_desc */ - *p_desc++ = cur_len; - *p_desc++ = desc_type; - /* Copy the rest of descriptor to *p_desc */ - UNUSED_RETURN_VALUE(p_cinst->p_class_methods->feed_descriptors(&descr, - p_cinst, - p_desc, - cur_len-2)); - return NRF_SUCCESS; - } - else - { - index++; - } - } - /* Fast-forward through unmatched descriptor */ - UNUSED_RETURN_VALUE(p_cinst->p_class_methods->feed_descriptors(&descr, - p_cinst, - NULL, - cur_len-2)); - cur_size += cur_len; - } - return NRF_ERROR_NOT_FOUND; -} - -/** - * @brief Access into selected endpoint configuration structure. - * - * @param ep Endpoint address. - * @return A pointer to the endpoint configuration structure. - * - * @note This function would assert when endpoint number is not correct and debugging is enabled. - */ -static app_usbd_ep_conf_t * app_usbd_ep_conf_access(nrf_drv_usbd_ep_t ep) -{ - if (NRF_USBD_EPIN_CHECK(ep)) - { - uint8_t nr = NRF_USBD_EP_NR_GET(ep); - ASSERT(nr < NRF_USBD_EPIN_CNT); - return &m_epin_conf[nr]; - } - else - { - uint8_t nr = NRF_USBD_EP_NR_GET(ep); - ASSERT(nr < NRF_USBD_EPOUT_CNT); - return &m_epout_conf[nr]; - } -} - -/** - * @brief Accessing instance connected with selected endpoint. - * - * @param ep Endpoint number. - * - * @return The pointer to the instance connected with endpoint. - */ -static inline app_usbd_class_inst_t const * app_usbd_ep_instance_get(nrf_drv_usbd_ep_t ep) -{ - return app_usbd_ep_conf_access(ep)->p_cinst; -} - -/** - * @brief Connect instance with selected endpoint. - * - * This function configures instance connected to endpoint but also sets - * default event handler function pointer. - * - * @param ep Endpoint number. - * @param p_cinst The instance to connect into the selected endpoint. - * NULL if endpoint is going to be disconnected. - * - * @note Disconnecting EP0 is not allowed and protected by assertion. - */ -static void app_usbd_ep_instance_set(nrf_drv_usbd_ep_t ep, app_usbd_class_inst_t const * p_cinst) -{ - app_usbd_ep_conf_t * p_ep_conf = app_usbd_ep_conf_access(ep); - /* Set instance and default event handler */ - p_ep_conf->p_cinst = p_cinst; - if (p_cinst == NULL) - { - ASSERT((ep != NRF_DRV_USBD_EPOUT0) && (ep != NRF_DRV_USBD_EPIN0)); /* EP0 should never be disconnected */ - p_ep_conf->event_handler = NULL; - } - else - { - p_ep_conf->event_handler = p_cinst->p_class_methods->event_handler; - } -} - -/** - * @brief Call the core handler. - * - * Core instance is special kind of instance that is connected only to endpoint 0. - * It is not present in instance list. - * This auxiliary function makes future changes easier. - * Just call the event instance for core module here. - */ -static inline ret_code_t app_usbd_core_handler_call(app_usbd_internal_evt_t const * const p_event) -{ - return m_epout_conf[0].event_handler( - m_epout_conf[0].p_cinst, - (app_usbd_complex_evt_t const *)p_event); -} - - - -/** - * @brief Add event for execution. - * - * Dependent on configuration event would be executed in place or would be added into queue - * to be executed later. - * - * @param p_event_input Event to be executed. - */ -static inline void app_usbd_event_add(app_usbd_internal_evt_t const * const p_event_input) -{ - app_usbd_internal_evt_t const * p_event = p_event_input; - - - if (p_event->type == APP_USBD_EVT_DRV_SETUP) - { - uint8_t bRequest = nrf_usbd_setup_brequest_get(); - uint8_t bmRequestType = nrf_usbd_setup_bmrequesttype_get(); - - if ((bmRequestType == app_usbd_setup_req_val( - APP_USBD_SETUP_REQREC_DEVICE, - APP_USBD_SETUP_REQTYPE_STD, - APP_USBD_SETUP_REQDIR_OUT)) - && (bRequest == APP_USBD_SETUP_STDREQ_SET_ADDRESS)) - { - static const app_usbd_internal_evt_t event_setaddress = - { - .type = APP_USBD_EVT_SETUP_SETADDRESS, - }; - p_event = &event_setaddress; - } - } - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) - - if (p_event->app_evt.type == APP_USBD_EVT_DRV_SOF) - { - /* Propagate SOF event to classes that need it in interrupt */ - app_usbd_class_inst_t const * p_inst = app_usbd_class_sof_interrupt_first_get(); - while (NULL != p_inst) - { - class_sof_interrupt_handler(p_inst, (app_usbd_complex_evt_t const *)p_event); - p_inst = app_usbd_class_sof_interrupt_next_get(p_inst); - } - -#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - CRITICAL_REGION_ENTER(); - if (m_sof_events_cnt == 0) - { - m_event_frame = p_event->drv_evt.data.sof.framecnt; - } - UNUSED_RETURN_VALUE(nrf_atomic_u32_add(&m_sof_events_cnt, 1)); - CRITICAL_REGION_EXIT(); - - user_event_handler(p_event, true); - if (m_sof_events_cnt == APP_USBD_SOF_WARNING_LIMIT) - { - NRF_LOG_WARNING("Stacked over %d SOF events.", APP_USBD_SOF_WARNING_LIMIT); - } - return; - -#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - -#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_INTERRUPT) - - user_event_handler(p_event, false); - app_usbd_event_execute(p_event); - return; - -#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_INTERRUPT) - } - - nrf_atfifo_item_put_t cx; - app_usbd_internal_queue_evt_t * p_event_item = nrf_atfifo_item_alloc(m_event_queue, &cx); - - if (NULL != p_event_item) - { - bool visible; - p_event_item->evt = *p_event; - -#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - CRITICAL_REGION_ENTER(); - p_event_item->start_frame = m_event_frame - m_sof_events_cnt + 1; - p_event_item->sof_cnt = nrf_atomic_u32_fetch_store(&m_sof_events_cnt, 0); - CRITICAL_REGION_EXIT(); -#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - - visible = nrf_atfifo_item_put(m_event_queue, &cx); - user_event_handler(p_event, visible); - } - else - { - NRF_LOG_ERROR("Event queue full."); - } -#else - m_current_conf.ev_handler(p_event); -#endif -} - -/** - * @brief Power event handler. - * - * The function that pushes power events into the queue. - * @param p_event Event from power driver to map into APP_USBD_EVT_POWER_ event. - */ -#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS -static void app_usbd_power_event_handler(nrf_drv_power_usb_evt_t event) -{ - switch(event) - { - case NRF_DRV_POWER_USB_EVT_DETECTED: - { - static const app_usbd_internal_evt_t ev = { - .type = APP_USBD_EVT_POWER_DETECTED - }; - app_usbd_event_add(&ev); - break; - } - case NRF_DRV_POWER_USB_EVT_REMOVED: - { - static const app_usbd_internal_evt_t ev = { - .type = APP_USBD_EVT_POWER_REMOVED - }; - app_usbd_event_add(&ev); - break; - } - case NRF_DRV_POWER_USB_EVT_READY: - { - static const app_usbd_internal_evt_t ev = { - .type = APP_USBD_EVT_POWER_READY - }; - app_usbd_event_add(&ev); - break; - } - default: - ASSERT(false); - } -} -#endif - -/** - * @brief Event handler. - * - * The function that pushes the event into the queue. - * @param p_event Event to push. - */ -static void app_usbd_event_handler(nrf_drv_usbd_evt_t const * const p_event) -{ - app_usbd_event_add((app_usbd_internal_evt_t const *)p_event); -} - -/** - * @brief HF clock ready event handler. - * - * Function that is called when high frequency clock is started. - * - * @param event Event type that comes from clock driver. - */ -static void app_usbd_hfclk_ready(nrf_drv_clock_evt_type_t event) -{ - ASSERT(NRF_DRV_CLOCK_EVT_HFCLK_STARTED == event); - static const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_HFCLK_READY - }; - app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); -} - -/** - * @brief Check if the HFCLK was requested in selected suspend state machine state. - * - * - * @param sustate State to be checked. - * - * @retval true High frequency clock was requested in selected state. - * @retval false High frequency clock was released in selected state. - */ -static inline bool app_usbd_sustate_with_requested_hfclk(app_usbd_sustate_t sustate) -{ - switch(sustate) - { - case SUSTATE_STOPPED: return false; - case SUSTATE_STARTED: return false; - case SUSTATE_ACTIVE: return true; - case SUSTATE_SUSPENDING: return false; - case SUSTATE_SUSPEND: return false; - case SUSTATE_RESUMING: return true; - case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: return true; - case SUSTATE_WAKINGUP_WAITING_HFCLK: return true; - case SUSTATE_WAKINGUP_WAITING_WREQ: return true; - default: - return false; - } -} - -/** - * @brief Check it the HFCLK is running in selected suspend state machine state. - * - * @param sustate State to be checked. - * - * @retval true High frequency clock is running in selected state. - * @retval false High frequency clock is released in selected state. - */ -static inline bool app_usbd_sustate_with_running_hfclk(app_usbd_sustate_t sustate) -{ - switch(sustate) - { - case SUSTATE_STOPPED: return false; - case SUSTATE_STARTED: return false; - case SUSTATE_ACTIVE: return true; - case SUSTATE_SUSPENDING: return false; - case SUSTATE_SUSPEND: return false; - case SUSTATE_RESUMING: return false; - case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: return false; - case SUSTATE_WAKINGUP_WAITING_HFCLK: return false; - case SUSTATE_WAKINGUP_WAITING_WREQ: return true; - default: - return false; - } -} - -/** - * @brief Get current suspend state machine state. - * - * @return The state of the suspend state machine. - */ -static inline app_usbd_sustate_t sustate_get(void) -{ - return m_sustate; -} - -/** - * @brief Set current suspend state machine state. - * - * @param sustate The requested state of the state machine. - */ -static inline void sustate_set(app_usbd_sustate_t sustate) -{ - if (app_usbd_sustate_with_requested_hfclk(sustate) != app_usbd_sustate_with_requested_hfclk(m_sustate)) - { - if (app_usbd_sustate_with_requested_hfclk(sustate)) - { - static nrf_drv_clock_handler_item_t clock_handler_item = - { - .event_handler = app_usbd_hfclk_ready - }; - nrf_drv_clock_hfclk_request(&clock_handler_item); - } - else - { - nrf_drv_clock_hfclk_release(); - } - } - if (app_usbd_sustate_with_running_hfclk(sustate) != app_usbd_sustate_with_running_hfclk(m_sustate)) - { - if (app_usbd_sustate_with_running_hfclk(sustate)) - { - nrf_drv_usbd_active_irq_config(); - } - else - { - nrf_drv_usbd_suspend_irq_config(); - } - } - m_sustate = sustate; -} - -/** - * @brief Default selection function for interface. - * - * This function just enables and clears interface endpoints. - * - * @param[in] p_inst Class instance. - * @param[in] iface_idx Interface index. - * @param[in] alternate Interface alternate setting. - * - * @note Currently only alternate setting 0 is supported. - * - * @return Standard error code @ref ret_code_t - * @retval NRF_SUCCESS Endpoints enabled and cleared. - * @retval NRF_ERROR_INVALID_PARAM Unsupported alternate selected. - */ -static inline ret_code_t default_iface_select( - app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx, - uint8_t alternate) -{ - ASSERT(iface_idx <= app_usbd_class_iface_count_get(p_inst)); - - if (alternate != 0) - { - return NRF_ERROR_INVALID_PARAM; - } - - app_usbd_class_iface_conf_t const * p_iface = app_usbd_class_iface_get(p_inst, iface_idx); - uint8_t ep_count = app_usbd_class_iface_ep_count_get(p_iface); - - for (uint8_t i = 0; i < ep_count; ++i) - { - /* Enable every endpoint */ - app_usbd_class_ep_conf_t const * p_ep = app_usbd_class_iface_ep_get(p_iface, i); - app_usbd_ep_enable(p_ep->address); - } - return NRF_SUCCESS; -} - -/** - * @brief Default deselection function for interface. - * - * This function just disables all interface endpoints. - * - * @param[in] p_inst Class instance. - * @param[in] iface_idx Interface index. - */ -static inline void default_iface_deselect( - app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx) -{ - ASSERT(iface_idx <= app_usbd_class_iface_count_get(p_inst)); - - app_usbd_class_iface_conf_t const * p_iface = app_usbd_class_iface_get(p_inst, iface_idx); - uint8_t ep_count = app_usbd_class_iface_ep_count_get(p_iface); - - for (uint8_t i = 0; i < ep_count; ++i) - { - /* Disable every endpoint */ - app_usbd_class_ep_conf_t const * p_ep = app_usbd_class_iface_ep_get(p_iface, i); - app_usbd_ep_disable(p_ep->address); - } -} - - -/** @} */ - -#if (APP_USBD_PROVIDE_SOF_TIMESTAMP) || defined(__SDK_DOXYGEN__) -uint32_t app_usbd_sof_timestamp_get(void) -{ - return m_last_frame; -} -#endif - -ret_code_t app_usbd_init(app_usbd_config_t const * p_config) -{ - ASSERT(nrf_drv_clock_init_check()); - ret_code_t ret; - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) - ret = NRF_ATFIFO_INIT(m_event_queue); - if (NRF_SUCCESS != ret) - { - return NRF_ERROR_INTERNAL; - } -#endif - - /* This is called at the beginning to secure multiple calls to init function */ - ret = nrf_drv_usbd_init(app_usbd_event_handler); - if (NRF_SUCCESS != ret) - { - return ret; - } - - /* Clear the variables */ - m_sustate = SUSTATE_STOPPED; - m_p_first_cinst = NULL; - m_p_first_sof_cinst = NULL; - memset(m_epin_conf , 0, sizeof(m_epin_conf )); - memset(m_epout_conf, 0, sizeof(m_epout_conf)); - /* Save the new configuration */ - if (p_config == NULL) - { - m_current_conf = m_default_conf; - } - else - { - m_current_conf = *p_config; - } - -#if (!(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)) - if(m_current_conf.ev_handler == NULL) - { - m_current_conf.ev_handler = m_default_conf.ev_handler; - } -#endif - -#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS - ret = nrf_drv_power_init(NULL); - if ((ret != NRF_SUCCESS) && (ret != NRF_ERROR_MODULE_ALREADY_INITIALIZED)) - { - /* This should never happen */ - APP_ERROR_HANDLER(ret); - } -#endif - - /*Pin core class to required endpoints*/ - uint8_t iface_idx; - app_usbd_class_iface_conf_t const * p_iface; - app_usbd_class_inst_t const * const p_inst = app_usbd_core_instance_access(); - iface_idx = 0; - while ((p_iface = app_usbd_class_iface_get(p_inst, iface_idx++)) != NULL) - { - uint8_t ep_idx = 0; - app_usbd_class_ep_conf_t const * p_ep; - while ((p_ep = app_usbd_class_iface_ep_get(p_iface, ep_idx++)) != NULL) - { - app_usbd_ep_instance_set(app_usbd_class_ep_address_get(p_ep), p_inst); - } - } - - /* Successfully attached */ - const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_INST_APPEND - }; - - ret = class_event_handler(p_inst, (app_usbd_complex_evt_t const *)(&evt_data)); - if (NRF_SUCCESS != ret) - { - UNUSED_RETURN_VALUE(nrf_drv_usbd_uninit()); - return ret; - } - - return NRF_SUCCESS; -} - - -ret_code_t app_usbd_uninit(void) -{ -#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS - nrf_drv_power_usbevt_uninit(); -#endif - - /* We get this error at very beginning but it would be used at the end of the function */ - const ret_code_t ret = nrf_drv_usbd_uninit(); - - /* Unchain instance list */ - app_usbd_class_inst_t const * * pp_inst; - pp_inst = &m_p_first_cinst; - while (NULL != (*pp_inst)) - { - app_usbd_class_inst_t const * * pp_next = &app_usbd_class_data_access(*pp_inst)->p_next; - (*pp_inst) = NULL; - pp_inst = pp_next; - } - - /* Unchain SOF list */ - pp_inst = &m_p_first_sof_cinst; - while (NULL != (*pp_inst)) - { - app_usbd_class_inst_t const * * pp_next = &app_usbd_class_data_access(*pp_inst)->p_sof_next; - (*pp_inst) = NULL; - pp_inst = pp_next; - } - - /* Unchain SOF interrupt list */ - pp_inst = &m_p_first_sof_interrupt_cinst; - while (NULL != (*pp_inst)) - { - app_usbd_class_inst_t const * * pp_next = &app_usbd_class_data_access(*pp_inst)->p_sof_next; - (*pp_inst) = NULL; - pp_inst = pp_next; - } - - /* Clear all endpoints configurations */ - memset(m_epin_conf , 0, sizeof(m_epin_conf )); - memset(m_epout_conf, 0, sizeof(m_epout_conf)); - /* Clear current configuration */ - memset(&m_current_conf, 0, sizeof(m_current_conf)); - - return ret; -} - - -#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS -ret_code_t app_usbd_power_events_enable(void) -{ - if (!nrf_drv_usbd_is_initialized() || nrf_drv_usbd_is_enabled()) - { - return NRF_ERROR_INVALID_STATE; - } - - ASSERT((!APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || (USBD_CONFIG_IRQ_PRIORITY == POWER_CONFIG_IRQ_PRIORITY)); - - ret_code_t ret; - static const nrf_drv_power_usbevt_config_t config = - { - .handler = app_usbd_power_event_handler - }; - - ret = nrf_drv_power_usbevt_init(&config); - APP_ERROR_CHECK(ret); - - return NRF_SUCCESS; -} -#endif /* APP_USBD_CONFIG_POWER_EVENTS_PROCESS */ - - -void app_usbd_enable(void) -{ - nrf_drv_usbd_enable(); -} - - -void app_usbd_disable(void) -{ - ASSERT(!nrf_drv_usbd_is_started()); - nrf_drv_usbd_disable(); -} - - -void app_usbd_start(void) -{ - ASSERT(nrf_drv_usbd_is_enabled()); - - /* Check if interface numbers are in correct order */ - if (APP_USBD_CONFIG_LOG_ENABLED) - { - uint8_t next_iface = 0; - for (app_usbd_class_inst_t const * * pp_inst = &m_p_first_cinst; - (*pp_inst) != NULL; - pp_inst = &(app_usbd_class_data_access(*pp_inst)->p_next)) - { - uint8_t iface_idx = 0; - app_usbd_class_iface_conf_t const * p_iface; - while (NULL != (p_iface = app_usbd_class_iface_get(*pp_inst, iface_idx++))) - { - if (p_iface->number != next_iface) - { - NRF_LOG_WARNING("Unexpected interface number, expected %d, got %d", - next_iface, - p_iface->number); - } - ++next_iface; - } - } - } - - /* Power should be already enabled - wait just in case if user calls - * app_usbd_start just after app_usbd_enable without waiting for the event. */ - while (!nrf_power_usbregstatus_outrdy_get()) - { - /* Wait for the power but terminate the function if USBD power disappears */ - if (!nrf_power_usbregstatus_vbusdet_get()) - return; - } - - static const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_START_REQ - }; - app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); -} - - -void app_usbd_stop(void) -{ - const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_STOP_REQ - }; - app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); -} - -void app_usbd_suspend_req(void) -{ - const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_SUSPEND_REQ - }; - app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); -} - -bool app_usbd_wakeup_req(void) -{ - ASSERT(app_usbd_class_rwu_enabled_check()); - if (!app_usbd_core_feature_state_get(APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP)) - return false; - - const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_WAKEUP_REQ - }; - app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); - return true; -} - -bool app_usbd_active_check(void) -{ - return (sustate_get() == SUSTATE_ACTIVE); -} - -void app_usbd_event_execute(app_usbd_internal_evt_t const * const p_event) -{ - ASSERT(NULL != m_p_first_cinst); - /* If no event queue is implemented, it has to be ensured that this function is never called - * from the context higher than USB interrupt level - * If queue is implemented it would be called always from Thread level - * if the library is used correctly. - * NOTE: Higher interrupt level -> lower priority value. - */ - ASSERT(USBD_CONFIG_IRQ_PRIORITY <= current_int_priority_get()); - - /* Note - there should never be situation that event is generated on disconnected endpoint */ - switch (p_event->type) - { - case APP_USBD_EVT_START_REQ: - { - static const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_STARTED - }; - - /* Send event to all classes */ - UNUSED_RETURN_VALUE(app_usbd_core_handler_call((app_usbd_internal_evt_t const * )&evt_data)); - app_usbd_all_call((app_usbd_complex_evt_t const *)&evt_data); - user_event_state_proc(APP_USBD_EVT_STARTED); - - app_usbd_all_iface_deselect(); - app_usbd_core_ep0_disable(); - nrf_drv_usbd_start((NULL != m_p_first_sof_cinst) || (m_current_conf.enable_sof) || (APP_USBD_PROVIDE_SOF_TIMESTAMP)); - sustate_set(SUSTATE_STARTED); - break; - } - case APP_USBD_EVT_STOP_REQ: - { - static const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_STOPPED - }; - - app_usbd_all_iface_deselect(); - nrf_drv_usbd_stop(); - sustate_set(SUSTATE_STOPPED); - - /* Send event to all classes */ - app_usbd_all_call((app_usbd_complex_evt_t const * )&evt_data); - UNUSED_RETURN_VALUE(app_usbd_core_handler_call((app_usbd_internal_evt_t const *)&evt_data)); - user_event_state_proc(APP_USBD_EVT_STOPPED); - if (app_usbd_sustate_with_requested_hfclk(sustate_get())) - { - nrf_drv_clock_hfclk_release(); - } - - break; - } - case APP_USBD_EVT_HFCLK_READY: - { - switch(sustate_get()) - { - case SUSTATE_RESUMING: - { - sustate_set(SUSTATE_ACTIVE); - break; - } - case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: - { - sustate_set(SUSTATE_WAKINGUP_WAITING_WREQ); - break; - } - case SUSTATE_WAKINGUP_WAITING_HFCLK: - { - sustate_set(SUSTATE_ACTIVE); - break; - } - default: - break; // Just ignore - it can happen in specific situation - } - break; - } - case APP_USBD_EVT_SUSPEND_REQ: - { - /* Suspend request can be only processed when we are in suspending state */ - if (SUSTATE_SUSPENDING == sustate_get()) - { - if (nrf_drv_usbd_suspend()) - { - sustate_set(SUSTATE_SUSPEND); - } - } - break; - } - case APP_USBD_EVT_WAKEUP_REQ: - { - /* Suspend temporary if no suspend function was called from the application. - * This makes it possible to generate APP_USBD_EVT_DRV_WUREQ event from the driver */ - if (sustate_get() == SUSTATE_SUSPENDING) - { - if (nrf_drv_usbd_suspend()) - { - sustate_set(SUSTATE_SUSPEND); - } - } - if (nrf_drv_usbd_wakeup_req()) - { - sustate_set(SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ); - } - break; - } - - case APP_USBD_EVT_DRV_SOF: - { -#if (APP_USBD_PROVIDE_SOF_TIMESTAMP) || defined(__SDK_DOXYGEN__) - m_last_frame = p_event->drv_evt.data.sof.framecnt; -#endif - /* Wake up if suspended */ - if ((sustate_get() == SUSTATE_SUSPENDING) || (sustate_get() == SUSTATE_WAKINGUP_WAITING_WREQ)) - { - static const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_DRV_RESUME - }; - app_usbd_event_execute((app_usbd_internal_evt_t *)&evt_data); - } - - user_event_state_proc(APP_USBD_EVT_DRV_SOF); - - app_usbd_class_inst_t const * p_inst = app_usbd_class_sof_first_get(); - while (NULL != p_inst) - { - ret_code_t r = class_event_handler(p_inst, (app_usbd_complex_evt_t const *)p_event); - UNUSED_VARIABLE(r); - p_inst = app_usbd_class_sof_next_get(p_inst); - } - break; - } - - case APP_USBD_EVT_DRV_RESET: - { - app_usbd_all_iface_deselect(); - app_usbd_core_ep0_enable(); - sustate_set(SUSTATE_ACTIVE); - user_event_state_proc(APP_USBD_EVT_DRV_RESET); - /* Processing core interface (connected only to EP0) and then all instances from the list */ - UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); - app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); - break; - } - case APP_USBD_EVT_DRV_RESUME: - { - if (sustate_get() == SUSTATE_WAKINGUP_WAITING_WREQ) - { - sustate_set(SUSTATE_ACTIVE); - nrf_drv_usbd_force_bus_wakeup(); - } - else - { - sustate_set(SUSTATE_RESUMING); - } - user_event_state_proc(APP_USBD_EVT_DRV_RESUME); - /* Processing core interface (connected only to EP0) and then all instances from the list */ - UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); - app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); - break; - } - case APP_USBD_EVT_DRV_WUREQ: - { - static const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_DRV_RESUME - }; - user_event_state_proc(APP_USBD_EVT_DRV_RESUME); - /* Processing core interface (connected only to EP0) and then all instances from the list */ - UNUSED_RETURN_VALUE(app_usbd_core_handler_call((app_usbd_internal_evt_t const *)&evt_data)); - app_usbd_all_call((app_usbd_complex_evt_t const *)&evt_data); - - switch(sustate_get()) - { - case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: - sustate_set(SUSTATE_WAKINGUP_WAITING_HFCLK); - break; - case SUSTATE_WAKINGUP_WAITING_WREQ: - sustate_set(SUSTATE_ACTIVE); - break; - default: - { - /* This should not happen - but try to recover by setting directly active state */ - NRF_LOG_WARNING("Unexpected state on WUREQ event (%u)", sustate_get()); - sustate_set(SUSTATE_ACTIVE); - } - } - break; - } - case APP_USBD_EVT_DRV_SUSPEND: - { - sustate_set(SUSTATE_SUSPENDING); - - user_event_state_proc(APP_USBD_EVT_DRV_SUSPEND); - - /* Processing all instances from the list and then core interface (connected only to EP0) */ - app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); - UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); - break; - } - - case APP_USBD_EVT_STATE_CHANGED: - { - user_event_state_proc(APP_USBD_EVT_STATE_CHANGED); - /* Processing all instances from the list and then core interface (connected only to EP0) */ - app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); - break; - } - - case APP_USBD_EVT_DRV_SETUP: - { - UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); - break; - } - - case APP_USBD_EVT_SETUP_SETADDRESS: - { - UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); - break; - } - - case APP_USBD_EVT_DRV_EPTRANSFER: - { - app_usbd_ep_conf_t const * p_ep_conf = - app_usbd_ep_conf_access(p_event->drv_evt.data.eptransfer.ep); - ASSERT(NULL != p_ep_conf->p_cinst); - ASSERT(NULL != p_ep_conf->event_handler); - - if (NRF_SUCCESS != p_ep_conf->event_handler(p_ep_conf->p_cinst, - (app_usbd_complex_evt_t const *)p_event)) - { - /* If error returned, every bulk/interrupt endpoint would be stalled */ - if (!(0 == NRF_USBD_EP_NR_GET(p_event->drv_evt.data.eptransfer.ep) || - NRF_USBD_EPISO_CHECK(p_event->drv_evt.data.eptransfer.ep))) - { - nrf_drv_usbd_ep_stall(p_event->drv_evt.data.eptransfer.ep); - } - } - break; - } -#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS - case APP_USBD_EVT_POWER_DETECTED: - { - user_event_state_proc(APP_USBD_EVT_POWER_DETECTED); - app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); - break; - } - case APP_USBD_EVT_POWER_REMOVED: - { - user_event_state_proc(APP_USBD_EVT_POWER_REMOVED); - app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); - break; - } - case APP_USBD_EVT_POWER_READY: - { - user_event_state_proc(APP_USBD_EVT_POWER_READY); - app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); - break; - } -#endif - default: - ASSERT(0); - break; - } -} - - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) -bool app_usbd_event_queue_process(void) -{ -#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - app_usbd_internal_evt_t sof_event = { - .app_evt.type = APP_USBD_EVT_DRV_SOF - }; -#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - static nrf_atfifo_item_get_t cx; - static app_usbd_internal_queue_evt_t * p_event_item = NULL; - if (NULL == p_event_item) - { - p_event_item = nrf_atfifo_item_get(m_event_queue, &cx); - } - - if (NULL != p_event_item) - { - -#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - if (p_event_item->sof_cnt > 0) - { - if (p_event_item->start_frame > USBD_FRAMECNTR_FRAMECNTR_Msk) - { - p_event_item->start_frame = 0; - } - sof_event.drv_evt.data.sof.framecnt = (p_event_item->start_frame)++; - --(p_event_item->sof_cnt); - app_usbd_event_execute(&sof_event); - return true; - } -#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - - app_usbd_event_execute(&(p_event_item->evt)); - UNUSED_RETURN_VALUE(nrf_atfifo_item_free(m_event_queue, &cx)); - p_event_item = NULL; - return true; - } -#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - else if (m_sof_events_cnt > 0) - { - CRITICAL_REGION_ENTER(); - if (m_event_frame > USBD_FRAMECNTR_FRAMECNTR_Msk) - { - m_event_frame = 0; - } - sof_event.drv_evt.data.sof.framecnt = m_event_frame++; - UNUSED_RETURN_VALUE(nrf_atomic_u32_sub_hs(&m_sof_events_cnt, 1)); - CRITICAL_REGION_EXIT(); - app_usbd_event_execute(&sof_event); - return true; - } -#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) - else - { - return false; - } -} -#endif - - -ret_code_t app_usbd_class_append(app_usbd_class_inst_t const * p_cinst) -{ - ASSERT(NULL != p_cinst); - ASSERT(NULL != p_cinst->p_class_methods); - ASSERT(NULL != p_cinst->p_class_methods->event_handler); - ASSERT(NULL == app_usbd_class_data_access(p_cinst)->p_next); - - /* This should be only called if USBD is disabled - * We simply assume that USBD is enabled if its interrupts are */ - ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); - - /* Check if all required endpoints are available - * Checking is splitted from setting to avoid situation that anything - * is modified and then operation finishes with error */ - uint8_t iface_idx; - app_usbd_class_iface_conf_t const * p_iface; - - iface_idx = 0; - while (NULL != (p_iface = app_usbd_class_iface_get(p_cinst, iface_idx++))) - { - uint8_t ep_idx = 0; - app_usbd_class_ep_conf_t const * p_ep; - while (NULL != (p_ep = app_usbd_class_iface_ep_get(p_iface, ep_idx++))) - { - if (NULL != app_usbd_ep_instance_get(app_usbd_class_ep_address_get(p_ep))) - { - return NRF_ERROR_BUSY; - } - } - } - - /* Connecting all required endpoints */ - iface_idx = 0; - while (NULL != (p_iface = app_usbd_class_iface_get(p_cinst, iface_idx++))) - { - uint8_t ep_idx = 0; - app_usbd_class_ep_conf_t const * p_ep; - while (NULL != (p_ep = app_usbd_class_iface_ep_get(p_iface, ep_idx++))) - { - app_usbd_ep_instance_set(app_usbd_class_ep_address_get(p_ep), p_cinst); - } - } - - /* Adding pointer to this instance to the end of the chain */ - app_usbd_class_inst_t const * * pp_last = &m_p_first_cinst; - while (NULL != (*pp_last)) - { - ASSERT((*pp_last) != p_cinst); - pp_last = &(app_usbd_class_data_access(*pp_last)->p_next); - } - (*pp_last) = p_cinst; - - /* Successfully attached */ - const app_usbd_evt_t evt_data = {.type = APP_USBD_EVT_INST_APPEND }; - return class_event_handler(p_cinst, (app_usbd_complex_evt_t const *)(&evt_data)); -} - - -ret_code_t app_usbd_class_remove(app_usbd_class_inst_t const * p_cinst) -{ - ASSERT(NULL != p_cinst); - ASSERT(NULL != p_cinst->p_class_methods); - ASSERT(NULL != p_cinst->p_class_methods->event_handler); - /* This function should be only called if USBD is disabled */ - ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); - ret_code_t ret; - /* Remove this class from the chain */ - app_usbd_class_inst_t const * * pp_last = &m_p_first_cinst; - while (NULL != (*pp_last)) - { - if ((*pp_last) == p_cinst) - { - /* Inform class instance that removing process is going to be started */ - const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_INST_REMOVE - }; - ret = class_event_handler(p_cinst, (app_usbd_complex_evt_t const *)(&evt_data)); - if (ret != NRF_SUCCESS) - { - return ret; - } - - /* Breaking chain */ - (*pp_last) = (app_usbd_class_data_access(p_cinst)->p_next); - app_usbd_class_data_access(p_cinst)->p_next = NULL; - - /* Disconnecting endpoints */ - uint8_t ep_idx; - for (ep_idx = 0; ep_idx < NRF_USBD_EPIN_CNT; ++ep_idx) - { - nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPIN(ep_idx); - if (app_usbd_ep_instance_get(ep) == p_cinst) - { - app_usbd_ep_instance_set(ep, NULL); - } - } - for (ep_idx = 0; ep_idx < NRF_USBD_EPOUT_CNT; ++ep_idx) - { - nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPOUT(ep_idx); - if (app_usbd_ep_instance_get(ep) == p_cinst) - { - app_usbd_ep_instance_set(ep, NULL); - } - } - - return NRF_SUCCESS; - } - pp_last = &(app_usbd_class_data_access(*pp_last)->p_next); - } - - return NRF_ERROR_NOT_FOUND; -} - - -ret_code_t app_usbd_class_remove_all(void) -{ - ret_code_t ret = NRF_SUCCESS; - while (NULL != m_p_first_cinst) - { - ret = app_usbd_class_remove(m_p_first_cinst); - if (ret != NRF_SUCCESS) - { - break; - } - } - - return ret; -} - - -ret_code_t app_usbd_ep_handler_set(app_usbd_class_inst_t const * const p_cinst, - nrf_drv_usbd_ep_t ep, - app_usbd_ep_event_handler_t handler) -{ - ASSERT(NULL != p_cinst); - ASSERT(NULL != handler); - /* This function should be only called if USBD is disabled */ - ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); - - if (p_cinst != app_usbd_ep_instance_get(ep)) - { - return NRF_ERROR_INVALID_PARAM; - } - - (app_usbd_ep_conf_access(ep))->event_handler = handler; - return NRF_SUCCESS; -} - - -ret_code_t app_usbd_class_sof_register(app_usbd_class_inst_t const * p_cinst) -{ - ASSERT(NULL != p_cinst); - ASSERT(NULL != p_cinst->p_class_methods); - ASSERT(NULL != p_cinst->p_class_methods->event_handler); - /* This function should be only called if USBD is disabled */ - ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); - - /* Make sure it's not in interrupt SOF list */ - app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_interrupt_cinst; - while (NULL != (*pp_last)) - { - ASSERT((*pp_last) != p_cinst); - pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); - } - - /* Next SOF event requiring instance has to be NULL now */ - ASSERT(NULL == (app_usbd_class_data_access(p_cinst)->p_sof_next)); - - /* Adding pointer to this instance to the end of the chain */ - pp_last = &m_p_first_sof_cinst; - while (NULL != (*pp_last)) - { - ASSERT((*pp_last) != p_cinst); - pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); - } - (*pp_last) = p_cinst; - - return NRF_SUCCESS; -} - - -ret_code_t app_usbd_class_sof_unregister(app_usbd_class_inst_t const * p_cinst) -{ - ASSERT(NULL != p_cinst); - /** This function should be only called if USBD is disabled */ - ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); - - app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_cinst; - while (NULL != (*pp_last)) - { - if ((*pp_last) == p_cinst) - { - /* Breaking chain */ - (*pp_last) = (app_usbd_class_data_access(p_cinst)->p_sof_next); - app_usbd_class_data_access(p_cinst)->p_sof_next = NULL; - - return NRF_SUCCESS; - } - pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); - } - return NRF_ERROR_NOT_FOUND; -} - -ret_code_t app_usbd_class_sof_interrupt_register(app_usbd_class_inst_t const * p_cinst, app_usbd_sof_interrupt_handler_t handler) -{ - ASSERT(NULL != p_cinst); - ASSERT(NULL != p_cinst->p_class_methods); - ASSERT(NULL != handler); - /* This function should be only called if USBD is disabled */ - ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); - - /* Next SOF event requiring instance has to be NULL now */ - ASSERT(NULL == (app_usbd_class_data_access(p_cinst)->p_sof_next)); - - app_usbd_class_data_access(p_cinst)->sof_handler = handler; - - /* Make sure it's not in normal SOF list */ - app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_cinst; - while (NULL != (*pp_last)) - { - ASSERT((*pp_last) != p_cinst); - pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); - } - - /* Adding pointer to this instance to the end of the interrupt chain */ - pp_last = &m_p_first_sof_interrupt_cinst; - while (NULL != (*pp_last)) - { - - ASSERT((*pp_last) != p_cinst); - pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); - } - (*pp_last) = p_cinst; - - return NRF_SUCCESS; -} - - -ret_code_t app_usbd_class_sof_interrupt_unregister(app_usbd_class_inst_t const * p_cinst) -{ - ASSERT(NULL != p_cinst); - /** This function should be only called if USBD is disabled */ - ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); - - app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_interrupt_cinst; - while (NULL != (*pp_last)) - { - if ((*pp_last) == p_cinst) - { - /* Breaking chain */ - (*pp_last) = (app_usbd_class_data_access(p_cinst)->p_sof_next); - app_usbd_class_data_access(p_cinst)->p_sof_next = NULL; - - return NRF_SUCCESS; - } - pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); - } - return NRF_ERROR_NOT_FOUND; -} - -ret_code_t app_usbd_class_rwu_register(app_usbd_class_inst_t const * const p_inst) -{ - ASSERT(p_inst != NULL); - ++m_rwu_registered_counter; - /*Overflow check*/ - ASSERT(m_rwu_registered_counter != 0); - - return NRF_SUCCESS; -} - - -ret_code_t app_usbd_class_rwu_unregister(app_usbd_class_inst_t const * const p_inst) -{ - ASSERT(p_inst != NULL); - /* Usage validation. If counter is 0 unregister is not possible.*/ - ASSERT(m_rwu_registered_counter != 0); - --m_rwu_registered_counter; - - return NRF_SUCCESS; -} - -bool app_usbd_class_rwu_enabled_check(void) -{ - return (m_rwu_registered_counter != 0); -} - -ret_code_t app_usbd_interface_ep_reset(app_usbd_class_inst_t const * const p_cinst, - uint8_t iface) -{ - uint8_t iface_count = app_usbd_class_iface_count_get(p_cinst); - - app_usbd_class_iface_conf_t const * p_iface = NULL; - for (uint8_t j = 0; j < iface_count; ++j) - { - p_iface = app_usbd_class_iface_get(p_cinst, j); - if (app_usbd_class_iface_number_get(p_iface) == iface) - { - break; - } - } - - if (p_iface == NULL) - { - return NRF_ERROR_NOT_SUPPORTED; - } - - uint8_t ep_count = app_usbd_class_iface_ep_count_get(p_iface); - - for (uint8_t j = 0; j < ep_count; ++j) - { - /*Clear stall for every endpoint*/ - app_usbd_class_ep_conf_t const * p_ep = app_usbd_class_iface_ep_get(p_iface, j); - - if (!NRF_USBD_EPISO_CHECK(p_ep->address)) - { - nrf_drv_usbd_ep_dtoggle_clear(p_ep->address); - nrf_drv_usbd_ep_stall_clear(p_ep->address); - } - - } - - return NRF_SUCCESS; -} - -void app_usbd_ep_enable(nrf_drv_usbd_ep_t ep) -{ - if (!NRF_USBD_EPISO_CHECK(ep)) - { - nrf_drv_usbd_ep_dtoggle_clear(ep); - nrf_drv_usbd_ep_stall_clear(ep); - } - nrf_drv_usbd_ep_enable(ep); -} - -void app_usbd_ep_disable(nrf_drv_usbd_ep_t ep) -{ - nrf_drv_usbd_ep_disable(ep); -} - - -app_usbd_class_inst_t const * app_usbd_class_first_get(void) -{ - return m_p_first_cinst; -} - -app_usbd_class_inst_t const * app_usbd_class_sof_first_get(void) -{ - return m_p_first_sof_cinst; -} - -app_usbd_class_inst_t const * app_usbd_class_sof_interrupt_first_get(void) -{ - return m_p_first_sof_interrupt_cinst; -} - -app_usbd_class_inst_t const * app_usbd_iface_find(uint8_t iface, uint8_t * p_iface_idx) -{ - app_usbd_class_inst_t const * p_inst = app_usbd_class_first_get(); - while (p_inst != NULL) - { - uint8_t iface_count = app_usbd_class_iface_count_get(p_inst); - /* Iterate over interfaces */ - for (uint8_t i = 0; i < iface_count; ++i) - { - app_usbd_class_iface_conf_t const * p_iface; - p_iface = app_usbd_class_iface_get(p_inst, i); - if (app_usbd_class_iface_number_get(p_iface) == iface) - { - if (p_iface_idx != NULL) - { - (*p_iface_idx) = i; - } - return p_inst; - } - } - p_inst = app_usbd_class_next_get(p_inst); - } - return NULL; -} - -ret_code_t app_usbd_iface_call( - app_usbd_class_inst_t const * const p_class_inst, - uint8_t iface_idx, - app_usbd_complex_evt_t const * const p_event) -{ - UNUSED_PARAMETER(iface_idx); - return class_event_handler(p_class_inst, p_event); -} - -ret_code_t app_usbd_ep_call(nrf_drv_usbd_ep_t ep, app_usbd_complex_evt_t const * const p_event) -{ - if (NRF_USBD_EP_VALIDATE(ep)) - { - app_usbd_class_inst_t const * p_inst = app_usbd_ep_conf_access(ep)->p_cinst; - if (p_inst != NULL) - { - return class_event_handler(p_inst, p_event); - } - } - return NRF_ERROR_INVALID_ADDR; -} - -void app_usbd_all_call(app_usbd_complex_evt_t const * const p_event) -{ - app_usbd_class_inst_t const * p_inst; - for (p_inst = app_usbd_class_first_get(); NULL != p_inst; - p_inst = app_usbd_class_next_get(p_inst)) - { - UNUSED_RETURN_VALUE(class_event_handler(p_inst, p_event)); - } -} - -ret_code_t app_usbd_all_until_served_call(app_usbd_complex_evt_t const * const p_event) -{ - app_usbd_class_inst_t const * p_inst; - ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; - /* Try to process via every instance */ - for (p_inst = app_usbd_class_first_get(); NULL != p_inst; - p_inst = app_usbd_class_next_get(p_inst)) - { - - ret = class_event_handler(p_inst, p_event); - if (NRF_ERROR_NOT_SUPPORTED != ret) - { - /* Processing finished */ - break; - } - } - - return ret; -} - -ret_code_t app_usbd_ep_transfer( - nrf_drv_usbd_ep_t ep, - nrf_drv_usbd_transfer_t const * const p_transfer) -{ - if (!nrf_drv_usbd_ep_enable_check(ep)) - { - return NRF_ERROR_INVALID_STATE; - } - if (m_sustate != SUSTATE_ACTIVE) - { - return NRF_ERROR_INVALID_STATE; - } - return nrf_drv_usbd_ep_transfer(ep, p_transfer); -} - -ret_code_t app_usbd_ep_handled_transfer( - nrf_drv_usbd_ep_t ep, - nrf_drv_usbd_handler_desc_t const * const p_handler) -{ - if (!nrf_drv_usbd_ep_enable_check(ep)) - { - return NRF_ERROR_INVALID_STATE; - } - if (m_sustate != SUSTATE_ACTIVE) - { - return NRF_ERROR_INVALID_STATE; - } - return nrf_drv_usbd_ep_handled_transfer(ep, p_handler); -} - -ret_code_t app_usbd_iface_select( - app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx, - uint8_t alternate) -{ - ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; - - if (p_inst->p_class_methods->iface_select != NULL) - { - ret = p_inst->p_class_methods->iface_select(p_inst, iface_idx, alternate); - } - - if(ret == NRF_ERROR_NOT_SUPPORTED) - { - ret = default_iface_select(p_inst, iface_idx, alternate); - } - return ret; -} - -void app_usbd_iface_deselect( - app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx) -{ - if (p_inst->p_class_methods->iface_deselect != NULL) - { - p_inst->p_class_methods->iface_deselect(p_inst, iface_idx); - } - default_iface_deselect(p_inst, iface_idx); -} - -uint8_t app_usbd_iface_selection_get( - app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx) -{ - uint8_t alt = 0; - if (p_inst->p_class_methods->iface_selection_get != NULL) - { - alt = p_inst->p_class_methods->iface_selection_get(p_inst, iface_idx); - } - return alt; -} - -void app_usbd_all_iface_select_0(void) -{ - app_usbd_class_inst_t const * p_inst = app_usbd_class_first_get(); - while (p_inst != NULL) - { - uint8_t iface_count = app_usbd_class_iface_count_get(p_inst); - for (uint8_t i = 0; i < iface_count; ++i) - { - ret_code_t ret; - ret = app_usbd_iface_select(p_inst, i, 0); - ASSERT(ret == NRF_SUCCESS); - UNUSED_VARIABLE(ret); - } - p_inst = app_usbd_class_next_get(p_inst); - } -} - -void app_usbd_all_iface_deselect(void) -{ - app_usbd_class_inst_t const * p_inst = app_usbd_class_first_get(); - while (p_inst != NULL) - { - uint8_t iface_count = app_usbd_class_iface_count_get(p_inst); - for (uint8_t i = 0; i < iface_count; ++i) - { - app_usbd_iface_deselect(p_inst, i); - } - p_inst = app_usbd_class_next_get(p_inst); - } -} - -#endif //NRF_MODULE_ENABLED(APP_USBD) +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_USBD) + +#include "app_usbd.h" +#include "app_usbd_core.h" +#include "app_usbd_request.h" +#include "nrf_power.h" +#include "nrf_drv_clock.h" +#include "nrf_drv_power.h" +#if APP_USBD_CONFIG_EVENT_QUEUE_ENABLE +#include "nrf_atfifo.h" +#include "nrf_atomic.h" +#endif + +#define NRF_LOG_MODULE_NAME app_usbd + +#if APP_USBD_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL APP_USBD_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR APP_USBD_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR APP_USBD_CONFIG_DEBUG_COLOR +#else //APP_USBD_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //APP_USBD_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +/* Base variables tests */ + +/* Check event of app_usbd_event_type_t enumerator */ +STATIC_ASSERT((int32_t)APP_USBD_EVT_FIRST_POWER == (int32_t)NRF_DRV_USBD_EVT_CNT); +STATIC_ASSERT(sizeof(app_usbd_event_type_t) == sizeof(nrf_drv_usbd_event_type_t)); + +STATIC_ASSERT(sizeof(app_usbd_descriptor_header_t) == 2); +STATIC_ASSERT(sizeof(app_usbd_descriptor_device_t) == 18); +STATIC_ASSERT(sizeof(app_usbd_descriptor_configuration_t) == 9); +STATIC_ASSERT(sizeof(app_usbd_descriptor_iface_t) == 9); +STATIC_ASSERT(sizeof(app_usbd_descriptor_ep_t) == 7); +STATIC_ASSERT(sizeof(app_usbd_descriptor_iad_t) == 8); + +STATIC_ASSERT(sizeof(app_usbd_setup_t) == sizeof(nrf_drv_usbd_setup_t)); + +/** + * @internal + * @defgroup app_usbd_internals USBD library internals + * @ingroup app_usbd + * + * Internal variables, auxiliary macros and functions of USBD library. + * @{ + */ + +#if (APP_USBD_PROVIDE_SOF_TIMESTAMP) || defined(__SDK_DOXYGEN__) +/** + * @brief The last received frame number. + */ +static uint16_t m_last_frame; +#endif + +/** + * @brief Variable type for endpoint configuration. + * + * Each endpoint would have assigned this type of configuration structure. + */ +typedef struct +{ + /** + * @brief The class instance. + * + * The pointer to the class instance that is connected to the endpoint. + */ + app_usbd_class_inst_t const * p_cinst; + + /** + * @brief Endpoint event handler. + * + * Event handler for the endpoint. + * It is set to event handler for the class instance during connection by default, + * but it can be then updated for as a reaction for @ref APP_USBD_EVT_ATTACHED event. + * This way we can speed up the interpretation of endpoint related events. + */ + app_usbd_ep_event_handler_t event_handler; +}app_usbd_ep_conf_t; + + +/** + * @brief Internal event with SOF counter. + */ +typedef struct +{ + app_usbd_internal_evt_t evt; //!< Internal event type + +#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) \ + || defined(__SDK_DOXYGEN__) + uint16_t sof_cnt; //!< Number of the SOF events that appears before current event + uint16_t start_frame; //!< Number of the SOF frame that starts this event +#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + +} app_usbd_internal_queue_evt_t; + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) +/** + * @brief Event queue. + * + * The queue with events to be processed. + */ +NRF_ATFIFO_DEF(m_event_queue, app_usbd_internal_queue_evt_t, APP_USBD_CONFIG_EVENT_QUEUE_SIZE); + +#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) \ + || defined(__SDK_DOXYGEN__) + +/** @brief SOF events counter */ +static nrf_atomic_u32_t m_sof_events_cnt; + +/** @brief SOF Frame counter */ +static uint16_t m_event_frame; + +/* Limit of SOF events stacked until warning message. */ +#define APP_USBD_SOF_WARNING_LIMIT 500 +#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + // || defined(__SDK_DOXYGEN__) + +#endif + +/** + * @brief Instances connected with IN endpoints. + * + * Array of instance pointers connected with every IN endpoint. + * @sa m_epout_instances + */ +static app_usbd_ep_conf_t m_epin_conf[NRF_USBD_EPIN_CNT]; + +/** + * @brief Instances connected with OUT endpoints. + * + * Array of instance pointers connected with every OUT endpoint. + * @sa m_epin_instances + */ +static app_usbd_ep_conf_t m_epout_conf[NRF_USBD_EPIN_CNT]; + +/** + * @brief Beginning of classes list. + * + * All enabled in current configuration instances are connected into + * a single linked list chain. + * This variable points to first element. + * Core class instance (connected to endpoint 0) is not listed here. + */ +static app_usbd_class_inst_t const * m_p_first_cinst; + +/** + * @brief Classes list that requires SOF events. + * + * Pointer to first class that requires SOF events. + */ +static app_usbd_class_inst_t const * m_p_first_sof_cinst; + +/** + * @brief Classes list that require SOF events in interrupt. + * + * Pointer to first class that requires SOF events in interrupt. + */ +static app_usbd_class_inst_t const * m_p_first_sof_interrupt_cinst; + +/** + * @brief Default configuration (when NULL is passed to @ref app_usbd_init). + */ +static const app_usbd_config_t m_default_conf = { +#if (!(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)) || defined(__SDK_DOXYGEN__) + .ev_handler = app_usbd_event_execute, +#endif +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) + .ev_isr_handler = NULL, +#endif + .ev_state_proc = NULL, + .enable_sof = false +}; + +/** + * @brief SUSPEND state machine states. + * + * The enumeration of internal SUSPEND state machine states. + */ +typedef enum +{ + SUSTATE_STOPPED, /**< The USB driver was not started */ + SUSTATE_STARTED, /**< The USB driver was started - waiting for USB RESET */ + SUSTATE_ACTIVE, /**< Active state */ + SUSTATE_SUSPENDING, /**< Suspending - waiting for the user to acknowledge */ + SUSTATE_SUSPEND, /**< Suspended */ + SUSTATE_RESUMING, /**< Resuming - waiting for clock */ + SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ, /**< Waking up - waiting for clock and WUREQ from driver */ + SUSTATE_WAKINGUP_WAITING_HFCLK, /**< Waking up - waiting for HFCLK (WUREQ detected) */ + SUSTATE_WAKINGUP_WAITING_WREQ, /**< Waking up - waiting for WREQ (HFCLK active) */ +}app_usbd_sustate_t; + +/** + * @brief Current suspend state. + * + * The state of the suspend state machine. + */ +static app_usbd_sustate_t m_sustate; + +/** + * @brief Remote wake-up register/unregister. + * + * Counter incremented when appended instance required remote wake-up functionality. + * It should be decremented when the class is removed. + * When this counter is not zero, remote wake-up functionality is activated inside core. + */ +static uint8_t m_rwu_registered_counter; + +/** + * @brief Current configuration. + */ +static app_usbd_config_t m_current_conf; + +/** + * @brief Class interface call: event handler + * + * @ref app_usbd_class_interface_t::event_handler + * + * @param[in] p_cinst Class instance. + * @param[in] p_event Event passed to class instance. + * + * @return Standard error code @ref ret_code_t + * @retval NRF_SUCCESS event handled successfully. + * @retval NRF_ERROR_NOT_SUPPORTED unsupported event. + * */ +static inline ret_code_t class_event_handler(app_usbd_class_inst_t const * const p_cinst, + app_usbd_complex_evt_t const * const p_event) +{ + ASSERT(p_cinst != NULL); + ASSERT(p_cinst->p_class_methods != NULL); + ASSERT(p_cinst->p_class_methods->event_handler != NULL); + return p_cinst->p_class_methods->event_handler(p_cinst, p_event); +} + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) +static inline void class_sof_interrupt_handler(app_usbd_class_inst_t const * const p_cinst, + app_usbd_complex_evt_t const * const p_event) +{ + ASSERT(p_cinst != NULL); + ASSERT(p_cinst->p_data != NULL); + ASSERT(p_cinst->p_data->sof_handler != NULL); + p_cinst->p_data->sof_handler(p_event->drv_evt.data.sof.framecnt); +} + +/** + * @brief User event handler call (passed via configuration). + * + * @param p_event Handler of an event that is going to be added into queue. + * @param queued The event is visible in the queue. + */ +static inline void user_event_handler(app_usbd_internal_evt_t const * const p_event, bool queued) +{ + if ((m_current_conf.ev_isr_handler) != NULL) + { + m_current_conf.ev_isr_handler(p_event, queued); + } +} +#endif + +/** + * @brief User event processor call (passed via configuration). + * + * @param event Event type. + */ +static inline void user_event_state_proc(app_usbd_event_type_t event) +{ + if ((m_current_conf.ev_state_proc) != NULL) + { + m_current_conf.ev_state_proc(event); + } +} + +/** + * @brief Find a specified descriptor. + * + * @param[in] p_cinst Class instance. + * @param[in] desc_type Descriptor type @ref app_usbd_descriptor_t + * @param[in] desc_index Descriptor index. + * @param[out] p_desc Pointer to escriptor. + * @param[out] p_desc_len Length of descriptor. + * + * @return Standard error code @ref ret_code_t + * @retval NRF_SUCCESS Descriptor successfully found. + * @retval NRF_ERROR_NOT_FOUND Descriptor not found. + * */ +ret_code_t app_usbd_class_descriptor_find(app_usbd_class_inst_t const * const p_cinst, + uint8_t desc_type, + uint8_t desc_index, + uint8_t * p_desc, + size_t * p_desc_len) +{ + app_usbd_class_descriptor_ctx_t siz; + APP_USBD_CLASS_DESCRIPTOR_INIT(&siz); + uint32_t total_size = 0; + while(p_cinst->p_class_methods->feed_descriptors(&siz, p_cinst, NULL, sizeof(uint8_t))) + { + total_size++; + } + + uint8_t cur_len = 0; + uint32_t cur_size = 0; + + uint8_t index = 0; + app_usbd_class_descriptor_ctx_t descr; + APP_USBD_CLASS_DESCRIPTOR_INIT(&descr); + + while(cur_size < total_size) + { + /* First byte of a descriptor is its size */ + UNUSED_RETURN_VALUE(p_cinst->p_class_methods->feed_descriptors(&descr, + p_cinst, + &cur_len, + sizeof(uint8_t))); + + /* Second byte is type of the descriptor */ + uint8_t type; + UNUSED_RETURN_VALUE(p_cinst->p_class_methods->feed_descriptors(&descr, + p_cinst, + &type, + sizeof(uint8_t))); + + if(type == desc_type) + { + if(index == desc_index) + { + /* Copy the length of descriptor to *p_desc_len */ + *p_desc_len = cur_len; + /* Two first bytes of descriptor have already been fed - copy them to *p_desc */ + *p_desc++ = cur_len; + *p_desc++ = desc_type; + /* Copy the rest of descriptor to *p_desc */ + UNUSED_RETURN_VALUE(p_cinst->p_class_methods->feed_descriptors(&descr, + p_cinst, + p_desc, + cur_len-2)); + return NRF_SUCCESS; + } + else + { + index++; + } + } + /* Fast-forward through unmatched descriptor */ + UNUSED_RETURN_VALUE(p_cinst->p_class_methods->feed_descriptors(&descr, + p_cinst, + NULL, + cur_len-2)); + cur_size += cur_len; + } + return NRF_ERROR_NOT_FOUND; +} + +/** + * @brief Access into selected endpoint configuration structure. + * + * @param ep Endpoint address. + * @return A pointer to the endpoint configuration structure. + * + * @note This function would assert when endpoint number is not correct and debugging is enabled. + */ +static app_usbd_ep_conf_t * app_usbd_ep_conf_access(nrf_drv_usbd_ep_t ep) +{ + if (NRF_USBD_EPIN_CHECK(ep)) + { + uint8_t nr = NRF_USBD_EP_NR_GET(ep); + ASSERT(nr < NRF_USBD_EPIN_CNT); + return &m_epin_conf[nr]; + } + else + { + uint8_t nr = NRF_USBD_EP_NR_GET(ep); + ASSERT(nr < NRF_USBD_EPOUT_CNT); + return &m_epout_conf[nr]; + } +} + +/** + * @brief Accessing instance connected with selected endpoint. + * + * @param ep Endpoint number. + * + * @return The pointer to the instance connected with endpoint. + */ +static inline app_usbd_class_inst_t const * app_usbd_ep_instance_get(nrf_drv_usbd_ep_t ep) +{ + return app_usbd_ep_conf_access(ep)->p_cinst; +} + +/** + * @brief Connect instance with selected endpoint. + * + * This function configures instance connected to endpoint but also sets + * default event handler function pointer. + * + * @param ep Endpoint number. + * @param p_cinst The instance to connect into the selected endpoint. + * NULL if endpoint is going to be disconnected. + * + * @note Disconnecting EP0 is not allowed and protected by assertion. + */ +static void app_usbd_ep_instance_set(nrf_drv_usbd_ep_t ep, app_usbd_class_inst_t const * p_cinst) +{ + app_usbd_ep_conf_t * p_ep_conf = app_usbd_ep_conf_access(ep); + /* Set instance and default event handler */ + p_ep_conf->p_cinst = p_cinst; + if (p_cinst == NULL) + { + ASSERT((ep != NRF_DRV_USBD_EPOUT0) && (ep != NRF_DRV_USBD_EPIN0)); /* EP0 should never be disconnected */ + p_ep_conf->event_handler = NULL; + } + else + { + p_ep_conf->event_handler = p_cinst->p_class_methods->event_handler; + } +} + +/** + * @brief Call the core handler. + * + * Core instance is special kind of instance that is connected only to endpoint 0. + * It is not present in instance list. + * This auxiliary function makes future changes easier. + * Just call the event instance for core module here. + */ +static inline ret_code_t app_usbd_core_handler_call(app_usbd_internal_evt_t const * const p_event) +{ + return m_epout_conf[0].event_handler( + m_epout_conf[0].p_cinst, + (app_usbd_complex_evt_t const *)p_event); +} + + + +/** + * @brief Add event for execution. + * + * Dependent on configuration event would be executed in place or would be added into queue + * to be executed later. + * + * @param p_event_input Event to be executed. + */ +static inline void app_usbd_event_add(app_usbd_internal_evt_t const * const p_event_input) +{ + app_usbd_internal_evt_t const * p_event = p_event_input; + + + if (p_event->type == APP_USBD_EVT_DRV_SETUP) + { + uint8_t bRequest = nrf_usbd_setup_brequest_get(); + uint8_t bmRequestType = nrf_usbd_setup_bmrequesttype_get(); + + if ((bmRequestType == app_usbd_setup_req_val( + APP_USBD_SETUP_REQREC_DEVICE, + APP_USBD_SETUP_REQTYPE_STD, + APP_USBD_SETUP_REQDIR_OUT)) + && (bRequest == APP_USBD_SETUP_STDREQ_SET_ADDRESS)) + { + static const app_usbd_internal_evt_t event_setaddress = + { + .type = APP_USBD_EVT_SETUP_SETADDRESS, + }; + p_event = &event_setaddress; + } + } + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) + + if (p_event->app_evt.type == APP_USBD_EVT_DRV_SOF) + { + /* Propagate SOF event to classes that need it in interrupt */ + app_usbd_class_inst_t const * p_inst = app_usbd_class_sof_interrupt_first_get(); + while (NULL != p_inst) + { + class_sof_interrupt_handler(p_inst, (app_usbd_complex_evt_t const *)p_event); + p_inst = app_usbd_class_sof_interrupt_next_get(p_inst); + } + +#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + CRITICAL_REGION_ENTER(); + if (m_sof_events_cnt == 0) + { + m_event_frame = p_event->drv_evt.data.sof.framecnt; + } + UNUSED_RETURN_VALUE(nrf_atomic_u32_add(&m_sof_events_cnt, 1)); + CRITICAL_REGION_EXIT(); + + user_event_handler(p_event, true); + if (m_sof_events_cnt == APP_USBD_SOF_WARNING_LIMIT) + { + NRF_LOG_WARNING("Stacked over %d SOF events.", APP_USBD_SOF_WARNING_LIMIT); + } + return; + +#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + +#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_INTERRUPT) + + user_event_handler(p_event, false); + app_usbd_event_execute(p_event); + return; + +#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_INTERRUPT) + } + + nrf_atfifo_item_put_t cx; + app_usbd_internal_queue_evt_t * p_event_item = nrf_atfifo_item_alloc(m_event_queue, &cx); + + if (NULL != p_event_item) + { + bool visible; + p_event_item->evt = *p_event; + +#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + CRITICAL_REGION_ENTER(); + p_event_item->start_frame = m_event_frame - m_sof_events_cnt + 1; + p_event_item->sof_cnt = nrf_atomic_u32_fetch_store(&m_sof_events_cnt, 0); + CRITICAL_REGION_EXIT(); +#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + + visible = nrf_atfifo_item_put(m_event_queue, &cx); + user_event_handler(p_event, visible); + } + else + { + NRF_LOG_ERROR("Event queue full."); + } +#else + m_current_conf.ev_handler(p_event); +#endif +} + +/** + * @brief Power event handler. + * + * The function that pushes power events into the queue. + * @param p_event Event from power driver to map into APP_USBD_EVT_POWER_ event. + */ +#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS +static void app_usbd_power_event_handler(nrf_drv_power_usb_evt_t event) +{ + switch(event) + { + case NRF_DRV_POWER_USB_EVT_DETECTED: + { + static const app_usbd_internal_evt_t ev = { + .type = APP_USBD_EVT_POWER_DETECTED + }; + app_usbd_event_add(&ev); + break; + } + case NRF_DRV_POWER_USB_EVT_REMOVED: + { + static const app_usbd_internal_evt_t ev = { + .type = APP_USBD_EVT_POWER_REMOVED + }; + app_usbd_event_add(&ev); + break; + } + case NRF_DRV_POWER_USB_EVT_READY: + { + static const app_usbd_internal_evt_t ev = { + .type = APP_USBD_EVT_POWER_READY + }; + app_usbd_event_add(&ev); + break; + } + default: + ASSERT(false); + } +} +#endif + +/** + * @brief Event handler. + * + * The function that pushes the event into the queue. + * @param p_event Event to push. + */ +static void app_usbd_event_handler(nrf_drv_usbd_evt_t const * const p_event) +{ + app_usbd_event_add((app_usbd_internal_evt_t const *)p_event); +} + +/** + * @brief HF clock ready event handler. + * + * Function that is called when high frequency clock is started. + * + * @param event Event type that comes from clock driver. + */ +static void app_usbd_hfclk_ready(nrf_drv_clock_evt_type_t event) +{ + ASSERT(NRF_DRV_CLOCK_EVT_HFCLK_STARTED == event); + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_HFCLK_READY + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); +} + +/** + * @brief Check if the HFCLK was requested in selected suspend state machine state. + * + * + * @param sustate State to be checked. + * + * @retval true High frequency clock was requested in selected state. + * @retval false High frequency clock was released in selected state. + */ +static inline bool app_usbd_sustate_with_requested_hfclk(app_usbd_sustate_t sustate) +{ + switch(sustate) + { + case SUSTATE_STOPPED: return false; + case SUSTATE_STARTED: return false; + case SUSTATE_ACTIVE: return true; + case SUSTATE_SUSPENDING: return false; + case SUSTATE_SUSPEND: return false; + case SUSTATE_RESUMING: return true; + case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: return true; + case SUSTATE_WAKINGUP_WAITING_HFCLK: return true; + case SUSTATE_WAKINGUP_WAITING_WREQ: return true; + default: + return false; + } +} + +/** + * @brief Check it the HFCLK is running in selected suspend state machine state. + * + * @param sustate State to be checked. + * + * @retval true High frequency clock is running in selected state. + * @retval false High frequency clock is released in selected state. + */ +static inline bool app_usbd_sustate_with_running_hfclk(app_usbd_sustate_t sustate) +{ + switch(sustate) + { + case SUSTATE_STOPPED: return false; + case SUSTATE_STARTED: return false; + case SUSTATE_ACTIVE: return true; + case SUSTATE_SUSPENDING: return false; + case SUSTATE_SUSPEND: return false; + case SUSTATE_RESUMING: return false; + case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: return false; + case SUSTATE_WAKINGUP_WAITING_HFCLK: return false; + case SUSTATE_WAKINGUP_WAITING_WREQ: return true; + default: + return false; + } +} + +/** + * @brief Get current suspend state machine state. + * + * @return The state of the suspend state machine. + */ +static inline app_usbd_sustate_t sustate_get(void) +{ + return m_sustate; +} + +/** + * @brief Set current suspend state machine state. + * + * @param sustate The requested state of the state machine. + */ +static inline void sustate_set(app_usbd_sustate_t sustate) +{ + if (app_usbd_sustate_with_requested_hfclk(sustate) != app_usbd_sustate_with_requested_hfclk(m_sustate)) + { + if (app_usbd_sustate_with_requested_hfclk(sustate)) + { + static nrf_drv_clock_handler_item_t clock_handler_item = + { + .event_handler = app_usbd_hfclk_ready + }; + nrf_drv_clock_hfclk_request(&clock_handler_item); + } + else + { + nrf_drv_clock_hfclk_release(); + } + } + if (app_usbd_sustate_with_running_hfclk(sustate) != app_usbd_sustate_with_running_hfclk(m_sustate)) + { + if (app_usbd_sustate_with_running_hfclk(sustate)) + { + nrf_drv_usbd_active_irq_config(); + } + else + { + nrf_drv_usbd_suspend_irq_config(); + } + } + m_sustate = sustate; +} + +/** + * @brief Default selection function for interface. + * + * This function just enables and clears interface endpoints. + * + * @param[in] p_inst Class instance. + * @param[in] iface_idx Interface index. + * @param[in] alternate Interface alternate setting. + * + * @note Currently only alternate setting 0 is supported. + * + * @return Standard error code @ref ret_code_t + * @retval NRF_SUCCESS Endpoints enabled and cleared. + * @retval NRF_ERROR_INVALID_PARAM Unsupported alternate selected. + */ +static inline ret_code_t default_iface_select( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx, + uint8_t alternate) +{ + ASSERT(iface_idx <= app_usbd_class_iface_count_get(p_inst)); + + if (alternate != 0) + { + return NRF_ERROR_INVALID_PARAM; + } + + app_usbd_class_iface_conf_t const * p_iface = app_usbd_class_iface_get(p_inst, iface_idx); + uint8_t ep_count = app_usbd_class_iface_ep_count_get(p_iface); + + for (uint8_t i = 0; i < ep_count; ++i) + { + /* Enable every endpoint */ + app_usbd_class_ep_conf_t const * p_ep = app_usbd_class_iface_ep_get(p_iface, i); + app_usbd_ep_enable(p_ep->address); + } + return NRF_SUCCESS; +} + +/** + * @brief Default deselection function for interface. + * + * This function just disables all interface endpoints. + * + * @param[in] p_inst Class instance. + * @param[in] iface_idx Interface index. + */ +static inline void default_iface_deselect( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx) +{ + ASSERT(iface_idx <= app_usbd_class_iface_count_get(p_inst)); + + app_usbd_class_iface_conf_t const * p_iface = app_usbd_class_iface_get(p_inst, iface_idx); + uint8_t ep_count = app_usbd_class_iface_ep_count_get(p_iface); + + for (uint8_t i = 0; i < ep_count; ++i) + { + /* Disable every endpoint */ + app_usbd_class_ep_conf_t const * p_ep = app_usbd_class_iface_ep_get(p_iface, i); + app_usbd_ep_disable(p_ep->address); + } +} + + +/** @} */ + +#if (APP_USBD_PROVIDE_SOF_TIMESTAMP) || defined(__SDK_DOXYGEN__) +uint32_t app_usbd_sof_timestamp_get(void) +{ + return m_last_frame; +} +#endif + +ret_code_t app_usbd_init(app_usbd_config_t const * p_config) +{ + ASSERT(nrf_drv_clock_init_check()); + ret_code_t ret; + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) + ret = NRF_ATFIFO_INIT(m_event_queue); + if (NRF_SUCCESS != ret) + { + return NRF_ERROR_INTERNAL; + } +#endif + + /* This is called at the beginning to secure multiple calls to init function */ + ret = nrf_drv_usbd_init(app_usbd_event_handler); + if (NRF_SUCCESS != ret) + { + return ret; + } + + /* Clear the variables */ + m_sustate = SUSTATE_STOPPED; + m_p_first_cinst = NULL; + m_p_first_sof_cinst = NULL; + memset(m_epin_conf , 0, sizeof(m_epin_conf )); + memset(m_epout_conf, 0, sizeof(m_epout_conf)); + /* Save the new configuration */ + if (p_config == NULL) + { + m_current_conf = m_default_conf; + } + else + { + m_current_conf = *p_config; + } + +#if (!(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)) + if(m_current_conf.ev_handler == NULL) + { + m_current_conf.ev_handler = m_default_conf.ev_handler; + } +#endif + +#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS + ret = nrf_drv_power_init(NULL); + if ((ret != NRF_SUCCESS) && (ret != NRF_ERROR_MODULE_ALREADY_INITIALIZED)) + { + /* This should never happen */ + APP_ERROR_HANDLER(ret); + } +#endif + + /*Pin core class to required endpoints*/ + uint8_t iface_idx; + app_usbd_class_iface_conf_t const * p_iface; + app_usbd_class_inst_t const * const p_inst = app_usbd_core_instance_access(); + iface_idx = 0; + while ((p_iface = app_usbd_class_iface_get(p_inst, iface_idx++)) != NULL) + { + uint8_t ep_idx = 0; + app_usbd_class_ep_conf_t const * p_ep; + while ((p_ep = app_usbd_class_iface_ep_get(p_iface, ep_idx++)) != NULL) + { + app_usbd_ep_instance_set(app_usbd_class_ep_address_get(p_ep), p_inst); + } + } + + /* Successfully attached */ + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_INST_APPEND + }; + + ret = class_event_handler(p_inst, (app_usbd_complex_evt_t const *)(&evt_data)); + if (NRF_SUCCESS != ret) + { + UNUSED_RETURN_VALUE(nrf_drv_usbd_uninit()); + return ret; + } + + return NRF_SUCCESS; +} + + +ret_code_t app_usbd_uninit(void) +{ +#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS + nrf_drv_power_usbevt_uninit(); +#endif + + /* We get this error at very beginning but it would be used at the end of the function */ + const ret_code_t ret = nrf_drv_usbd_uninit(); + + /* Unchain instance list */ + app_usbd_class_inst_t const * * pp_inst; + pp_inst = &m_p_first_cinst; + while (NULL != (*pp_inst)) + { + app_usbd_class_inst_t const * * pp_next = &app_usbd_class_data_access(*pp_inst)->p_next; + (*pp_inst) = NULL; + pp_inst = pp_next; + } + + /* Unchain SOF list */ + pp_inst = &m_p_first_sof_cinst; + while (NULL != (*pp_inst)) + { + app_usbd_class_inst_t const * * pp_next = &app_usbd_class_data_access(*pp_inst)->p_sof_next; + (*pp_inst) = NULL; + pp_inst = pp_next; + } + + /* Unchain SOF interrupt list */ + pp_inst = &m_p_first_sof_interrupt_cinst; + while (NULL != (*pp_inst)) + { + app_usbd_class_inst_t const * * pp_next = &app_usbd_class_data_access(*pp_inst)->p_sof_next; + (*pp_inst) = NULL; + pp_inst = pp_next; + } + + /* Clear all endpoints configurations */ + memset(m_epin_conf , 0, sizeof(m_epin_conf )); + memset(m_epout_conf, 0, sizeof(m_epout_conf)); + /* Clear current configuration */ + memset(&m_current_conf, 0, sizeof(m_current_conf)); + + return ret; +} + + +#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS +ret_code_t app_usbd_power_events_enable(void) +{ + if (!nrf_drv_usbd_is_initialized() || nrf_drv_usbd_is_enabled()) + { + return NRF_ERROR_INVALID_STATE; + } + + ASSERT((!APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || (USBD_CONFIG_IRQ_PRIORITY == POWER_CONFIG_IRQ_PRIORITY)); + + ret_code_t ret; + static const nrf_drv_power_usbevt_config_t config = + { + .handler = app_usbd_power_event_handler + }; + + ret = nrf_drv_power_usbevt_init(&config); + APP_ERROR_CHECK(ret); + + return NRF_SUCCESS; +} +#endif /* APP_USBD_CONFIG_POWER_EVENTS_PROCESS */ + + +void app_usbd_enable(void) +{ + nrf_drv_usbd_enable(); +} + + +void app_usbd_disable(void) +{ + ASSERT(!nrf_drv_usbd_is_started()); + nrf_drv_usbd_disable(); +} + + +void app_usbd_start(void) +{ + ASSERT(nrf_drv_usbd_is_enabled()); + + /* Check if interface numbers are in correct order */ + if (APP_USBD_CONFIG_LOG_ENABLED) + { + uint8_t next_iface = 0; + for (app_usbd_class_inst_t const * * pp_inst = &m_p_first_cinst; + (*pp_inst) != NULL; + pp_inst = &(app_usbd_class_data_access(*pp_inst)->p_next)) + { + uint8_t iface_idx = 0; + app_usbd_class_iface_conf_t const * p_iface; + while (NULL != (p_iface = app_usbd_class_iface_get(*pp_inst, iface_idx++))) + { + if (p_iface->number != next_iface) + { + NRF_LOG_WARNING("Unexpected interface number, expected %d, got %d", + next_iface, + p_iface->number); + } + ++next_iface; + } + } + } + + /* Power should be already enabled - wait just in case if user calls + * app_usbd_start just after app_usbd_enable without waiting for the event. */ + while (!nrf_power_usbregstatus_outrdy_get()) + { + /* Wait for the power but terminate the function if USBD power disappears */ + if (!nrf_power_usbregstatus_vbusdet_get()) + return; + } + + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_START_REQ + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); +} + + +void app_usbd_stop(void) +{ + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_STOP_REQ + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); +} + +void app_usbd_suspend_req(void) +{ + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_SUSPEND_REQ + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); +} + +bool app_usbd_wakeup_req(void) +{ + ASSERT(app_usbd_class_rwu_enabled_check()); + if (!app_usbd_core_feature_state_get(APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP)) + return false; + + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_WAKEUP_REQ + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); + return true; +} + +bool app_usbd_active_check(void) +{ + return (sustate_get() == SUSTATE_ACTIVE); +} + +void app_usbd_event_execute(app_usbd_internal_evt_t const * const p_event) +{ + ASSERT(NULL != m_p_first_cinst); + /* If no event queue is implemented, it has to be ensured that this function is never called + * from the context higher than USB interrupt level + * If queue is implemented it would be called always from Thread level + * if the library is used correctly. + * NOTE: Higher interrupt level -> lower priority value. + */ + ASSERT(USBD_CONFIG_IRQ_PRIORITY <= current_int_priority_get()); + + /* Note - there should never be situation that event is generated on disconnected endpoint */ + switch (p_event->type) + { + case APP_USBD_EVT_START_REQ: + { + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_STARTED + }; + + /* Send event to all classes */ + UNUSED_RETURN_VALUE(app_usbd_core_handler_call((app_usbd_internal_evt_t const * )&evt_data)); + app_usbd_all_call((app_usbd_complex_evt_t const *)&evt_data); + user_event_state_proc(APP_USBD_EVT_STARTED); + + app_usbd_all_iface_deselect(); + app_usbd_core_ep0_disable(); + nrf_drv_usbd_start((NULL != m_p_first_sof_cinst) || (m_current_conf.enable_sof) || (APP_USBD_PROVIDE_SOF_TIMESTAMP)); + sustate_set(SUSTATE_STARTED); + break; + } + case APP_USBD_EVT_STOP_REQ: + { + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_STOPPED + }; + + app_usbd_all_iface_deselect(); + nrf_drv_usbd_stop(); + sustate_set(SUSTATE_STOPPED); + + /* Send event to all classes */ + app_usbd_all_call((app_usbd_complex_evt_t const * )&evt_data); + UNUSED_RETURN_VALUE(app_usbd_core_handler_call((app_usbd_internal_evt_t const *)&evt_data)); + user_event_state_proc(APP_USBD_EVT_STOPPED); + if (app_usbd_sustate_with_requested_hfclk(sustate_get())) + { + nrf_drv_clock_hfclk_release(); + } + + break; + } + case APP_USBD_EVT_HFCLK_READY: + { + switch(sustate_get()) + { + case SUSTATE_RESUMING: + { + sustate_set(SUSTATE_ACTIVE); + break; + } + case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: + { + sustate_set(SUSTATE_WAKINGUP_WAITING_WREQ); + break; + } + case SUSTATE_WAKINGUP_WAITING_HFCLK: + { + sustate_set(SUSTATE_ACTIVE); + break; + } + default: + break; // Just ignore - it can happen in specific situation + } + break; + } + case APP_USBD_EVT_SUSPEND_REQ: + { + /* Suspend request can be only processed when we are in suspending state */ + if (SUSTATE_SUSPENDING == sustate_get()) + { + if (nrf_drv_usbd_suspend()) + { + sustate_set(SUSTATE_SUSPEND); + } + } + break; + } + case APP_USBD_EVT_WAKEUP_REQ: + { + /* Suspend temporary if no suspend function was called from the application. + * This makes it possible to generate APP_USBD_EVT_DRV_WUREQ event from the driver */ + if (sustate_get() == SUSTATE_SUSPENDING) + { + if (nrf_drv_usbd_suspend()) + { + sustate_set(SUSTATE_SUSPEND); + } + } + if (nrf_drv_usbd_wakeup_req()) + { + sustate_set(SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ); + } + break; + } + + case APP_USBD_EVT_DRV_SOF: + { +#if (APP_USBD_PROVIDE_SOF_TIMESTAMP) || defined(__SDK_DOXYGEN__) + m_last_frame = p_event->drv_evt.data.sof.framecnt; +#endif + /* Wake up if suspended */ + if ((sustate_get() == SUSTATE_SUSPENDING) || (sustate_get() == SUSTATE_WAKINGUP_WAITING_WREQ)) + { + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_DRV_RESUME + }; + app_usbd_event_execute((app_usbd_internal_evt_t *)&evt_data); + } + + user_event_state_proc(APP_USBD_EVT_DRV_SOF); + + app_usbd_class_inst_t const * p_inst = app_usbd_class_sof_first_get(); + while (NULL != p_inst) + { + ret_code_t r = class_event_handler(p_inst, (app_usbd_complex_evt_t const *)p_event); + UNUSED_VARIABLE(r); + p_inst = app_usbd_class_sof_next_get(p_inst); + } + break; + } + + case APP_USBD_EVT_DRV_RESET: + { + app_usbd_all_iface_deselect(); + app_usbd_core_ep0_enable(); + sustate_set(SUSTATE_ACTIVE); + user_event_state_proc(APP_USBD_EVT_DRV_RESET); + /* Processing core interface (connected only to EP0) and then all instances from the list */ + UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + break; + } + case APP_USBD_EVT_DRV_RESUME: + { + if (sustate_get() == SUSTATE_WAKINGUP_WAITING_WREQ) + { + sustate_set(SUSTATE_ACTIVE); + nrf_drv_usbd_force_bus_wakeup(); + } + else + { + sustate_set(SUSTATE_RESUMING); + } + user_event_state_proc(APP_USBD_EVT_DRV_RESUME); + /* Processing core interface (connected only to EP0) and then all instances from the list */ + UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + break; + } + case APP_USBD_EVT_DRV_WUREQ: + { + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_DRV_RESUME + }; + user_event_state_proc(APP_USBD_EVT_DRV_RESUME); + /* Processing core interface (connected only to EP0) and then all instances from the list */ + UNUSED_RETURN_VALUE(app_usbd_core_handler_call((app_usbd_internal_evt_t const *)&evt_data)); + app_usbd_all_call((app_usbd_complex_evt_t const *)&evt_data); + + switch(sustate_get()) + { + case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: + sustate_set(SUSTATE_WAKINGUP_WAITING_HFCLK); + break; + case SUSTATE_WAKINGUP_WAITING_WREQ: + sustate_set(SUSTATE_ACTIVE); + break; + default: + { + /* This should not happen - but try to recover by setting directly active state */ + NRF_LOG_WARNING("Unexpected state on WUREQ event (%u)", sustate_get()); + sustate_set(SUSTATE_ACTIVE); + } + } + break; + } + case APP_USBD_EVT_DRV_SUSPEND: + { + sustate_set(SUSTATE_SUSPENDING); + + user_event_state_proc(APP_USBD_EVT_DRV_SUSPEND); + + /* Processing all instances from the list and then core interface (connected only to EP0) */ + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); + break; + } + + case APP_USBD_EVT_STATE_CHANGED: + { + user_event_state_proc(APP_USBD_EVT_STATE_CHANGED); + /* Processing all instances from the list and then core interface (connected only to EP0) */ + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + break; + } + + case APP_USBD_EVT_DRV_SETUP: + { + UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); + break; + } + + case APP_USBD_EVT_SETUP_SETADDRESS: + { + UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); + break; + } + + case APP_USBD_EVT_DRV_EPTRANSFER: + { + app_usbd_ep_conf_t const * p_ep_conf = + app_usbd_ep_conf_access(p_event->drv_evt.data.eptransfer.ep); + ASSERT(NULL != p_ep_conf->p_cinst); + ASSERT(NULL != p_ep_conf->event_handler); + + if (NRF_SUCCESS != p_ep_conf->event_handler(p_ep_conf->p_cinst, + (app_usbd_complex_evt_t const *)p_event)) + { + /* If error returned, every bulk/interrupt endpoint would be stalled */ + if (!(0 == NRF_USBD_EP_NR_GET(p_event->drv_evt.data.eptransfer.ep) || + NRF_USBD_EPISO_CHECK(p_event->drv_evt.data.eptransfer.ep))) + { + nrf_drv_usbd_ep_stall(p_event->drv_evt.data.eptransfer.ep); + } + } + break; + } +#if APP_USBD_CONFIG_POWER_EVENTS_PROCESS + case APP_USBD_EVT_POWER_DETECTED: + { + user_event_state_proc(APP_USBD_EVT_POWER_DETECTED); + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + break; + } + case APP_USBD_EVT_POWER_REMOVED: + { + user_event_state_proc(APP_USBD_EVT_POWER_REMOVED); + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + break; + } + case APP_USBD_EVT_POWER_READY: + { + user_event_state_proc(APP_USBD_EVT_POWER_READY); + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + break; + } +#endif + default: + ASSERT(0); + break; + } +} + + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) +bool app_usbd_event_queue_process(void) +{ +#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + app_usbd_internal_evt_t sof_event = { + .app_evt.type = APP_USBD_EVT_DRV_SOF + }; +#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + static nrf_atfifo_item_get_t cx; + static app_usbd_internal_queue_evt_t * p_event_item = NULL; + if (NULL == p_event_item) + { + p_event_item = nrf_atfifo_item_get(m_event_queue, &cx); + } + + if (NULL != p_event_item) + { + +#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + if (p_event_item->sof_cnt > 0) + { + if (p_event_item->start_frame > USBD_FRAMECNTR_FRAMECNTR_Msk) + { + p_event_item->start_frame = 0; + } + sof_event.drv_evt.data.sof.framecnt = (p_event_item->start_frame)++; + --(p_event_item->sof_cnt); + app_usbd_event_execute(&sof_event); + return true; + } +#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + + app_usbd_event_execute(&(p_event_item->evt)); + UNUSED_RETURN_VALUE(nrf_atfifo_item_free(m_event_queue, &cx)); + p_event_item = NULL; + return true; + } +#if (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + else if (m_sof_events_cnt > 0) + { + CRITICAL_REGION_ENTER(); + if (m_event_frame > USBD_FRAMECNTR_FRAMECNTR_Msk) + { + m_event_frame = 0; + } + sof_event.drv_evt.data.sof.framecnt = m_event_frame++; + UNUSED_RETURN_VALUE(nrf_atomic_u32_sub_hs(&m_sof_events_cnt, 1)); + CRITICAL_REGION_EXIT(); + app_usbd_event_execute(&sof_event); + return true; + } +#endif // (APP_USBD_CONFIG_SOF_HANDLING_MODE == APP_USBD_SOF_HANDLING_COMPRESS_QUEUE) + else + { + return false; + } +} +#endif + + +ret_code_t app_usbd_class_append(app_usbd_class_inst_t const * p_cinst) +{ + ASSERT(NULL != p_cinst); + ASSERT(NULL != p_cinst->p_class_methods); + ASSERT(NULL != p_cinst->p_class_methods->event_handler); + ASSERT(NULL == app_usbd_class_data_access(p_cinst)->p_next); + + /* This should be only called if USBD is disabled + * We simply assume that USBD is enabled if its interrupts are */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + /* Check if all required endpoints are available + * Checking is splitted from setting to avoid situation that anything + * is modified and then operation finishes with error */ + uint8_t iface_idx; + app_usbd_class_iface_conf_t const * p_iface; + + iface_idx = 0; + while (NULL != (p_iface = app_usbd_class_iface_get(p_cinst, iface_idx++))) + { + uint8_t ep_idx = 0; + app_usbd_class_ep_conf_t const * p_ep; + while (NULL != (p_ep = app_usbd_class_iface_ep_get(p_iface, ep_idx++))) + { + if (NULL != app_usbd_ep_instance_get(app_usbd_class_ep_address_get(p_ep))) + { + return NRF_ERROR_BUSY; + } + } + } + + /* Connecting all required endpoints */ + iface_idx = 0; + while (NULL != (p_iface = app_usbd_class_iface_get(p_cinst, iface_idx++))) + { + uint8_t ep_idx = 0; + app_usbd_class_ep_conf_t const * p_ep; + while (NULL != (p_ep = app_usbd_class_iface_ep_get(p_iface, ep_idx++))) + { + app_usbd_ep_instance_set(app_usbd_class_ep_address_get(p_ep), p_cinst); + } + } + + /* Adding pointer to this instance to the end of the chain */ + app_usbd_class_inst_t const * * pp_last = &m_p_first_cinst; + while (NULL != (*pp_last)) + { + ASSERT((*pp_last) != p_cinst); + pp_last = &(app_usbd_class_data_access(*pp_last)->p_next); + } + (*pp_last) = p_cinst; + + /* Successfully attached */ + const app_usbd_evt_t evt_data = {.type = APP_USBD_EVT_INST_APPEND }; + return class_event_handler(p_cinst, (app_usbd_complex_evt_t const *)(&evt_data)); +} + + +ret_code_t app_usbd_class_remove(app_usbd_class_inst_t const * p_cinst) +{ + ASSERT(NULL != p_cinst); + ASSERT(NULL != p_cinst->p_class_methods); + ASSERT(NULL != p_cinst->p_class_methods->event_handler); + /* This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + ret_code_t ret; + /* Remove this class from the chain */ + app_usbd_class_inst_t const * * pp_last = &m_p_first_cinst; + while (NULL != (*pp_last)) + { + if ((*pp_last) == p_cinst) + { + /* Inform class instance that removing process is going to be started */ + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_INST_REMOVE + }; + ret = class_event_handler(p_cinst, (app_usbd_complex_evt_t const *)(&evt_data)); + if (ret != NRF_SUCCESS) + { + return ret; + } + + /* Breaking chain */ + (*pp_last) = (app_usbd_class_data_access(p_cinst)->p_next); + app_usbd_class_data_access(p_cinst)->p_next = NULL; + + /* Disconnecting endpoints */ + uint8_t ep_idx; + for (ep_idx = 0; ep_idx < NRF_USBD_EPIN_CNT; ++ep_idx) + { + nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPIN(ep_idx); + if (app_usbd_ep_instance_get(ep) == p_cinst) + { + app_usbd_ep_instance_set(ep, NULL); + } + } + for (ep_idx = 0; ep_idx < NRF_USBD_EPOUT_CNT; ++ep_idx) + { + nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPOUT(ep_idx); + if (app_usbd_ep_instance_get(ep) == p_cinst) + { + app_usbd_ep_instance_set(ep, NULL); + } + } + + return NRF_SUCCESS; + } + pp_last = &(app_usbd_class_data_access(*pp_last)->p_next); + } + + return NRF_ERROR_NOT_FOUND; +} + + +ret_code_t app_usbd_class_remove_all(void) +{ + ret_code_t ret = NRF_SUCCESS; + while (NULL != m_p_first_cinst) + { + ret = app_usbd_class_remove(m_p_first_cinst); + if (ret != NRF_SUCCESS) + { + break; + } + } + + return ret; +} + + +ret_code_t app_usbd_ep_handler_set(app_usbd_class_inst_t const * const p_cinst, + nrf_drv_usbd_ep_t ep, + app_usbd_ep_event_handler_t handler) +{ + ASSERT(NULL != p_cinst); + ASSERT(NULL != handler); + /* This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + if (p_cinst != app_usbd_ep_instance_get(ep)) + { + return NRF_ERROR_INVALID_PARAM; + } + + (app_usbd_ep_conf_access(ep))->event_handler = handler; + return NRF_SUCCESS; +} + + +ret_code_t app_usbd_class_sof_register(app_usbd_class_inst_t const * p_cinst) +{ + ASSERT(NULL != p_cinst); + ASSERT(NULL != p_cinst->p_class_methods); + ASSERT(NULL != p_cinst->p_class_methods->event_handler); + /* This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + /* Make sure it's not in interrupt SOF list */ + app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_interrupt_cinst; + while (NULL != (*pp_last)) + { + ASSERT((*pp_last) != p_cinst); + pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); + } + + /* Next SOF event requiring instance has to be NULL now */ + ASSERT(NULL == (app_usbd_class_data_access(p_cinst)->p_sof_next)); + + /* Adding pointer to this instance to the end of the chain */ + pp_last = &m_p_first_sof_cinst; + while (NULL != (*pp_last)) + { + ASSERT((*pp_last) != p_cinst); + pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); + } + (*pp_last) = p_cinst; + + return NRF_SUCCESS; +} + + +ret_code_t app_usbd_class_sof_unregister(app_usbd_class_inst_t const * p_cinst) +{ + ASSERT(NULL != p_cinst); + /** This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_cinst; + while (NULL != (*pp_last)) + { + if ((*pp_last) == p_cinst) + { + /* Breaking chain */ + (*pp_last) = (app_usbd_class_data_access(p_cinst)->p_sof_next); + app_usbd_class_data_access(p_cinst)->p_sof_next = NULL; + + return NRF_SUCCESS; + } + pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); + } + return NRF_ERROR_NOT_FOUND; +} + +ret_code_t app_usbd_class_sof_interrupt_register(app_usbd_class_inst_t const * p_cinst, app_usbd_sof_interrupt_handler_t handler) +{ + ASSERT(NULL != p_cinst); + ASSERT(NULL != p_cinst->p_class_methods); + ASSERT(NULL != handler); + /* This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + /* Next SOF event requiring instance has to be NULL now */ + ASSERT(NULL == (app_usbd_class_data_access(p_cinst)->p_sof_next)); + + app_usbd_class_data_access(p_cinst)->sof_handler = handler; + + /* Make sure it's not in normal SOF list */ + app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_cinst; + while (NULL != (*pp_last)) + { + ASSERT((*pp_last) != p_cinst); + pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); + } + + /* Adding pointer to this instance to the end of the interrupt chain */ + pp_last = &m_p_first_sof_interrupt_cinst; + while (NULL != (*pp_last)) + { + + ASSERT((*pp_last) != p_cinst); + pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); + } + (*pp_last) = p_cinst; + + return NRF_SUCCESS; +} + + +ret_code_t app_usbd_class_sof_interrupt_unregister(app_usbd_class_inst_t const * p_cinst) +{ + ASSERT(NULL != p_cinst); + /** This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_interrupt_cinst; + while (NULL != (*pp_last)) + { + if ((*pp_last) == p_cinst) + { + /* Breaking chain */ + (*pp_last) = (app_usbd_class_data_access(p_cinst)->p_sof_next); + app_usbd_class_data_access(p_cinst)->p_sof_next = NULL; + + return NRF_SUCCESS; + } + pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); + } + return NRF_ERROR_NOT_FOUND; +} + +ret_code_t app_usbd_class_rwu_register(app_usbd_class_inst_t const * const p_inst) +{ + ASSERT(p_inst != NULL); + ++m_rwu_registered_counter; + /*Overflow check*/ + ASSERT(m_rwu_registered_counter != 0); + + return NRF_SUCCESS; +} + + +ret_code_t app_usbd_class_rwu_unregister(app_usbd_class_inst_t const * const p_inst) +{ + ASSERT(p_inst != NULL); + /* Usage validation. If counter is 0 unregister is not possible.*/ + ASSERT(m_rwu_registered_counter != 0); + --m_rwu_registered_counter; + + return NRF_SUCCESS; +} + +bool app_usbd_class_rwu_enabled_check(void) +{ + return (m_rwu_registered_counter != 0); +} + +ret_code_t app_usbd_interface_ep_reset(app_usbd_class_inst_t const * const p_cinst, + uint8_t iface) +{ + uint8_t iface_count = app_usbd_class_iface_count_get(p_cinst); + + app_usbd_class_iface_conf_t const * p_iface = NULL; + for (uint8_t j = 0; j < iface_count; ++j) + { + p_iface = app_usbd_class_iface_get(p_cinst, j); + if (app_usbd_class_iface_number_get(p_iface) == iface) + { + break; + } + } + + if (p_iface == NULL) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + uint8_t ep_count = app_usbd_class_iface_ep_count_get(p_iface); + + for (uint8_t j = 0; j < ep_count; ++j) + { + /*Clear stall for every endpoint*/ + app_usbd_class_ep_conf_t const * p_ep = app_usbd_class_iface_ep_get(p_iface, j); + + if (!NRF_USBD_EPISO_CHECK(p_ep->address)) + { + nrf_drv_usbd_ep_dtoggle_clear(p_ep->address); + nrf_drv_usbd_ep_stall_clear(p_ep->address); + } + + } + + return NRF_SUCCESS; +} + +void app_usbd_ep_enable(nrf_drv_usbd_ep_t ep) +{ + if (!NRF_USBD_EPISO_CHECK(ep)) + { + nrf_drv_usbd_ep_dtoggle_clear(ep); + nrf_drv_usbd_ep_stall_clear(ep); + } + nrf_drv_usbd_ep_enable(ep); +} + +void app_usbd_ep_disable(nrf_drv_usbd_ep_t ep) +{ + nrf_drv_usbd_ep_disable(ep); +} + + +app_usbd_class_inst_t const * app_usbd_class_first_get(void) +{ + return m_p_first_cinst; +} + +app_usbd_class_inst_t const * app_usbd_class_sof_first_get(void) +{ + return m_p_first_sof_cinst; +} + +app_usbd_class_inst_t const * app_usbd_class_sof_interrupt_first_get(void) +{ + return m_p_first_sof_interrupt_cinst; +} + +app_usbd_class_inst_t const * app_usbd_iface_find(uint8_t iface, uint8_t * p_iface_idx) +{ + app_usbd_class_inst_t const * p_inst = app_usbd_class_first_get(); + while (p_inst != NULL) + { + uint8_t iface_count = app_usbd_class_iface_count_get(p_inst); + /* Iterate over interfaces */ + for (uint8_t i = 0; i < iface_count; ++i) + { + app_usbd_class_iface_conf_t const * p_iface; + p_iface = app_usbd_class_iface_get(p_inst, i); + if (app_usbd_class_iface_number_get(p_iface) == iface) + { + if (p_iface_idx != NULL) + { + (*p_iface_idx) = i; + } + return p_inst; + } + } + p_inst = app_usbd_class_next_get(p_inst); + } + return NULL; +} + +ret_code_t app_usbd_iface_call( + app_usbd_class_inst_t const * const p_class_inst, + uint8_t iface_idx, + app_usbd_complex_evt_t const * const p_event) +{ + UNUSED_PARAMETER(iface_idx); + return class_event_handler(p_class_inst, p_event); +} + +ret_code_t app_usbd_ep_call(nrf_drv_usbd_ep_t ep, app_usbd_complex_evt_t const * const p_event) +{ + if (NRF_USBD_EP_VALIDATE(ep)) + { + app_usbd_class_inst_t const * p_inst = app_usbd_ep_conf_access(ep)->p_cinst; + if (p_inst != NULL) + { + return class_event_handler(p_inst, p_event); + } + } + return NRF_ERROR_INVALID_ADDR; +} + +void app_usbd_all_call(app_usbd_complex_evt_t const * const p_event) +{ + app_usbd_class_inst_t const * p_inst; + for (p_inst = app_usbd_class_first_get(); NULL != p_inst; + p_inst = app_usbd_class_next_get(p_inst)) + { + UNUSED_RETURN_VALUE(class_event_handler(p_inst, p_event)); + } +} + +ret_code_t app_usbd_all_until_served_call(app_usbd_complex_evt_t const * const p_event) +{ + app_usbd_class_inst_t const * p_inst; + ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; + /* Try to process via every instance */ + for (p_inst = app_usbd_class_first_get(); NULL != p_inst; + p_inst = app_usbd_class_next_get(p_inst)) + { + + ret = class_event_handler(p_inst, p_event); + if (NRF_ERROR_NOT_SUPPORTED != ret) + { + /* Processing finished */ + break; + } + } + + return ret; +} + +ret_code_t app_usbd_ep_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_transfer_t const * const p_transfer) +{ + if (!nrf_drv_usbd_ep_enable_check(ep)) + { + return NRF_ERROR_INVALID_STATE; + } + if (m_sustate != SUSTATE_ACTIVE) + { + return NRF_ERROR_INVALID_STATE; + } + return nrf_drv_usbd_ep_transfer(ep, p_transfer); +} + +ret_code_t app_usbd_ep_handled_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_handler_desc_t const * const p_handler) +{ + if (!nrf_drv_usbd_ep_enable_check(ep)) + { + return NRF_ERROR_INVALID_STATE; + } + if (m_sustate != SUSTATE_ACTIVE) + { + return NRF_ERROR_INVALID_STATE; + } + return nrf_drv_usbd_ep_handled_transfer(ep, p_handler); +} + +ret_code_t app_usbd_iface_select( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx, + uint8_t alternate) +{ + ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; + + if (p_inst->p_class_methods->iface_select != NULL) + { + ret = p_inst->p_class_methods->iface_select(p_inst, iface_idx, alternate); + } + + if(ret == NRF_ERROR_NOT_SUPPORTED) + { + ret = default_iface_select(p_inst, iface_idx, alternate); + } + return ret; +} + +void app_usbd_iface_deselect( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx) +{ + if (p_inst->p_class_methods->iface_deselect != NULL) + { + p_inst->p_class_methods->iface_deselect(p_inst, iface_idx); + } + default_iface_deselect(p_inst, iface_idx); +} + +uint8_t app_usbd_iface_selection_get( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx) +{ + uint8_t alt = 0; + if (p_inst->p_class_methods->iface_selection_get != NULL) + { + alt = p_inst->p_class_methods->iface_selection_get(p_inst, iface_idx); + } + return alt; +} + +void app_usbd_all_iface_select_0(void) +{ + app_usbd_class_inst_t const * p_inst = app_usbd_class_first_get(); + while (p_inst != NULL) + { + uint8_t iface_count = app_usbd_class_iface_count_get(p_inst); + for (uint8_t i = 0; i < iface_count; ++i) + { + ret_code_t ret; + ret = app_usbd_iface_select(p_inst, i, 0); + ASSERT(ret == NRF_SUCCESS); + UNUSED_VARIABLE(ret); + } + p_inst = app_usbd_class_next_get(p_inst); + } +} + +void app_usbd_all_iface_deselect(void) +{ + app_usbd_class_inst_t const * p_inst = app_usbd_class_first_get(); + while (p_inst != NULL) + { + uint8_t iface_count = app_usbd_class_iface_count_get(p_inst); + for (uint8_t i = 0; i < iface_count; ++i) + { + app_usbd_iface_deselect(p_inst, i); + } + p_inst = app_usbd_class_next_get(p_inst); + } +} + +#endif //NRF_MODULE_ENABLED(APP_USBD) diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd.h index 3913373a2..0bb881d90 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd.h +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd.h @@ -1,816 +1,816 @@ -/** - * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef APP_USBD_H__ -#define APP_USBD_H__ - -#include "nrf_drv_usbd.h" -#include "app_usbd_types.h" -#include "app_usbd_class_base.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup app_usbd USB Device high level library - * @ingroup app_common - * - * @brief @tagAPI52840 Module for easy support for any USB device configuration. - * - * This module manages class instances that would create the USB device, - * manages endpoints and interfaces transactions. - * @{ - */ - -/** - * @brief Highest value of Frame Number in SOF packets. - */ -#define APP_USBD_SOF_MAX 2047 - -/** - * @brief True if SOF timestamping is really provided. - * - * SOF timestamping is really provided if it was requested and if the logger is enabled. - */ -#if ((APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE) && (NRF_LOG_ENABLED)) -#define APP_USBD_PROVIDE_SOF_TIMESTAMP 1 -#else -#define APP_USBD_PROVIDE_SOF_TIMESTAMP 0 -#endif - -/** - * @brief SOF event handling modes. - */ -#define APP_USBD_SOF_HANDLING_NORMAL_QUEUE 0 //!< Push SOF events into event queue. -#define APP_USBD_SOF_HANDLING_COMPRESS_QUEUE 1 //!< Compress SOF events. -#define APP_USBD_SOF_HANDLING_INTERRUPT 2 //!< Handle SOF events in interrupt. - -/** - * @brief Configuration passed to @ref app_usbd_init. - */ -typedef struct { -#if (!(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)) || defined(__SDK_DOXYGEN__) - /** - * @brief User defined event handler. - * - * This function is called on every event from the interrupt. - * It is prepared for external user function that would queue events to be processed - * from the main context. - * It should be used with operating systems with its own implementation of the queue. - * - * @param p_event The event structure pointer. - * - * @note This field is available only when USB internal queue is disabled - * (see @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE). - */ - void (*ev_handler)(app_usbd_internal_evt_t const * const p_event); -#endif - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) - /** - * @brief User defined event handler. - * - * This function is called on every event from the interrupt. - * - * @param p_event The event structure pointer. - * @param queued The event is visible in the queue. - * If queue conflict is detected the event might not be accessible inside queue - * until all write operations finish. - * See @ref nrf_atfifo for more details. - * - * @note This field is available only when USBD internal queue is configured - * (see @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE). - * - * @note If is set to NULL no event would be called from interrupt. - * @note This function is called before event is processed. - * It means that if the event type is @ref APP_USBD_EVT_DRV_SETUP, - * there would not be setup field present in the event structure. - */ - void (*ev_isr_handler)(app_usbd_internal_evt_t const * const p_event, bool queued); -#endif - - /** - * @brief User defined event processor - * - * This function is called while state event is processed. - * - * * @note This field is available only when USBD internal queue is configured - * (see @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE). - * - * @param event Event type. - * Only following events are sent into this function: - * - APP_USBD_EVT_DRV_SOF - * - APP_USBD_EVT_DRV_RESET - Note that it also exits suspend - * - APP_USBD_EVT_DRV_SUSPEND - * - APP_USBD_EVT_DRV_RESUME - It is also generated when remote wakeup is generated - * - APP_USBD_EVT_START - * - APP_USBD_EVT_STOP - * - APP_USBD_EVT_STATE_CHANGED - * - APP_USBD_EVT_POWER_DETECTED - * - APP_USBD_EVT_POWER_REMOVED - * - APP_USBD_EVT_POWER_READY - */ - void (*ev_state_proc)(app_usbd_event_type_t event); - - /** - * @brief SOF processing required by the user event processing. - * - * This flag would enable SOF processing for the user events regardless of the fact if any - * of the implemented class requires SOF event. - * - * @note SOF event would be enabled anyway if any of the appended class requires SOF processing. - */ - bool enable_sof; -} app_usbd_config_t; - - -#if (APP_USBD_PROVIDE_SOF_TIMESTAMP) || defined(__SDK_DOXYGEN__) -/** - * @brief Timestamp function for the logger. - * - * @return Current frame number taken directly from the last processed SOF. - */ -uint32_t app_usbd_sof_timestamp_get(void); -#endif - -/** - * @brief USB library initialization. - * - * Call this function before any configuration or class attachment. - * USBD peripheral would be ready to accept commands, and library would be ready, - * but it would not be connected to the bus. - * Call @ref app_usbd_enable to enable USBD communication with the host. - * - * @param p_config Configuration. NULL pointer might be passed here and default - * configuration will be applied then. - */ -ret_code_t app_usbd_init(app_usbd_config_t const * p_config); - -/** - * @brief USB library un-initialization. - * - * @note Currently not supported. - */ -ret_code_t app_usbd_uninit(void); - -#if (APP_USBD_CONFIG_POWER_EVENTS_PROCESS) || defined(__SDK_DOXYGEN__) -/** - * @brief Function to start USB related power events processing. - * - * This function should be called after @ref app_usbd_init and after all the - * required classes were appended (@ref app_usbd_class_append). - * - * @retval NRF_SUCCESS Power events successfully initialized. - * @retval NRF_ERROR_INVALID_STATE The state of the driver does not allow to enable - * the power events processing. - */ -ret_code_t app_usbd_power_events_enable(void); -#endif - -/** - * @brief Enable USBD. - * - * USBD is enabled. - * Since now the high frequency clock may be requested when USB RESET would be detected. - */ -void app_usbd_enable(void); - -/** - * @brief Disable USBD. - * - * Disabled USDB peripheral cannot be accessed but also stops requesting - * High Frequency clock and releases power regulator. - * - * @note This function cannot be called when USB is started. Stop it first. - */ -void app_usbd_disable(void); - -/** - * @brief Request USBD to start. - * - * The function sends start request to the event queue. - * If the queue is enabled (@ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) it would be processed - * when the queue is processed. - * If queue is disabled it would be processed immediately inside this function. - * It means that if queue is disabled this function cannot be called from interrupt with priority - * higher than USB interrupt. - * - * When start is processed it would: - * 1. Start library. - * 2. Enable interrupts. - * 3. Enable USB pull-ups. - * - * @note - * In some specific circumstances the library can be left not started and this function would - * silently exit. - * This may happen if some glitches appears on USB power line or if the plug was disconnected before - * whole starting process finishes. - * User would get the event from POWER peripheral then. - * Also no @ref APP_USBD_EVT_STARTED event would be generated to the classes and user event handler. - * For the safe code it is recommended to wait for @ref APP_USBD_EVT_STARTED event if anything - * has to be initialized after USB driver is started (just before enabling the interrupts). - * If library is properly started the @ref APP_USBD_EVT_STARTED event passed to the user handler - * from this function body. - */ -void app_usbd_start(void); - -/** - * @brief Stop USB. - * - * The function sends stop request to the event queue. - * If the queue is enabled (@ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) it would be processed - * when the queue is processed. - * If queue is disabled it would be processed immediately inside this function. - * It means that if queue is disabled this function cannot be called from interrupt with priority - * higher than USB interrupt. - * - * When the event is processed interrupts and USB pull-ups are disabled. - * The peripheral itself is left enabled so it can be programmed, - * but a HOST sees it as a peripheral disconnection. - * - * @note - * If the library is not started when this function is called it exits silently - also - * no @ref APP_USBD_EVT_STOPPED is generated. - */ -void app_usbd_stop(void); - -/** - * @brief Request library to suspend. - * - * This function send suspend request to the event queue. - * - * @note This function should only be called after @ref APP_USBD_EVT_DRV_SUSPEND os received. - * Internal suspend request processing would give no effect if the bus is not in suspend state. - */ -void app_usbd_suspend_req(void); - -/** - * @brief Request library to wake-up. - * - * This function send wakeup request to the event queue. - * - * @note Calling this function does not mean that peripheral is active - the wakeup request is sent - * into message queue and needs to be processed. - * - * @retval true Wakeup generation has been started. - * @retval false No wakeup would be generated becouse it is disabled by the host. - */ -bool app_usbd_wakeup_req(void); - -/** - * @brief Get information whether there is an active connection. - * - * Function to check if the communication with the bus is possible. - * - * @retval true The bus is active. - * @retval false There is no connection or bus is suspended. - */ -bool app_usbd_active_check(void); - -/** - * @brief USBD event processor. - * - * Function to be called on each event to be processed by the library. - */ -void app_usbd_event_execute(app_usbd_internal_evt_t const * const p_event); - - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) -/** - * @brief Function that process events from the queue. - * - * @note This function calls @ref app_usbd_event_execute internally. - * - * @retval true Event was processed. - * @retval false The event queue is empty. - */ -bool app_usbd_event_queue_process(void); -#endif - -/** - * @brief Add class instance. - * - * This function connects given instance into internal class instance chain and - * into all required endpoints. - * The instance event handler would be connected into endpoint by default, - * but this can be overwritten by @ref app_usbd_ep_handler_set. - * - * After successful attachment @ref APP_USBD_EVT_INST_APPEND would be passed to class instance. - * - * @note This function can only be called after USBD library is initialized but still disabled. - * Assertion would be generated otherwise. - * - * @param[in,out] p_cinst Instance to connect. Chain data would be written into writable instance data. - * - * @retval NRF_SUCCESS Instance successfully added. - * @retval NRF_ERROR_BUSY Endpoint(s) not available. - */ -ret_code_t app_usbd_class_append(app_usbd_class_inst_t const * p_cinst); - -/** - * @brief Remove class instance. - * - * Instance is removed from instance chain. - * Instance and event handlers are removed also from endpoints. - * Endpoints used by by the class instance are left disabled. - * - * @note This function can only be called after USBD library is initialized but still disabled. - * Assertion would be generated otherwise. - * - * @param p_cinst Instance pointer to remove. - * - * @retval NRF_SUCCESS Instance successfully removed. - * @retval NRF_ERROR_NOT_FOUND Instance not found in the instance chain. - */ -ret_code_t app_usbd_class_remove(app_usbd_class_inst_t const * p_cinst); - -/** - * @brief Remove all class instances. - * - * This function basically calls @ref app_usbd_class_remove - * on instances chain as long as there is any element left. - * - * @note This function can only be called after USBD library is initialized but still disabled. - * Assertion would be generated otherwise. - * - * @sa app_usbd_class_remove - * - * @return Is should always return @ref NRF_SUCCESS. - * Any error value returned would mean there is an error inside the library. - */ -ret_code_t app_usbd_class_remove_all(void); - -/** - * @brief Change endpoint handler. - * - * This function may be called for the endpoint only if the class instance is - * already properly attached by the @ref app_usbd_class_append function. - * - * The endpoint event handler function can be only overwritten by the class instance - * that was connected into the endpoint. - * - * @note This function can only be called after USBD library is initialized but still disabled. - * Assertion would be generated otherwise. - * - * @param[in] p_cinst Instance of a class that wish to set new event handler. - * It has to match currently configured instance for the selected endpoint. - * In other situation error would be returned. - * @param[in] ep Endpoint address to configure. - * @param[in] handler Event handler function to set. - * - * @retval NRF_SUCCESS New handler successfully set - * @retval NRF_ERROR_INVALID_PARAM p_cinst is not the same as currently set for the endpoint - */ -ret_code_t app_usbd_ep_handler_set(app_usbd_class_inst_t const * p_cinst, - nrf_drv_usbd_ep_t ep, - app_usbd_ep_event_handler_t handler); - -/** - * @brief Register class instance as the one that requires SOF events. - * - * This function should be called in reaction on APP_USBD_EVT_INST_APPEND event. - * Connect the class instance to the list of instances that requires SOF processing. - * If none of the appended instances requires SOF event - it is disabled. - * - * @param p_cinst Instance that requires SOF event. - * - * @retval NRF_SUCCESS Instance linked into SOF processing list. - * - * @sa app_usbd_class_sof_unregister - */ -ret_code_t app_usbd_class_sof_register(app_usbd_class_inst_t const * p_cinst); - -/** - * @brief Unregister class instance from SOF processing instances list. - * - * Every class that calls @ref app_usbd_class_sof_register have to call also unregistering function - * in reaction to @ref APP_USBD_EVT_INST_REMOVE event. - * - * @param p_cinst Instance to be unregistered from SOF event processing list. - * - * @retval NRF_SUCCESS Instance linked into SOF processing list. - * @retval NRF_ERROR_NOT_FOUND Instance not found in the SOF processing list. - * - * @sa app_usbd_class_sof_register - */ -ret_code_t app_usbd_class_sof_unregister(app_usbd_class_inst_t const * p_cinst); - -/** - * @brief Register class instance as the one that requires SOF events in interrupt. - * - * This function should be called in reaction on APP_USBD_EVT_INST_APPEND event. - * Connect the class instance to the list of instances that requires SOF processing. - * If none of the appended instances requires SOF event - it is disabled. - * - * @param p_cinst Instance that requires SOF event. - * @param handler Handler to SOF event - * - * @retval NRF_SUCCESS Instance linked into SOF processing list. - * - * @sa app_usbd_class_sof_interrupt_unregister - */ -ret_code_t app_usbd_class_sof_interrupt_register(app_usbd_class_inst_t const * p_cinst, - app_usbd_sof_interrupt_handler_t handler); - -/** - * @brief Unregister class instance from SOF processing in interrupt instances list. - * - * Every class that calls @ref app_usbd_class_sof_interrupt_register have to call - * also unregistering function in reaction to @ref APP_USBD_EVT_INST_REMOVE event. - * - * @param p_cinst Instance to be unregistered from SOF processing in interrupt list. - * - * @retval NRF_SUCCESS Instance linked into SOF processing in interrupt list. - * @retval NRF_ERROR_NOT_FOUND Instance not found in the SOF processing in interrupt list. - * - * @sa app_usbd_class_sof_interrupt_register - */ -ret_code_t app_usbd_class_sof_interrupt_unregister(app_usbd_class_inst_t const * p_cinst); - - -/** - * @brief Register class on remote wake-up feature. - * - * @param[in] p_inst Instance of the class. - * - * @retval NRF_SUCCESS Instance that requires remote wake-up registered. - */ -ret_code_t app_usbd_class_rwu_register(app_usbd_class_inst_t const * const p_inst); - -/** - * @brief Unregister class from remote wake-up feature. - * - * @param[in] p_inst Instance of the class. - * - * @retval NRF_SUCCESS Instance that requires remote wake-up removed. - */ -ret_code_t app_usbd_class_rwu_unregister(app_usbd_class_inst_t const * const p_inst); - -/** - * @brief Check if there is any class with remote wakeup. - * - * The function checks internal registered class with remote wakeup counter. - * - * @sa app_usbd_class_rwu_register, app_usbd_class_rwu_unregister - * - * @retval true The remote wakeup functionality is required by some class instance. - * @retval false There is no class instance that requires wakeup functionality. - */ -bool app_usbd_class_rwu_enabled_check(void); - -/** - * @brief Find a specified descriptor. - * - * @param[in] p_cinst Class instance. - * @param[in] desc_type Descriptor type @ref app_usbd_descriptor_t - * @param[in] desc_index Descriptor index. - * @param[out] p_desc Pointer to escriptor. - * @param[out] p_desc_len Length of descriptor. - * - * @return Standard error code @ref ret_code_t - * @retval NRF_SUCCESS Descriptor successfully found. - * @retval NRF_ERROR_NOT_FOUND Descriptor not found. - * */ -ret_code_t app_usbd_class_descriptor_find(app_usbd_class_inst_t const * const p_cinst, - uint8_t desc_type, - uint8_t desc_index, - uint8_t * p_desc, - size_t * p_desc_len); - -/** - * @brief Standard set interface request handle. - * - * This function should be called when processing SET_INTERFACE request. - * - * @param[in] p_cinst Instance of a class. - * @param[in] iface Interface number. - * - * @return Standard error code. - * - * @note Selected interface to reset has to be part of given class. - * */ -ret_code_t app_usbd_interface_ep_reset(app_usbd_class_inst_t const * const p_cinst, - uint8_t iface); - - -/** - * @brief Enable selected endpoint. - * - * Selected endpoint is enabled and cleared. - * - * @param ep Endpoint number. - */ -void app_usbd_ep_enable(nrf_drv_usbd_ep_t ep); - -/** - * @brief Disable selected endpoint. - * - * @param ep Endpoint number. - */ -void app_usbd_ep_disable(nrf_drv_usbd_ep_t ep); - -/** - * @name Iterate through classes lists - * - * Functions that helps to iterate through internally chained classes. - * @{ - */ - /** - * @brief Get first class instance in the list. - * - * Get first instance from the list of active class instances. - * That instance may be used then in @ref app_usbd_class_next_get function. - * - * @return First instance in the list or NULL if there are no instances available. - */ - app_usbd_class_inst_t const * app_usbd_class_first_get(void); - - /** - * @brief Get next instance in the list. - * - * Get the next instance from the list of active instances. - * Used to iterate through all instances. - * - * @param[in] p_cinst The current instance from with next one is required. - * - * @return Next instance to the given one or NULL if there is no more instances in the list. - */ - static inline app_usbd_class_inst_t const * app_usbd_class_next_get( - app_usbd_class_inst_t const * const p_cinst) - { - ASSERT(NULL != p_cinst); - return app_usbd_class_data_access(p_cinst)->p_next; - } - - /** - * @brief Get first instance in SOF list. - * - * Start iteration through the list of instances that require SOF event processing. - * - * @return First instance in the list or NULL if the list is empty. - * - * @sa app_usbd_class_first_get - */ - app_usbd_class_inst_t const * app_usbd_class_sof_first_get(void); - - /** - * @brief Get next instance in the SOF list. - * - * Get the next instance from the list of instances requiring SOF event processing. - * Used to iterate through all SOF instances. - * - * @param p_cinst The current instance from with next one is required. - * - * @return Next instance to the given one or NULL if there is no more instances in the list. - */ - static inline app_usbd_class_inst_t const * app_usbd_class_sof_next_get( - app_usbd_class_inst_t const * const p_cinst) - { - ASSERT(NULL != p_cinst); - return app_usbd_class_data_access(p_cinst)->p_sof_next; - } - - /** - * @brief Get first instance in SOF interrupt list. - * - * Start iteration through the list of instances that require SOF processing in interrupt. - * - * @return First instance in the list or NULL if the list is empty. - * - * @sa app_usbd_class_first_get - */ - app_usbd_class_inst_t const * app_usbd_class_sof_interrupt_first_get(void); - - /** - * @brief Get next instance in the SOF interrupt list. - * - * Get the next instance from the list of instances requiring SOF processing in interrupt. - * Used to iterate through all SOF instances that have SOF handlers. - * - * @param p_cinst The current instance from with next one is required. - * - * @return Next instance to the given one or NULL if there is no more instances in the list. - */ - static inline app_usbd_class_inst_t const * app_usbd_class_sof_interrupt_next_get( - app_usbd_class_inst_t const * const p_cinst) - { - ASSERT(NULL != p_cinst); - return app_usbd_class_data_access(p_cinst)->p_sof_next; - } -/** @} */ - -/** - * @brief Search for selected interface. - * - * Function searches for the given interface number and returns the class that contains it. - * Optionally it can return interface index inside class instance. - * - * @param[in] iface Interface number. - * @param[out] p_iface_idx Pointer to a variable that would hold interface index inside returned - * class instance. - * - * @return Pointer to the class structure that cointain given interface or NULL if not found. - */ -app_usbd_class_inst_t const * app_usbd_iface_find(uint8_t iface, uint8_t * p_iface_idx); - - -/** - * @name Communicate with interfaces, endpoints and instances inside usbd library - * - * @{ - */ - - /** - * @brief Call interface event handler. - * - * Call event handler for selected interface. - * @param[in,out] p_class_inst Class instance that holds selected interface. - * @param[in] iface_idx Index of the interface in class structure. - * @param[in] p_event Event structure to be processed. - * - * @return Operation status. - */ - ret_code_t app_usbd_iface_call( - app_usbd_class_inst_t const * const p_class_inst, - uint8_t iface_idx, - app_usbd_complex_evt_t const * const p_event); - - /** - * @brief Call endpoint event handler. - * - * Call event handler for the selected endpoint. - * @param[in] ep Endpoint number. - * @param[in] p_event Event structure to send. - * - * @return Operation status. - */ - ret_code_t app_usbd_ep_call(nrf_drv_usbd_ep_t ep, app_usbd_complex_evt_t const * const p_event); - - /** - * @brief Auxiliary function that process event by every instance in the list. - * - * This function ignores the result of called handler. - * - * @param p_event Event to pass to every instance. - */ - void app_usbd_all_call(app_usbd_complex_evt_t const * const p_event); - - /** - * @brief Call interface event handlers and stop when served. - * - * Call event handlers from instances as long as we get result different than @ref NRF_ERROR_NOT_SUPPORTED - * @param[in] p_event Event structure to send. - * - * @return Operation status or @ref NRF_ERROR_NOT_SUPPORTED if none of instances in the list can support given event. - */ - ret_code_t app_usbd_all_until_served_call(app_usbd_complex_evt_t const * const p_event); -/** @} */ - -/** - * @brief Endpoint transfer. - * - * @param ep Endpoint number. - * @param p_transfer Description of the transfer to be performed. - * The direction of the transfer is determined by the - * endpoint number. - * - * @retval NRF_ERROR_INVALID_STATE The state of the USB device does not allow - * data transfer on the endpoint. - * @return Values returned by @ref nrf_drv_usbd_ep_transfer. - * - * @sa app_usbd_ep_handled_transfer - */ -ret_code_t app_usbd_ep_transfer( - nrf_drv_usbd_ep_t ep, - nrf_drv_usbd_transfer_t const * const p_transfer); - -/** - * @brief Set up an endpoint handled transfer. - * - * Configures a transfer handled by the feedback function. - * - * @param ep Endpoint number. - * @param p_handler Function called when the next chunk of data is requested. - * - * @retval NRF_ERROR_INVALID_STATE The state of the USB device does not allow - * data transfer on the endpoint. - * @return Values returned by @ref nrf_drv_usbd_ep_handled_transfer. - */ -ret_code_t app_usbd_ep_handled_transfer( - nrf_drv_usbd_ep_t ep, - nrf_drv_usbd_handler_desc_t const * const p_handler); - - -/** - * @brief Select interface - * - * Select the given interface. - * This function calls class interface selection function or default - * interface selection function. - * - * After calling this function interface should be functional. - * - * @param[in,out] p_inst Instance of the class. - * @param[in] iface_idx Index of the interface inside class structure. - * @param[in] alternate Alternate setting that should be selected. - * - * @return Standard error code. - */ -ret_code_t app_usbd_iface_select( - app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx, - uint8_t alternate); - - -/** - * @brief Deselect interface. - * - * Disable the given interface. - * This function calls class interface deselection function or - * default interface selection function. - * - * After calling this function all the endpoints from the interface - * have to be disabled. - * - * @param[in,out] p_inst Instance of the class. - * @param[in] iface_idx Index of the interface inside class structure. - */ -void app_usbd_iface_deselect( - app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx); - -/** - * @brief Get selected interface. - * - * Function retieves currently selected interface. - * If the class contains @ref app_usbd_class_methods_t::iface_selection_get it is called. - * It it does not contain this function this function would return default, 0 value. - * - * @param[in] p_inst Instance of the class. - * @param[in] iface_idx Index of the interface inside class structure. - * - * @return Selected alternate interface setting. - */ -uint8_t app_usbd_iface_selection_get( - app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx); - -/** - * @brief Select alternate configuration 0 for all interfaces. - * - * Auxiliary function that clears settings for all interfaces leaving them enabled. - */ -void app_usbd_all_iface_select_0(void); - -/** - * @brief Deselect all interfaces. - * - * Auxiliary function to disable all interfaces. - */ -void app_usbd_all_iface_deselect(void); - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_H__ */ +/** + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef APP_USBD_H__ +#define APP_USBD_H__ + +#include "nrf_drv_usbd.h" +#include "app_usbd_types.h" +#include "app_usbd_class_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup app_usbd USB Device high level library + * @ingroup app_common + * + * @brief @tagAPI52840 Module for easy support for any USB device configuration. + * + * This module manages class instances that would create the USB device, + * manages endpoints and interfaces transactions. + * @{ + */ + +/** + * @brief Highest value of Frame Number in SOF packets. + */ +#define APP_USBD_SOF_MAX 2047 + +/** + * @brief True if SOF timestamping is really provided. + * + * SOF timestamping is really provided if it was requested and if the logger is enabled. + */ +#if ((APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE) && (NRF_LOG_ENABLED)) +#define APP_USBD_PROVIDE_SOF_TIMESTAMP 1 +#else +#define APP_USBD_PROVIDE_SOF_TIMESTAMP 0 +#endif + +/** + * @brief SOF event handling modes. + */ +#define APP_USBD_SOF_HANDLING_NORMAL_QUEUE 0 //!< Push SOF events into event queue. +#define APP_USBD_SOF_HANDLING_COMPRESS_QUEUE 1 //!< Compress SOF events. +#define APP_USBD_SOF_HANDLING_INTERRUPT 2 //!< Handle SOF events in interrupt. + +/** + * @brief Configuration passed to @ref app_usbd_init. + */ +typedef struct { +#if (!(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)) || defined(__SDK_DOXYGEN__) + /** + * @brief User defined event handler. + * + * This function is called on every event from the interrupt. + * It is prepared for external user function that would queue events to be processed + * from the main context. + * It should be used with operating systems with its own implementation of the queue. + * + * @param p_event The event structure pointer. + * + * @note This field is available only when USB internal queue is disabled + * (see @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE). + */ + void (*ev_handler)(app_usbd_internal_evt_t const * const p_event); +#endif + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) + /** + * @brief User defined event handler. + * + * This function is called on every event from the interrupt. + * + * @param p_event The event structure pointer. + * @param queued The event is visible in the queue. + * If queue conflict is detected the event might not be accessible inside queue + * until all write operations finish. + * See @ref nrf_atfifo for more details. + * + * @note This field is available only when USBD internal queue is configured + * (see @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE). + * + * @note If is set to NULL no event would be called from interrupt. + * @note This function is called before event is processed. + * It means that if the event type is @ref APP_USBD_EVT_DRV_SETUP, + * there would not be setup field present in the event structure. + */ + void (*ev_isr_handler)(app_usbd_internal_evt_t const * const p_event, bool queued); +#endif + + /** + * @brief User defined event processor + * + * This function is called while state event is processed. + * + * * @note This field is available only when USBD internal queue is configured + * (see @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE). + * + * @param event Event type. + * Only following events are sent into this function: + * - APP_USBD_EVT_DRV_SOF + * - APP_USBD_EVT_DRV_RESET - Note that it also exits suspend + * - APP_USBD_EVT_DRV_SUSPEND + * - APP_USBD_EVT_DRV_RESUME - It is also generated when remote wakeup is generated + * - APP_USBD_EVT_START + * - APP_USBD_EVT_STOP + * - APP_USBD_EVT_STATE_CHANGED + * - APP_USBD_EVT_POWER_DETECTED + * - APP_USBD_EVT_POWER_REMOVED + * - APP_USBD_EVT_POWER_READY + */ + void (*ev_state_proc)(app_usbd_event_type_t event); + + /** + * @brief SOF processing required by the user event processing. + * + * This flag would enable SOF processing for the user events regardless of the fact if any + * of the implemented class requires SOF event. + * + * @note SOF event would be enabled anyway if any of the appended class requires SOF processing. + */ + bool enable_sof; +} app_usbd_config_t; + + +#if (APP_USBD_PROVIDE_SOF_TIMESTAMP) || defined(__SDK_DOXYGEN__) +/** + * @brief Timestamp function for the logger. + * + * @return Current frame number taken directly from the last processed SOF. + */ +uint32_t app_usbd_sof_timestamp_get(void); +#endif + +/** + * @brief USB library initialization. + * + * Call this function before any configuration or class attachment. + * USBD peripheral would be ready to accept commands, and library would be ready, + * but it would not be connected to the bus. + * Call @ref app_usbd_enable to enable USBD communication with the host. + * + * @param p_config Configuration. NULL pointer might be passed here and default + * configuration will be applied then. + */ +ret_code_t app_usbd_init(app_usbd_config_t const * p_config); + +/** + * @brief USB library un-initialization. + * + * @note Currently not supported. + */ +ret_code_t app_usbd_uninit(void); + +#if (APP_USBD_CONFIG_POWER_EVENTS_PROCESS) || defined(__SDK_DOXYGEN__) +/** + * @brief Function to start USB related power events processing. + * + * This function should be called after @ref app_usbd_init and after all the + * required classes were appended (@ref app_usbd_class_append). + * + * @retval NRF_SUCCESS Power events successfully initialized. + * @retval NRF_ERROR_INVALID_STATE The state of the driver does not allow to enable + * the power events processing. + */ +ret_code_t app_usbd_power_events_enable(void); +#endif + +/** + * @brief Enable USBD. + * + * USBD is enabled. + * Since now the high frequency clock may be requested when USB RESET would be detected. + */ +void app_usbd_enable(void); + +/** + * @brief Disable USBD. + * + * Disabled USDB peripheral cannot be accessed but also stops requesting + * High Frequency clock and releases power regulator. + * + * @note This function cannot be called when USB is started. Stop it first. + */ +void app_usbd_disable(void); + +/** + * @brief Request USBD to start. + * + * The function sends start request to the event queue. + * If the queue is enabled (@ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) it would be processed + * when the queue is processed. + * If queue is disabled it would be processed immediately inside this function. + * It means that if queue is disabled this function cannot be called from interrupt with priority + * higher than USB interrupt. + * + * When start is processed it would: + * 1. Start library. + * 2. Enable interrupts. + * 3. Enable USB pull-ups. + * + * @note + * In some specific circumstances the library can be left not started and this function would + * silently exit. + * This may happen if some glitches appears on USB power line or if the plug was disconnected before + * whole starting process finishes. + * User would get the event from POWER peripheral then. + * Also no @ref APP_USBD_EVT_STARTED event would be generated to the classes and user event handler. + * For the safe code it is recommended to wait for @ref APP_USBD_EVT_STARTED event if anything + * has to be initialized after USB driver is started (just before enabling the interrupts). + * If library is properly started the @ref APP_USBD_EVT_STARTED event passed to the user handler + * from this function body. + */ +void app_usbd_start(void); + +/** + * @brief Stop USB. + * + * The function sends stop request to the event queue. + * If the queue is enabled (@ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) it would be processed + * when the queue is processed. + * If queue is disabled it would be processed immediately inside this function. + * It means that if queue is disabled this function cannot be called from interrupt with priority + * higher than USB interrupt. + * + * When the event is processed interrupts and USB pull-ups are disabled. + * The peripheral itself is left enabled so it can be programmed, + * but a HOST sees it as a peripheral disconnection. + * + * @note + * If the library is not started when this function is called it exits silently - also + * no @ref APP_USBD_EVT_STOPPED is generated. + */ +void app_usbd_stop(void); + +/** + * @brief Request library to suspend. + * + * This function send suspend request to the event queue. + * + * @note This function should only be called after @ref APP_USBD_EVT_DRV_SUSPEND os received. + * Internal suspend request processing would give no effect if the bus is not in suspend state. + */ +void app_usbd_suspend_req(void); + +/** + * @brief Request library to wake-up. + * + * This function send wakeup request to the event queue. + * + * @note Calling this function does not mean that peripheral is active - the wakeup request is sent + * into message queue and needs to be processed. + * + * @retval true Wakeup generation has been started. + * @retval false No wakeup would be generated becouse it is disabled by the host. + */ +bool app_usbd_wakeup_req(void); + +/** + * @brief Get information whether there is an active connection. + * + * Function to check if the communication with the bus is possible. + * + * @retval true The bus is active. + * @retval false There is no connection or bus is suspended. + */ +bool app_usbd_active_check(void); + +/** + * @brief USBD event processor. + * + * Function to be called on each event to be processed by the library. + */ +void app_usbd_event_execute(app_usbd_internal_evt_t const * const p_event); + + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) +/** + * @brief Function that process events from the queue. + * + * @note This function calls @ref app_usbd_event_execute internally. + * + * @retval true Event was processed. + * @retval false The event queue is empty. + */ +bool app_usbd_event_queue_process(void); +#endif + +/** + * @brief Add class instance. + * + * This function connects given instance into internal class instance chain and + * into all required endpoints. + * The instance event handler would be connected into endpoint by default, + * but this can be overwritten by @ref app_usbd_ep_handler_set. + * + * After successful attachment @ref APP_USBD_EVT_INST_APPEND would be passed to class instance. + * + * @note This function can only be called after USBD library is initialized but still disabled. + * Assertion would be generated otherwise. + * + * @param[in,out] p_cinst Instance to connect. Chain data would be written into writable instance data. + * + * @retval NRF_SUCCESS Instance successfully added. + * @retval NRF_ERROR_BUSY Endpoint(s) not available. + */ +ret_code_t app_usbd_class_append(app_usbd_class_inst_t const * p_cinst); + +/** + * @brief Remove class instance. + * + * Instance is removed from instance chain. + * Instance and event handlers are removed also from endpoints. + * Endpoints used by by the class instance are left disabled. + * + * @note This function can only be called after USBD library is initialized but still disabled. + * Assertion would be generated otherwise. + * + * @param p_cinst Instance pointer to remove. + * + * @retval NRF_SUCCESS Instance successfully removed. + * @retval NRF_ERROR_NOT_FOUND Instance not found in the instance chain. + */ +ret_code_t app_usbd_class_remove(app_usbd_class_inst_t const * p_cinst); + +/** + * @brief Remove all class instances. + * + * This function basically calls @ref app_usbd_class_remove + * on instances chain as long as there is any element left. + * + * @note This function can only be called after USBD library is initialized but still disabled. + * Assertion would be generated otherwise. + * + * @sa app_usbd_class_remove + * + * @return Is should always return @ref NRF_SUCCESS. + * Any error value returned would mean there is an error inside the library. + */ +ret_code_t app_usbd_class_remove_all(void); + +/** + * @brief Change endpoint handler. + * + * This function may be called for the endpoint only if the class instance is + * already properly attached by the @ref app_usbd_class_append function. + * + * The endpoint event handler function can be only overwritten by the class instance + * that was connected into the endpoint. + * + * @note This function can only be called after USBD library is initialized but still disabled. + * Assertion would be generated otherwise. + * + * @param[in] p_cinst Instance of a class that wish to set new event handler. + * It has to match currently configured instance for the selected endpoint. + * In other situation error would be returned. + * @param[in] ep Endpoint address to configure. + * @param[in] handler Event handler function to set. + * + * @retval NRF_SUCCESS New handler successfully set + * @retval NRF_ERROR_INVALID_PARAM p_cinst is not the same as currently set for the endpoint + */ +ret_code_t app_usbd_ep_handler_set(app_usbd_class_inst_t const * p_cinst, + nrf_drv_usbd_ep_t ep, + app_usbd_ep_event_handler_t handler); + +/** + * @brief Register class instance as the one that requires SOF events. + * + * This function should be called in reaction on APP_USBD_EVT_INST_APPEND event. + * Connect the class instance to the list of instances that requires SOF processing. + * If none of the appended instances requires SOF event - it is disabled. + * + * @param p_cinst Instance that requires SOF event. + * + * @retval NRF_SUCCESS Instance linked into SOF processing list. + * + * @sa app_usbd_class_sof_unregister + */ +ret_code_t app_usbd_class_sof_register(app_usbd_class_inst_t const * p_cinst); + +/** + * @brief Unregister class instance from SOF processing instances list. + * + * Every class that calls @ref app_usbd_class_sof_register have to call also unregistering function + * in reaction to @ref APP_USBD_EVT_INST_REMOVE event. + * + * @param p_cinst Instance to be unregistered from SOF event processing list. + * + * @retval NRF_SUCCESS Instance linked into SOF processing list. + * @retval NRF_ERROR_NOT_FOUND Instance not found in the SOF processing list. + * + * @sa app_usbd_class_sof_register + */ +ret_code_t app_usbd_class_sof_unregister(app_usbd_class_inst_t const * p_cinst); + +/** + * @brief Register class instance as the one that requires SOF events in interrupt. + * + * This function should be called in reaction on APP_USBD_EVT_INST_APPEND event. + * Connect the class instance to the list of instances that requires SOF processing. + * If none of the appended instances requires SOF event - it is disabled. + * + * @param p_cinst Instance that requires SOF event. + * @param handler Handler to SOF event + * + * @retval NRF_SUCCESS Instance linked into SOF processing list. + * + * @sa app_usbd_class_sof_interrupt_unregister + */ +ret_code_t app_usbd_class_sof_interrupt_register(app_usbd_class_inst_t const * p_cinst, + app_usbd_sof_interrupt_handler_t handler); + +/** + * @brief Unregister class instance from SOF processing in interrupt instances list. + * + * Every class that calls @ref app_usbd_class_sof_interrupt_register have to call + * also unregistering function in reaction to @ref APP_USBD_EVT_INST_REMOVE event. + * + * @param p_cinst Instance to be unregistered from SOF processing in interrupt list. + * + * @retval NRF_SUCCESS Instance linked into SOF processing in interrupt list. + * @retval NRF_ERROR_NOT_FOUND Instance not found in the SOF processing in interrupt list. + * + * @sa app_usbd_class_sof_interrupt_register + */ +ret_code_t app_usbd_class_sof_interrupt_unregister(app_usbd_class_inst_t const * p_cinst); + + +/** + * @brief Register class on remote wake-up feature. + * + * @param[in] p_inst Instance of the class. + * + * @retval NRF_SUCCESS Instance that requires remote wake-up registered. + */ +ret_code_t app_usbd_class_rwu_register(app_usbd_class_inst_t const * const p_inst); + +/** + * @brief Unregister class from remote wake-up feature. + * + * @param[in] p_inst Instance of the class. + * + * @retval NRF_SUCCESS Instance that requires remote wake-up removed. + */ +ret_code_t app_usbd_class_rwu_unregister(app_usbd_class_inst_t const * const p_inst); + +/** + * @brief Check if there is any class with remote wakeup. + * + * The function checks internal registered class with remote wakeup counter. + * + * @sa app_usbd_class_rwu_register, app_usbd_class_rwu_unregister + * + * @retval true The remote wakeup functionality is required by some class instance. + * @retval false There is no class instance that requires wakeup functionality. + */ +bool app_usbd_class_rwu_enabled_check(void); + +/** + * @brief Find a specified descriptor. + * + * @param[in] p_cinst Class instance. + * @param[in] desc_type Descriptor type @ref app_usbd_descriptor_t + * @param[in] desc_index Descriptor index. + * @param[out] p_desc Pointer to escriptor. + * @param[out] p_desc_len Length of descriptor. + * + * @return Standard error code @ref ret_code_t + * @retval NRF_SUCCESS Descriptor successfully found. + * @retval NRF_ERROR_NOT_FOUND Descriptor not found. + * */ +ret_code_t app_usbd_class_descriptor_find(app_usbd_class_inst_t const * const p_cinst, + uint8_t desc_type, + uint8_t desc_index, + uint8_t * p_desc, + size_t * p_desc_len); + +/** + * @brief Standard set interface request handle. + * + * This function should be called when processing SET_INTERFACE request. + * + * @param[in] p_cinst Instance of a class. + * @param[in] iface Interface number. + * + * @return Standard error code. + * + * @note Selected interface to reset has to be part of given class. + * */ +ret_code_t app_usbd_interface_ep_reset(app_usbd_class_inst_t const * const p_cinst, + uint8_t iface); + + +/** + * @brief Enable selected endpoint. + * + * Selected endpoint is enabled and cleared. + * + * @param ep Endpoint number. + */ +void app_usbd_ep_enable(nrf_drv_usbd_ep_t ep); + +/** + * @brief Disable selected endpoint. + * + * @param ep Endpoint number. + */ +void app_usbd_ep_disable(nrf_drv_usbd_ep_t ep); + +/** + * @name Iterate through classes lists + * + * Functions that helps to iterate through internally chained classes. + * @{ + */ + /** + * @brief Get first class instance in the list. + * + * Get first instance from the list of active class instances. + * That instance may be used then in @ref app_usbd_class_next_get function. + * + * @return First instance in the list or NULL if there are no instances available. + */ + app_usbd_class_inst_t const * app_usbd_class_first_get(void); + + /** + * @brief Get next instance in the list. + * + * Get the next instance from the list of active instances. + * Used to iterate through all instances. + * + * @param[in] p_cinst The current instance from with next one is required. + * + * @return Next instance to the given one or NULL if there is no more instances in the list. + */ + static inline app_usbd_class_inst_t const * app_usbd_class_next_get( + app_usbd_class_inst_t const * const p_cinst) + { + ASSERT(NULL != p_cinst); + return app_usbd_class_data_access(p_cinst)->p_next; + } + + /** + * @brief Get first instance in SOF list. + * + * Start iteration through the list of instances that require SOF event processing. + * + * @return First instance in the list or NULL if the list is empty. + * + * @sa app_usbd_class_first_get + */ + app_usbd_class_inst_t const * app_usbd_class_sof_first_get(void); + + /** + * @brief Get next instance in the SOF list. + * + * Get the next instance from the list of instances requiring SOF event processing. + * Used to iterate through all SOF instances. + * + * @param p_cinst The current instance from with next one is required. + * + * @return Next instance to the given one or NULL if there is no more instances in the list. + */ + static inline app_usbd_class_inst_t const * app_usbd_class_sof_next_get( + app_usbd_class_inst_t const * const p_cinst) + { + ASSERT(NULL != p_cinst); + return app_usbd_class_data_access(p_cinst)->p_sof_next; + } + + /** + * @brief Get first instance in SOF interrupt list. + * + * Start iteration through the list of instances that require SOF processing in interrupt. + * + * @return First instance in the list or NULL if the list is empty. + * + * @sa app_usbd_class_first_get + */ + app_usbd_class_inst_t const * app_usbd_class_sof_interrupt_first_get(void); + + /** + * @brief Get next instance in the SOF interrupt list. + * + * Get the next instance from the list of instances requiring SOF processing in interrupt. + * Used to iterate through all SOF instances that have SOF handlers. + * + * @param p_cinst The current instance from with next one is required. + * + * @return Next instance to the given one or NULL if there is no more instances in the list. + */ + static inline app_usbd_class_inst_t const * app_usbd_class_sof_interrupt_next_get( + app_usbd_class_inst_t const * const p_cinst) + { + ASSERT(NULL != p_cinst); + return app_usbd_class_data_access(p_cinst)->p_sof_next; + } +/** @} */ + +/** + * @brief Search for selected interface. + * + * Function searches for the given interface number and returns the class that contains it. + * Optionally it can return interface index inside class instance. + * + * @param[in] iface Interface number. + * @param[out] p_iface_idx Pointer to a variable that would hold interface index inside returned + * class instance. + * + * @return Pointer to the class structure that cointain given interface or NULL if not found. + */ +app_usbd_class_inst_t const * app_usbd_iface_find(uint8_t iface, uint8_t * p_iface_idx); + + +/** + * @name Communicate with interfaces, endpoints and instances inside usbd library + * + * @{ + */ + + /** + * @brief Call interface event handler. + * + * Call event handler for selected interface. + * @param[in,out] p_class_inst Class instance that holds selected interface. + * @param[in] iface_idx Index of the interface in class structure. + * @param[in] p_event Event structure to be processed. + * + * @return Operation status. + */ + ret_code_t app_usbd_iface_call( + app_usbd_class_inst_t const * const p_class_inst, + uint8_t iface_idx, + app_usbd_complex_evt_t const * const p_event); + + /** + * @brief Call endpoint event handler. + * + * Call event handler for the selected endpoint. + * @param[in] ep Endpoint number. + * @param[in] p_event Event structure to send. + * + * @return Operation status. + */ + ret_code_t app_usbd_ep_call(nrf_drv_usbd_ep_t ep, app_usbd_complex_evt_t const * const p_event); + + /** + * @brief Auxiliary function that process event by every instance in the list. + * + * This function ignores the result of called handler. + * + * @param p_event Event to pass to every instance. + */ + void app_usbd_all_call(app_usbd_complex_evt_t const * const p_event); + + /** + * @brief Call interface event handlers and stop when served. + * + * Call event handlers from instances as long as we get result different than @ref NRF_ERROR_NOT_SUPPORTED + * @param[in] p_event Event structure to send. + * + * @return Operation status or @ref NRF_ERROR_NOT_SUPPORTED if none of instances in the list can support given event. + */ + ret_code_t app_usbd_all_until_served_call(app_usbd_complex_evt_t const * const p_event); +/** @} */ + +/** + * @brief Endpoint transfer. + * + * @param ep Endpoint number. + * @param p_transfer Description of the transfer to be performed. + * The direction of the transfer is determined by the + * endpoint number. + * + * @retval NRF_ERROR_INVALID_STATE The state of the USB device does not allow + * data transfer on the endpoint. + * @return Values returned by @ref nrf_drv_usbd_ep_transfer. + * + * @sa app_usbd_ep_handled_transfer + */ +ret_code_t app_usbd_ep_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_transfer_t const * const p_transfer); + +/** + * @brief Set up an endpoint handled transfer. + * + * Configures a transfer handled by the feedback function. + * + * @param ep Endpoint number. + * @param p_handler Function called when the next chunk of data is requested. + * + * @retval NRF_ERROR_INVALID_STATE The state of the USB device does not allow + * data transfer on the endpoint. + * @return Values returned by @ref nrf_drv_usbd_ep_handled_transfer. + */ +ret_code_t app_usbd_ep_handled_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_handler_desc_t const * const p_handler); + + +/** + * @brief Select interface + * + * Select the given interface. + * This function calls class interface selection function or default + * interface selection function. + * + * After calling this function interface should be functional. + * + * @param[in,out] p_inst Instance of the class. + * @param[in] iface_idx Index of the interface inside class structure. + * @param[in] alternate Alternate setting that should be selected. + * + * @return Standard error code. + */ +ret_code_t app_usbd_iface_select( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx, + uint8_t alternate); + + +/** + * @brief Deselect interface. + * + * Disable the given interface. + * This function calls class interface deselection function or + * default interface selection function. + * + * After calling this function all the endpoints from the interface + * have to be disabled. + * + * @param[in,out] p_inst Instance of the class. + * @param[in] iface_idx Index of the interface inside class structure. + */ +void app_usbd_iface_deselect( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx); + +/** + * @brief Get selected interface. + * + * Function retieves currently selected interface. + * If the class contains @ref app_usbd_class_methods_t::iface_selection_get it is called. + * It it does not contain this function this function would return default, 0 value. + * + * @param[in] p_inst Instance of the class. + * @param[in] iface_idx Index of the interface inside class structure. + * + * @return Selected alternate interface setting. + */ +uint8_t app_usbd_iface_selection_get( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx); + +/** + * @brief Select alternate configuration 0 for all interfaces. + * + * Auxiliary function that clears settings for all interfaces leaving them enabled. + */ +void app_usbd_all_iface_select_0(void); + +/** + * @brief Deselect all interfaces. + * + * Auxiliary function to disable all interfaces. + */ +void app_usbd_all_iface_deselect(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_class_base.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_class_base.h index 15b4ed3fb..7420c7bf2 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_class_base.h +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_class_base.h @@ -1,1103 +1,1103 @@ -/** - * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef APP_USBD_CLASS_BASE_H__ -#define APP_USBD_CLASS_BASE_H__ - -#include -#include - -#include "app_usbd_types.h" -#include "nrf_drv_usbd.h" -#include "nrf_assert.h" -#include "app_util.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup app_usbd_class_base USBD Class Base module - * @ingroup app_usbd - * - * @brief @tagAPI52840 The base for any class instance is defined in this module. - * - * @details Any class instance must start from base class instance structure. - * This makes them compatible with USBD library independently of the - * implementation details. - * @{ - */ - -/** - * @brief Endpoint configuration. - */ -typedef struct -{ - nrf_drv_usbd_ep_t address; //!< Endpoint address -} app_usbd_class_ep_conf_t; - -/** - * @brief Interface configuration. - */ -typedef struct -{ - uint8_t number; //!< Interface number - uint8_t ep_cnt; //!< Endpoint number - uint8_t ep_offset; //!< Offset of the first endpoint - /**< Offset in bytes of the first endpoint. - * The offset is calculated from the address of this interface structure - */ -} app_usbd_class_iface_conf_t; - -/** - * @brief Instance variable data. - */ -typedef struct -{ - app_usbd_class_inst_t const * p_next; //!< Pointer to the next instance - app_usbd_class_inst_t const * p_sof_next; //!< Pointer to the next SOF event requiring instance - app_usbd_sof_interrupt_handler_t sof_handler; //!< Instance specific SOF interrupt handler -} app_usbd_class_data_t; - -/** - * @brief Class descriptor context. - */ -typedef struct -{ - uint32_t line; //!< Number of line to resume writing descriptors from - uint8_t data_buffer; //!< Data from last call of feeder -} app_usbd_class_descriptor_ctx_t; - -/** - * @brief Class descriptor state. - */ -typedef struct -{ - uint8_t * p_buffer; //!< Pointer to buffer - uint32_t current_size; //!< Current size of descriptor - uint32_t maximum_size; //!< Maximum size of descriptor - app_usbd_class_descriptor_ctx_t * p_context; //!< Pointer to context -} app_usbd_class_descriptor_state_t; - -/** - * @brief Class interface function set. - * */ -typedef struct { - /** - * @brief Instance callback function. - * - * The function used by every class instance. - * @param[in,out] p_inst Instance of the class. - * @param[in] p_event Event to process. - * - * @return Standard error code. - * - * @note If given event is not supported by class, return @ref NRF_ERROR_NOT_SUPPORTED - */ - ret_code_t (* event_handler)(app_usbd_class_inst_t const * const p_inst, - app_usbd_complex_evt_t const * const p_event); - - /** - * @brief Instance feed descriptors. - * - * Feeds whole descriptor of the instance. - * @param[in] p_ctx Class descriptor context. - * @param[in,out] p_inst Instance of the class. - * @param[out] p_buff Buffer for descriptor. - * @param[in] max_size Requested size of the descriptor. - * - * @return True if not finished feeding the descriptor, false if done. - */ - bool (* feed_descriptors)(app_usbd_class_descriptor_ctx_t * p_ctx, - app_usbd_class_inst_t const * p_inst, - uint8_t * p_buff, - size_t max_size); - - - /** - * @brief Select interface - * - * Function called when class interface has to be selected. - * - * This function would be called for every interface when: - * - SET_INTERFACE command is processed by the default handler - * - SET_CONFIG(1) command is processed by the default handler - * - * @note Remember to disable all the endpoints that are not used - * in the selected configuration. - * @note If this function pointer is NULL default procedure would - * just enable all the interface endpoints and selecting - * alternate configurations other than 0 would generate error. - * @note Calling the function with alternate setting 0 has to always succeed. - * - * @param[in,out] p_inst Instance of the class - * @param[in] iface_idx Index of the interface inside class structure - * @param[in] alternate Alternate setting that should be selected - * - * @return Function has to return @ref NRF_SUCCESS when it has successfully proceed - * interface selection. - * If it returns @ref NRF_ERROR_NOT_SUPPORTED, default function would be used - * to proceed the request - just like there would be NULL pointer in this field. - * Any other kind of error would make library to STALL the request. - */ - ret_code_t (* iface_select)(app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx, - uint8_t alternate); - - /** - * @brief Deselect interface. - * - * Function called when the class interface has to be deselected. - * - * This function would be called for every interface when: - * - Library start internal event is processed by the default handler - * - RESET event is processed by the default handler - * - SET_ADDRESS is processed by the default handler - * - SET_CONFIG(0) is processed by the default handler - * - * @note Just after this function is called all the interface - * endpoints would be disabled. - * This function does not has to take care about it. - * @note If this function pointer is NULL default procedure would - * just disable all the interface endpoints. - * - * @param[in,out] p_inst Instance of the class. - * @param[in] iface_idx Index of the interface inside class structure. - */ - void (* iface_deselect)(app_usbd_class_inst_t const * const p_inst, uint8_t iface_idx); - - /** - * @brief Get current interface. - * - * Function called when class interface has to return its alternate settings - * in reaction on GET_INTERFACE command. - * It should be defined in a pair with @ref app_usbd_class_methods_t::iface_select. - * - * @param[in] p_inst Instance of the class. - * @param[in] iface_idx Index of the interface inside class structure. - * - * @return Current alternate setting of the selected interface. - * - * @note For the classes that support this function, when an interface that has not alternate - * configurations has been selected this function has to return 0 - default alternate setting. - * - * @note If this function pointer it NULL default procedure would return alternate interface - * value 0. - */ - uint8_t (* iface_selection_get)(app_usbd_class_inst_t const * const p_inst, uint8_t iface_idx); - -} app_usbd_class_methods_t; - -/** - * @brief The instance structure itself. - * - * The structure of base class instance. - */ -struct app_usbd_class_inst_s -{ - app_usbd_class_data_t * p_data; //!< Pointer to non-constant data - app_usbd_class_methods_t const * p_class_methods; //!< Class interface methods - struct - { - uint8_t cnt; //!< Number of defined interfaces - uint8_t config[]; //!< Interface configuration data followed by endpoint data - } iface; //!< Interface structure -}; - - -/** - * @brief Get total number of interfaces. - * - * - */ -static inline uint8_t app_usbd_class_iface_count_get(app_usbd_class_inst_t const * const p_inst) -{ - return p_inst->iface.cnt; -} - -/** - * @brief Interface accessing function. - * - * Get interface pointer. - * Interfaces create continuous array in the memory so it is possible to get - * interface with index 0 and then just iterate to the next one. - * - * @param p_inst Pointer to the class instance - * @param iface_idx Index of the instance to get. - * This is not the interface identifier. - * Technically it is the index of the interface in the class description array. - * @return Pointer to the interface configuration parameters or NULL if given index is out of interface scope for given class. - */ -static inline app_usbd_class_iface_conf_t const * app_usbd_class_iface_get( - app_usbd_class_inst_t const * const p_inst, - uint8_t iface_idx) -{ - ASSERT(NULL != p_inst); - if (iface_idx >= (app_usbd_class_iface_count_get(p_inst))) - { - return NULL; - } - - app_usbd_class_iface_conf_t const * p_interface = - (app_usbd_class_iface_conf_t const * )(p_inst->iface.config); - return &(p_interface[iface_idx]); -} - -/** - * @brief Get interface number. - * - * @param p_iface Pointer to interface structure. - * - * @return Interface number from interface configuration structure. - */ -static inline uint8_t app_usbd_class_iface_number_get( - app_usbd_class_iface_conf_t const * const p_iface) -{ - return p_iface->number; -} - -/** - * @brief Get number of endpoints in interface. - * - * @param p_iface Pointer to interface structure. - * - * @return Number of endpoints used by given interface. - */ -static inline uint8_t app_usbd_class_iface_ep_count_get( - app_usbd_class_iface_conf_t const * const p_iface) -{ - return p_iface->ep_cnt; -} - -/** - * @brief Interface Endpoint accessing function. - * - * @param p_iface Interface configuration pointer. - * @param ep_idx Endpoint index. - * - * @return Endpoint information structure pointer or NULL if given index is outside of endpoints for selected interface. - * - * @sa app_usbd_class_iface_get - */ -static inline app_usbd_class_ep_conf_t const * app_usbd_class_iface_ep_get( - app_usbd_class_iface_conf_t const * const p_iface, - uint8_t ep_idx) -{ - ASSERT(NULL != p_iface); - if (ep_idx >= p_iface->ep_cnt) - { - return NULL; - } - - app_usbd_class_ep_conf_t const * p_ep = - (app_usbd_class_ep_conf_t const * )(((uint8_t const *)p_iface) + p_iface->ep_offset); - return &(p_ep[ep_idx]); -} - -/** - * @brief Translate endpoint address to class index. - * - * @param p_iface Interface configuration pointer. - * @param ep_address Endpoint address. - * - * @return Endpoint index or number of endpoints if not found. - * - */ -static inline uint8_t app_usbd_class_iface_ep_idx_get( - app_usbd_class_iface_conf_t const * const p_iface, - nrf_drv_usbd_ep_t ep_address) -{ - ASSERT(NULL != p_iface); - app_usbd_class_ep_conf_t const * p_ep = - (app_usbd_class_ep_conf_t const * )(((uint8_t const *)p_iface) + p_iface->ep_offset); - - uint8_t i; - for (i = 0; i < p_iface->ep_cnt; ++i) - { - if (ep_address == p_ep[i].address) - { - break; - } - } - - return i; -} - -/** - * @brief Get the selected endpoint address. - * - * @param p_ep Endpoint configuration structure. - * - * @return Endpoint address - */ -static inline nrf_drv_usbd_ep_t app_usbd_class_ep_address_get(app_usbd_class_ep_conf_t const * p_ep) -{ - return (nrf_drv_usbd_ep_t)p_ep->address; -} - -/** - * @brief Get the pointer to the writable instance data. - * - * @param p_inst Instance pointer. - * @return Pointer to writable instance data. - */ -static inline app_usbd_class_data_t * app_usbd_class_data_access( - app_usbd_class_inst_t const * const p_inst) -{ - return p_inst->p_data; -} - -/** - * @name Internal macros for argument mapping - * - * Functions to be used as a mapping macro for @ref MACRO_MAP, @ref MACRO_MAP_FOR or @ref MACRO_MAP_FOR_PARAM - * @{ - */ - /** - * @brief Count the number of endpoints in given configuration. - * - * Config should be given as a interface configuration in a brackets: - * @code - * (interface_nr, ep1, ep2, ep3) - * @endcode - * Number of endpoints may vary from 0 to a few (technically up to 16, but it seems not to make sense to use more than 4). - * Interface number is always present. - * - * @param iface_config Single interface configuration (in brackets). - * - * @return Number of endpoints in interface. This is computed value - can be used by compiler but not by preprocessor. - */ - #define APP_USBD_CLASS_CONF_IFACE_EP_COUNT_(iface_config) \ - (NUM_VA_ARGS(BRACKET_EXTRACT(iface_config)) - 1) - - /** - * @brief Adds the number of endpoints in given config to the current value. - * - * This is basically @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ with plus sign added. - * - * @param iface_config See parameters documentation in @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ - * - * @return Plus sign followed by number of endpoints in interface. - * - * @sa APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ - */ - #define APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_(iface_config) \ - + APP_USBD_CLASS_CONF_IFACE_EP_COUNT_(iface_config) - - /** - * @brief Create variable for endpoint. - */ - - /** - * @brief Extract endpoints given interface configuration. - * - * This macro gets single endpoint configuration and extracts all the endpoints. - * It also adds comma on the end of extracted endpoints. - * This way when this macro is called few times it generates nice list of all endpoints - * that may be used to array initialization. - * - * @param iface_config Single interface configuration in brackets. - * The format should be similar like described in @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_. - */ - #define APP_USBD_CLASS_IFACE_EP_EXTRACT_(iface_config) \ - CONCAT_2(APP_USBD_CLASS_IFACE_EP_EXTRACT_, \ - NUM_VA_ARGS_IS_MORE_THAN_1(BRACKET_EXTRACT(iface_config))) \ - (BRACKET_EXTRACT(iface_config)) - - /** - * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_EP_EXTRACT_ - * - * This macro is called when interface has no endpoints. - */ - #define APP_USBD_CLASS_IFACE_EP_EXTRACT_0(iface_nr) - - /** - * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_EP_EXTRACT_ - * - * This macro is called when interface has at least one endpoint. - */ - #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1(...) \ - APP_USBD_CLASS_IFACE_EP_EXTRACT_1_(__VA_ARGS__) - - #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1_(iface_nr, ...) \ - MACRO_MAP_REC(APP_USBD_CLASS_IFACE_EP_EXTRACT_1__, __VA_ARGS__) - - #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1__(ep) \ - {(nrf_drv_usbd_ep_t) (ep)}, - - /** - * @brief Generate configuration for single interface. - * - * This macro extract configuration for single interface. - * The configuration is inside curly brackets and comma is added on the end. - * This mean it can be directly used to init array of interface configurations. - * - * @param iface_config Single interface configuration. - * @param N Currently processed configuration. - * @param iface_configs All interfaces configuration in brackets. - */ - #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_(iface_config, N, iface_configs) \ - CONCAT_2(APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_, \ - NUM_VA_ARGS_IS_MORE_THAN_1(BRACKET_EXTRACT(iface_config))) \ - (N, iface_configs, BRACKET_EXTRACT(iface_config)) - - /** - * @brief Macro used when there was an error extracting number of configs. - * - * Throws a syntax error. - */ - #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_x(iface_config, N, iface_configs) \ - [N] = !!!iface_config!!! - /** - * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ - * - * This macro is called when interface has no endpoints. - */ - #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0(N, iface_configs, iface_nr) \ - APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0_(N, iface_configs, iface_nr) - #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0_(N, iface_configs, iface_nr) \ - { .number = iface_nr, .ep_cnt = 0, .ep_offset = 0 }, - - /** - * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ - * - * This macro is called when interface has at last one endpoint. - */ - #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1(N, iface_configs, ...) \ - APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1_(N, iface_configs, __VA_ARGS__) - #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1_(N, iface_configs, iface_nr, ...) \ - { .number = iface_nr, .ep_cnt = NUM_VA_ARGS(__VA_ARGS__), \ - .ep_offset = APP_USBD_CLASS_CONF_TOTAL_EP_COUNT_N(N, iface_configs) * \ - sizeof(app_usbd_class_ep_conf_t) \ - + ((NUM_VA_ARGS(BRACKET_EXTRACT(iface_configs)) - N) * \ - sizeof(app_usbd_class_iface_conf_t)) \ - }, - -/** @} */ - - -/** - * @name Macros that uses mapping macros internally - * - * Auxiliary macros that uses mapping macros to make some calculations or realize other functionality. - * Mapped here for easier unit testing and to hide complex mapping functions calling. - * @{ - */ - -/** - * @brief Count total number of endpoints. - * - * @param iface_configs List of interface configurations like explained - * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF - * - * @return The equation to calculate the number of endpoints by compiler. - */ -#define APP_USBD_CLASS_CONF_TOTAL_EP_COUNT(iface_configs) \ - (0 MACRO_MAP(APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_, BRACKET_EXTRACT(iface_configs))) - -/** - * @brief Count total number of endpoint up-to interface index. - * - * The version of @ref APP_USBD_CLASS_CONF_TOTAL_EP_COUNT macro which takes the - * number of interfaces to analyze. - * - * @param N Number of interfaces to analyze. - * @param iface_configs List of interface configurations like explained - * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF - * - * @return The equation to calculate the number of endpoints by compiler. - */ -#define APP_USBD_CLASS_CONF_TOTAL_EP_COUNT_N(N, iface_configs) \ - (0 MACRO_MAP_N(N, APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_, BRACKET_EXTRACT(iface_configs))) - -/** - * @brief Extract configurations for interfaces. - * - * This macro extracts the configurations for every interface. - * Basically uses the @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ macro on every - * configuration found. - * - * This should generate interface configuration initialization data - * in comma separated initializers in curly braces. - * - * @param iface_configs List of interface configurations like explained - * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF - * - * @return Comma separated initialization data for all interfaces. - */ -/*lint -emacro( (40), APP_USBD_CLASS_IFACES_CONFIG_EXTRACT) */ -#define APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(iface_configs) \ - MACRO_MAP_FOR_PARAM(iface_configs, \ - APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_, \ - BRACKET_EXTRACT(iface_configs)) - -/** - * @brief Extract all endpoints. - * - * Macro that extracts all endpoints from every interface. - * - * @param iface_configs List of interface configurations like explained - * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF - * - * @return Comma separated list of endpoints. - */ -/*lint -emacro( (40), APP_USBD_CLASS_IFACES_EP_EXTRACT) */ -#define APP_USBD_CLASS_IFACES_EP_EXTRACT(iface_configs) \ - MACRO_MAP(APP_USBD_CLASS_IFACE_EP_EXTRACT_, BRACKET_EXTRACT(iface_configs)) - - -/** @} */ - - -/** - * @brief USBD instance of class mnemonic. - * - * Macro that generates mnemonic for the name of the structure that describes instance for selected class. - * - * @param type_name The name of the instance without _t postfix. - * - * @return The name with the right postfix to create the name for the type for the class. - */ -#define APP_USBD_CLASS_INSTANCE_TYPE(type_name) CONCAT_2(type_name, _t) - -/** - * @brief USBD data for instance class mnemonic. - * - * The mnemonic of the variable type that holds writable part of the class instance. - * - * @param type_name The name of the instance without _t postfix. - * - * @return The name with the right postfix to create the name for the data type for the class. - */ -#define APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(type_name, _data_t) - -/** - * @brief Declare class specific member of class instance. - * - * @param type Type of the attached class configuration. - * - * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF - */ -#define APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC(type) type class_part; - -/** - * @brief Used if there is no class specific configuration. - * - * This constant can be used if there is no specific configuration inside created instance. - * - * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF - */ -#define APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE - -/** - * @brief Declare class specific member of class data. - * - * @param type Type of the attached class data. - * - * @sa APP_USBD_CLASS_DATA_TYPEDEF - */ -#define APP_USBD_CLASS_DATA_SPECIFIC_DEC(type) APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC(type) - -/** - * @brief Used if there is no class specific data. - * - * This constant can be used if there is no specific writable data inside created instance. - * - * @sa APP_USBD_CLASS_DATA_TYPEDEF - */ -#define APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE - - - - -/** - * @brief Instance structure declaration. - * - * The macro that declares a variable type that would be used to store given class instance. - * Class instance stores all the data from @ref app_usbd_class_inst_t and overlaid data for specified class. - * - * The structure of interface configuration data: - * @code - * ( - * (iface1_nr, (ep1, ep2, ep3)), - (iface2_nr), - (iface3_nr, (ep4)) - * ) - * @endcode - * - * @param type_name The name of the instance without _t postfix. - * @param interfaces_configs List of interface configurations like explained above. - * @param class_config_dec Result of the macro - * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC or - * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE - * - * @return The definition of the structure type that holds all the required data. - * - * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_DATA_TYPEDEF instead. - * - * @note APP_USBD_CLASS_DATA_TYPEDEF has to be called first for the compilation to success. - * - * @sa APP_USBD_CLASS_TYPEDEF - */ -#define APP_USBD_CLASS_INSTANCE_TYPEDEF(type_name, interfaces_configs, class_config_dec) \ - typedef union CONCAT_2(type_name, _u) \ - { \ - app_usbd_class_inst_t base; \ - struct \ - { \ - APP_USBD_CLASS_DATA_TYPE(type_name) * p_data; \ - app_usbd_class_methods_t const * p_class_methods; \ - struct \ - { \ - uint8_t cnt; \ - app_usbd_class_iface_conf_t \ - config[NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs))]; \ - app_usbd_class_ep_conf_t \ - ep[APP_USBD_CLASS_CONF_TOTAL_EP_COUNT(interfaces_configs)]; \ - } iface; \ - class_config_dec \ - } specific; \ - } APP_USBD_CLASS_INSTANCE_TYPE(type_name) - -/** - * @brief Same as @ref APP_USBD_CLASS_INSTANCE_TYPEDEF but for class with EP0 only. - */ -#define APP_USBD_CLASS_INSTANCE_NO_EP_TYPEDEF(type_name, interfaces_configs, class_config_dec) \ - typedef union CONCAT_2(type_name, _u) \ - { \ - app_usbd_class_inst_t base; \ - struct \ - { \ - APP_USBD_CLASS_DATA_TYPE(type_name) * p_data; \ - app_usbd_class_methods_t const * p_class_methods; \ - struct \ - { \ - uint8_t cnt; \ - app_usbd_class_iface_conf_t \ - config[NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs))]; \ - } iface; \ - class_config_dec \ - } specific; \ - } APP_USBD_CLASS_INSTANCE_TYPE(type_name) - -/** - * @brief Writable data structure declaration. - * - * The macro that declares a variable type that would be used to store given class writable data. - * Writable data contains base part of the type @ref app_usbd_class_data_t followed by - * class specific data. - * - * @param type_name The name of the type without _t postfix. - * @param class_data_dec Result of the macro - * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC or - * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE - * - * @return The definition of the structure type that holds all the required writable data. - * - * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_DATA_TYPEDEF instead. - * - * @sa APP_USBD_CLASS_TYPEDEF - */ -#define APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec) \ - typedef struct \ - { \ - app_usbd_class_data_t base; \ - class_data_dec \ - }APP_USBD_CLASS_DATA_TYPE(type_name) - - -/** - * @brief Declare all data types required by the class instance. - * - * Macro that declares data type first and then instance type. - * - * @param type_name The name of the type without _t postfix. - * @param interface_configs List of interface configurations like in @ref APP_USBD_CLASS_INSTANCE_TYPEDEF. - * @param class_config_dec Result of the macro - * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC or - * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE - * @param class_data_dec Result of the macro - * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC or - * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE - * - * @return Declaration of the data type for the instance and instance itself. - * - * @sa APP_USBD_CLASS_DATA_TYPEDEF - * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF - */ -#define APP_USBD_CLASS_TYPEDEF(type_name, interface_configs, class_config_dec, class_data_dec) \ - APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec); \ - APP_USBD_CLASS_INSTANCE_TYPEDEF(type_name, interface_configs, class_config_dec) - -/** - * @brief Same as @ref APP_USBD_CLASS_TYPEDEF but for class with EP0 only. - */ -#define APP_USBD_CLASS_NO_EP_TYPEDEF(type_name, \ - interface_configs, \ - class_config_dec, \ - class_data_dec) \ - APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec); \ - APP_USBD_CLASS_INSTANCE_NO_EP_TYPEDEF(type_name, interface_configs, class_config_dec) - -/** - * @brief Forward declaration of type defined by @ref APP_USBD_CLASS_TYPEDEF - * - * @param type_name The name of the type without _t postfix. - * */ -#define APP_USBD_CLASS_FORWARD(type_name) union CONCAT_2(type_name, _u) - -/** - * @brief Generate the initialization data for. - * - * Macro that generates the initialization data for instance. - * - * @param p_ram_data Pointer to writable instance data structure. - * @param class_methods Class methods. - * @param interfaces_configs Exactly the same interface config data that in @ref APP_USBD_CLASS_INSTANCE_TYPEDEF - * @param class_config_part Configuration part. The data should be inside brackets. - * Any data here would be removed from brackets and then put as an initialization - * data for class_part member of instance structure. - * - * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_INST_DEF instead. - */ -#define APP_USBD_CLASS_INSTANCE_INITVAL(p_ram_data, \ - class_methods, \ - interfaces_configs, \ - class_config_part) \ - { \ - .specific = { \ - .p_data = p_ram_data, \ - .p_class_methods = class_methods, \ - .iface = { \ - .cnt = NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs)), \ - .config = { APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(interfaces_configs) }, \ - .ep = { APP_USBD_CLASS_IFACES_EP_EXTRACT(interfaces_configs) } \ - }, \ - BRACKET_EXTRACT(class_config_part) \ - } \ - } - -/** - * @brief Same as @ref APP_USBD_CLASS_INSTANCE_INITVAL but for class with EP0 only. - */ -#define APP_USBD_CLASS_INSTANCE_NO_EP_INITVAL(p_ram_data, \ - class_methods, \ - interfaces_configs, \ - class_config_part) \ - { \ - .specific = { \ - .p_data = p_ram_data, \ - .p_class_methods = class_methods, \ - .iface = { \ - .cnt = NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs)), \ - .config = { APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(interfaces_configs) } \ - }, \ - BRACKET_EXTRACT(class_config_part) \ - } \ - } - -/** - * @brief Define the base class instance. - * - * Macro that defines whole instance variable and fill it with initialization data. - * - * The tricky part is @c class_config_part. - * The configuration data here has to be placed inside brackets. - * Then any type of values can be used depending on the type used in @ref APP_USBD_CLASS_TYPEDEF. - * If instance does not has any specyfic data, use just empty bracket here. - * @code - * APP_USBD_CLASS_TYPEDEF( - * some_base_class, - * CLASS_BASE_CONFIGURATION, - * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, - * APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE - * ); - * APP_USBD_CLASS_INST_DEF( - * some_base_class_inst, - * some_base_class, - * base_class_event_handler, - * CLASS_BASE_CONFIGURATION, - * () // Empty configuration - * ); - * @endcode - * - * If the type of instance configuration is simple type, just provide initialization value: - * @code - * APP_USBD_CLASS_TYPEDEF( - * some_base_class, - * CLASS_BASE_CONFIGURATION, - * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, - * APP_USBD_CLASS_DATA_SPECIFIC_DEC(uint8_t) - * ); - * APP_USBD_CLASS_INST_DEF( - * some_base_class_inst, - * some_base_class, - * base_class_event_handler, - * CLASS_BASE_CONFIGURATION, - * (12) // Example values - * ); - * @endcode - * - * If the type of instance configuration is structure, provide initialization value for the whole structure: - * @code - * typedef structure - * { - * uint32_t p1; - * uint8_t p2; - * }my_config_t; - * - * APP_USBD_CLASS_TYPEDEF( - * some_base_class, - * CLASS_BASE_CONFIGURATION, - * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, - * APP_USBD_CLASS_DATA_SPECIFIC_DEC(my_config_t) - * ); - * APP_USBD_CLASS_INST_DEF( - * some_base_class_inst, - * some_base_class, - * base_class_event_handler, - * CLASS_BASE_CONFIGURATION, - * ({12, 3}) // Example values - * ); - * @endcode - * - * @param instance_name The name of created instance variable. - * It would be constant variable and its type would be app_usbd_class_inst_t. - * @param type_name The name of the variable type. It has to be the same type that was passed to - * @ref APP_USBD_CLASS_TYPEDEF - * @param class_methods Class unified interface. - * @param interfaces_configs The same configuration data that the one passed to @ref APP_USBD_CLASS_TYPEDEF - * @param class_config_part Configuration data to the type that was declared by class_data_dec when calling - * @ref APP_USBD_CLASS_TYPEDEF. - * Configuration data has to be provided in brackets. - * It would be extracted from brackets and placed in initialization part of configuration structure. - * See detailed description of this macro for more informations. - */ -#define APP_USBD_CLASS_INST_DEF(instance_name, \ - type_name, \ - class_methods, \ - interfaces_configs, \ - class_config_part) \ - static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \ - static const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \ - APP_USBD_CLASS_INSTANCE_INITVAL( \ - &CONCAT_2(instance_name, _data), \ - class_methods, \ - interfaces_configs, \ - class_config_part) - - -/** - * @brief Define the base class instance in global scope. - * - * This is the same macro like @ref APP_USBD_CLASS_INST_DEF but it creates the instance - * without static keyword. - * - * @param instance_name See documentation for @ref APP_USBD_CLASS_INST_DEF - * @param type_name See documentation for @ref APP_USBD_CLASS_INST_DEF - * @param class_methods See documentation for @ref APP_USBD_CLASS_INST_DEF - * @param interfaces_configs See documentation for @ref APP_USBD_CLASS_INST_DEF - * @param class_config_part See documentation for @ref APP_USBD_CLASS_INST_DEF - */ -#define APP_USBD_CLASS_INST_GLOBAL_DEF(instance_name, \ - type_name, \ - class_methods, \ - interfaces_configs, \ - class_config_part) \ - static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \ - const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \ - APP_USBD_CLASS_INSTANCE_INITVAL( \ - &CONCAT_2(instance_name, _data), \ - class_methods, \ - interfaces_configs, \ - class_config_part) - -/** - * @brief Same as @ref APP_USBD_CLASS_INST_GLOBAL_DEF but for class with EP0 only. - */ -#define APP_USBD_CLASS_INST_NO_EP_GLOBAL_DEF(instance_name, \ - type_name, \ - class_methods, \ - interfaces_configs, \ - class_config_part) \ - static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \ - const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \ - APP_USBD_CLASS_INSTANCE_NO_EP_INITVAL( \ - &CONCAT_2(instance_name, _data), \ - class_methods, \ - interfaces_configs, \ - class_config_part) -/** - * @brief Access class specific configuration. - * - * Macro that returns class specific configuration. - * - * @param[in] p_inst Instance pointer. - * - * @return A pointer for class specific part of the instance. - * - * @note If macro is used on the instance that has no class specific configuration - * an error would be generated during compilation. - */ -#define APP_USBD_CLASS_GET_SPECIFIC_CONFIG(p_inst) (&((p_inst)->specific.class_part)) - -/** - * @brief Access class specific data. - * - * @param[in] p_inst Instance pointer. - * - * @return A pointer for class specific part of writable data. - * - * @note If macro is used on the instance that has no class specific data - * an error would be generated during compilation. - */ -#define APP_USBD_CLASS_GET_SPECIFIC_DATA(p_inst) (&(((p_inst)->specific.p_data)->class_part)) - -/** - * @brief Macro to get base instance from class specific instance. - * - * This macro may be used on class specific instance to get base instance that - * can be processed by base instance access functions. - * Class specific instance can be just casted to class base instance, - * but then we would totally lost type safety. - * - * A little more safe is to use pointer to base member of class instance. - * This would generate an error when used on any variable that has no base member - * and would generate also error if this base member is wrong type. - */ -#define APP_USBD_CLASS_BASE_INSTANCE(p_inst) (&((p_inst)->base)) - -/*lint -emacro(142 438 616 646, APP_USBD_CLASS_DESCRIPTOR_INIT, APP_USBD_CLASS_DESCRIPTOR_BEGIN, APP_USBD_CLASS_DESCRIPTOR_YIELD, APP_USBD_CLASS_DESCRIPTOR_END, APP_USBD_CLASS_DESCRIPTOR_WRITE)*/ - -/** - * @brief Initialize class descriptor. - * - * @param[in] p_ctx Class descriptor context. - */ - -#define APP_USBD_CLASS_DESCRIPTOR_INIT(p_ctx) \ - (p_ctx)->line = 0; - -/** - * @brief Begin class descriptor. - * - * @param[in] p_ctx Class descriptor context. - * @param[in] p_buff Buffer to write into. - * @param[in] max_size Size of the buffer. - */ - -#define APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size) \ - ASSERT((p_ctx) != NULL); \ - app_usbd_class_descriptor_state_t this_descriptor_feed; \ - this_descriptor_feed.p_buffer = (p_buff); \ - this_descriptor_feed.current_size = 0; \ - this_descriptor_feed.maximum_size = (max_size); \ - this_descriptor_feed.p_context = (p_ctx); \ - switch ((this_descriptor_feed.p_context)->line) \ - { \ - case 0: \ - ; - -/** - * @brief Yield class descriptor - * - */ - -#define APP_USBD_CLASS_DESCRIPTOR_YIELD() \ -do \ -{ \ - (this_descriptor_feed.p_context)->line = __LINE__; \ - return true; \ - case __LINE__: \ - ; \ -} while (0) - -/*lint -emacro(438 527, APP_USBD_CLASS_DESCRIPTOR_END)*/ - -/** - * @brief End class descriptor. - * - * This function has to be called at the end of class descriptor feeder function. - * No other operations in feeder function can be done after calling it. - */ - -#define APP_USBD_CLASS_DESCRIPTOR_END() \ - APP_USBD_CLASS_DESCRIPTOR_YIELD(); \ - } \ - (this_descriptor_feed.p_context)->line = 0; \ - return false; - - -/** - * @brief Write descriptor using protothreads. - * - * This function writes one byte to the buffer with offset. If buffer is full - * it yields. - * - * It is used by the class descriptor feeders internally. - * - * @ref APP_USBD_CLASS_DESCRIPTOR_BEGIN has to be called before using this function. - * @ref APP_USBD_CLASS_DESCRIPTOR_END has to be called after last use of this function. - * - * @param data Byte to be written to buffer. - */ -#define APP_USBD_CLASS_DESCRIPTOR_WRITE(data) \ -do \ -{ \ - (this_descriptor_feed.p_context)->data_buffer = (data); \ - if (this_descriptor_feed.current_size >= this_descriptor_feed.maximum_size) \ - { \ - APP_USBD_CLASS_DESCRIPTOR_YIELD(); \ - } \ - if(this_descriptor_feed.p_buffer != NULL) \ - { \ - *(this_descriptor_feed.p_buffer + this_descriptor_feed.current_size) = \ - (this_descriptor_feed.p_context)->data_buffer; \ - } \ - this_descriptor_feed.current_size++; \ -} while(0); - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_CLASS_BASE_H__ */ +/** + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef APP_USBD_CLASS_BASE_H__ +#define APP_USBD_CLASS_BASE_H__ + +#include +#include + +#include "app_usbd_types.h" +#include "nrf_drv_usbd.h" +#include "nrf_assert.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup app_usbd_class_base USBD Class Base module + * @ingroup app_usbd + * + * @brief @tagAPI52840 The base for any class instance is defined in this module. + * + * @details Any class instance must start from base class instance structure. + * This makes them compatible with USBD library independently of the + * implementation details. + * @{ + */ + +/** + * @brief Endpoint configuration. + */ +typedef struct +{ + nrf_drv_usbd_ep_t address; //!< Endpoint address +} app_usbd_class_ep_conf_t; + +/** + * @brief Interface configuration. + */ +typedef struct +{ + uint8_t number; //!< Interface number + uint8_t ep_cnt; //!< Endpoint number + uint8_t ep_offset; //!< Offset of the first endpoint + /**< Offset in bytes of the first endpoint. + * The offset is calculated from the address of this interface structure + */ +} app_usbd_class_iface_conf_t; + +/** + * @brief Instance variable data. + */ +typedef struct +{ + app_usbd_class_inst_t const * p_next; //!< Pointer to the next instance + app_usbd_class_inst_t const * p_sof_next; //!< Pointer to the next SOF event requiring instance + app_usbd_sof_interrupt_handler_t sof_handler; //!< Instance specific SOF interrupt handler +} app_usbd_class_data_t; + +/** + * @brief Class descriptor context. + */ +typedef struct +{ + uint32_t line; //!< Number of line to resume writing descriptors from + uint8_t data_buffer; //!< Data from last call of feeder +} app_usbd_class_descriptor_ctx_t; + +/** + * @brief Class descriptor state. + */ +typedef struct +{ + uint8_t * p_buffer; //!< Pointer to buffer + uint32_t current_size; //!< Current size of descriptor + uint32_t maximum_size; //!< Maximum size of descriptor + app_usbd_class_descriptor_ctx_t * p_context; //!< Pointer to context +} app_usbd_class_descriptor_state_t; + +/** + * @brief Class interface function set. + * */ +typedef struct { + /** + * @brief Instance callback function. + * + * The function used by every class instance. + * @param[in,out] p_inst Instance of the class. + * @param[in] p_event Event to process. + * + * @return Standard error code. + * + * @note If given event is not supported by class, return @ref NRF_ERROR_NOT_SUPPORTED + */ + ret_code_t (* event_handler)(app_usbd_class_inst_t const * const p_inst, + app_usbd_complex_evt_t const * const p_event); + + /** + * @brief Instance feed descriptors. + * + * Feeds whole descriptor of the instance. + * @param[in] p_ctx Class descriptor context. + * @param[in,out] p_inst Instance of the class. + * @param[out] p_buff Buffer for descriptor. + * @param[in] max_size Requested size of the descriptor. + * + * @return True if not finished feeding the descriptor, false if done. + */ + bool (* feed_descriptors)(app_usbd_class_descriptor_ctx_t * p_ctx, + app_usbd_class_inst_t const * p_inst, + uint8_t * p_buff, + size_t max_size); + + + /** + * @brief Select interface + * + * Function called when class interface has to be selected. + * + * This function would be called for every interface when: + * - SET_INTERFACE command is processed by the default handler + * - SET_CONFIG(1) command is processed by the default handler + * + * @note Remember to disable all the endpoints that are not used + * in the selected configuration. + * @note If this function pointer is NULL default procedure would + * just enable all the interface endpoints and selecting + * alternate configurations other than 0 would generate error. + * @note Calling the function with alternate setting 0 has to always succeed. + * + * @param[in,out] p_inst Instance of the class + * @param[in] iface_idx Index of the interface inside class structure + * @param[in] alternate Alternate setting that should be selected + * + * @return Function has to return @ref NRF_SUCCESS when it has successfully proceed + * interface selection. + * If it returns @ref NRF_ERROR_NOT_SUPPORTED, default function would be used + * to proceed the request - just like there would be NULL pointer in this field. + * Any other kind of error would make library to STALL the request. + */ + ret_code_t (* iface_select)(app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx, + uint8_t alternate); + + /** + * @brief Deselect interface. + * + * Function called when the class interface has to be deselected. + * + * This function would be called for every interface when: + * - Library start internal event is processed by the default handler + * - RESET event is processed by the default handler + * - SET_ADDRESS is processed by the default handler + * - SET_CONFIG(0) is processed by the default handler + * + * @note Just after this function is called all the interface + * endpoints would be disabled. + * This function does not has to take care about it. + * @note If this function pointer is NULL default procedure would + * just disable all the interface endpoints. + * + * @param[in,out] p_inst Instance of the class. + * @param[in] iface_idx Index of the interface inside class structure. + */ + void (* iface_deselect)(app_usbd_class_inst_t const * const p_inst, uint8_t iface_idx); + + /** + * @brief Get current interface. + * + * Function called when class interface has to return its alternate settings + * in reaction on GET_INTERFACE command. + * It should be defined in a pair with @ref app_usbd_class_methods_t::iface_select. + * + * @param[in] p_inst Instance of the class. + * @param[in] iface_idx Index of the interface inside class structure. + * + * @return Current alternate setting of the selected interface. + * + * @note For the classes that support this function, when an interface that has not alternate + * configurations has been selected this function has to return 0 - default alternate setting. + * + * @note If this function pointer it NULL default procedure would return alternate interface + * value 0. + */ + uint8_t (* iface_selection_get)(app_usbd_class_inst_t const * const p_inst, uint8_t iface_idx); + +} app_usbd_class_methods_t; + +/** + * @brief The instance structure itself. + * + * The structure of base class instance. + */ +struct app_usbd_class_inst_s +{ + app_usbd_class_data_t * p_data; //!< Pointer to non-constant data + app_usbd_class_methods_t const * p_class_methods; //!< Class interface methods + struct + { + uint8_t cnt; //!< Number of defined interfaces + uint8_t config[]; //!< Interface configuration data followed by endpoint data + } iface; //!< Interface structure +}; + + +/** + * @brief Get total number of interfaces. + * + * + */ +static inline uint8_t app_usbd_class_iface_count_get(app_usbd_class_inst_t const * const p_inst) +{ + return p_inst->iface.cnt; +} + +/** + * @brief Interface accessing function. + * + * Get interface pointer. + * Interfaces create continuous array in the memory so it is possible to get + * interface with index 0 and then just iterate to the next one. + * + * @param p_inst Pointer to the class instance + * @param iface_idx Index of the instance to get. + * This is not the interface identifier. + * Technically it is the index of the interface in the class description array. + * @return Pointer to the interface configuration parameters or NULL if given index is out of interface scope for given class. + */ +static inline app_usbd_class_iface_conf_t const * app_usbd_class_iface_get( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx) +{ + ASSERT(NULL != p_inst); + if (iface_idx >= (app_usbd_class_iface_count_get(p_inst))) + { + return NULL; + } + + app_usbd_class_iface_conf_t const * p_interface = + (app_usbd_class_iface_conf_t const * )(p_inst->iface.config); + return &(p_interface[iface_idx]); +} + +/** + * @brief Get interface number. + * + * @param p_iface Pointer to interface structure. + * + * @return Interface number from interface configuration structure. + */ +static inline uint8_t app_usbd_class_iface_number_get( + app_usbd_class_iface_conf_t const * const p_iface) +{ + return p_iface->number; +} + +/** + * @brief Get number of endpoints in interface. + * + * @param p_iface Pointer to interface structure. + * + * @return Number of endpoints used by given interface. + */ +static inline uint8_t app_usbd_class_iface_ep_count_get( + app_usbd_class_iface_conf_t const * const p_iface) +{ + return p_iface->ep_cnt; +} + +/** + * @brief Interface Endpoint accessing function. + * + * @param p_iface Interface configuration pointer. + * @param ep_idx Endpoint index. + * + * @return Endpoint information structure pointer or NULL if given index is outside of endpoints for selected interface. + * + * @sa app_usbd_class_iface_get + */ +static inline app_usbd_class_ep_conf_t const * app_usbd_class_iface_ep_get( + app_usbd_class_iface_conf_t const * const p_iface, + uint8_t ep_idx) +{ + ASSERT(NULL != p_iface); + if (ep_idx >= p_iface->ep_cnt) + { + return NULL; + } + + app_usbd_class_ep_conf_t const * p_ep = + (app_usbd_class_ep_conf_t const * )(((uint8_t const *)p_iface) + p_iface->ep_offset); + return &(p_ep[ep_idx]); +} + +/** + * @brief Translate endpoint address to class index. + * + * @param p_iface Interface configuration pointer. + * @param ep_address Endpoint address. + * + * @return Endpoint index or number of endpoints if not found. + * + */ +static inline uint8_t app_usbd_class_iface_ep_idx_get( + app_usbd_class_iface_conf_t const * const p_iface, + nrf_drv_usbd_ep_t ep_address) +{ + ASSERT(NULL != p_iface); + app_usbd_class_ep_conf_t const * p_ep = + (app_usbd_class_ep_conf_t const * )(((uint8_t const *)p_iface) + p_iface->ep_offset); + + uint8_t i; + for (i = 0; i < p_iface->ep_cnt; ++i) + { + if (ep_address == p_ep[i].address) + { + break; + } + } + + return i; +} + +/** + * @brief Get the selected endpoint address. + * + * @param p_ep Endpoint configuration structure. + * + * @return Endpoint address + */ +static inline nrf_drv_usbd_ep_t app_usbd_class_ep_address_get(app_usbd_class_ep_conf_t const * p_ep) +{ + return (nrf_drv_usbd_ep_t)p_ep->address; +} + +/** + * @brief Get the pointer to the writable instance data. + * + * @param p_inst Instance pointer. + * @return Pointer to writable instance data. + */ +static inline app_usbd_class_data_t * app_usbd_class_data_access( + app_usbd_class_inst_t const * const p_inst) +{ + return p_inst->p_data; +} + +/** + * @name Internal macros for argument mapping + * + * Functions to be used as a mapping macro for @ref MACRO_MAP, @ref MACRO_MAP_FOR or @ref MACRO_MAP_FOR_PARAM + * @{ + */ + /** + * @brief Count the number of endpoints in given configuration. + * + * Config should be given as a interface configuration in a brackets: + * @code + * (interface_nr, ep1, ep2, ep3) + * @endcode + * Number of endpoints may vary from 0 to a few (technically up to 16, but it seems not to make sense to use more than 4). + * Interface number is always present. + * + * @param iface_config Single interface configuration (in brackets). + * + * @return Number of endpoints in interface. This is computed value - can be used by compiler but not by preprocessor. + */ + #define APP_USBD_CLASS_CONF_IFACE_EP_COUNT_(iface_config) \ + (NUM_VA_ARGS(BRACKET_EXTRACT(iface_config)) - 1) + + /** + * @brief Adds the number of endpoints in given config to the current value. + * + * This is basically @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ with plus sign added. + * + * @param iface_config See parameters documentation in @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ + * + * @return Plus sign followed by number of endpoints in interface. + * + * @sa APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ + */ + #define APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_(iface_config) \ + + APP_USBD_CLASS_CONF_IFACE_EP_COUNT_(iface_config) + + /** + * @brief Create variable for endpoint. + */ + + /** + * @brief Extract endpoints given interface configuration. + * + * This macro gets single endpoint configuration and extracts all the endpoints. + * It also adds comma on the end of extracted endpoints. + * This way when this macro is called few times it generates nice list of all endpoints + * that may be used to array initialization. + * + * @param iface_config Single interface configuration in brackets. + * The format should be similar like described in @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_. + */ + #define APP_USBD_CLASS_IFACE_EP_EXTRACT_(iface_config) \ + CONCAT_2(APP_USBD_CLASS_IFACE_EP_EXTRACT_, \ + NUM_VA_ARGS_IS_MORE_THAN_1(BRACKET_EXTRACT(iface_config))) \ + (BRACKET_EXTRACT(iface_config)) + + /** + * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_EP_EXTRACT_ + * + * This macro is called when interface has no endpoints. + */ + #define APP_USBD_CLASS_IFACE_EP_EXTRACT_0(iface_nr) + + /** + * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_EP_EXTRACT_ + * + * This macro is called when interface has at least one endpoint. + */ + #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1(...) \ + APP_USBD_CLASS_IFACE_EP_EXTRACT_1_(__VA_ARGS__) + + #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1_(iface_nr, ...) \ + MACRO_MAP_REC(APP_USBD_CLASS_IFACE_EP_EXTRACT_1__, __VA_ARGS__) + + #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1__(ep) \ + {(nrf_drv_usbd_ep_t) (ep)}, + + /** + * @brief Generate configuration for single interface. + * + * This macro extract configuration for single interface. + * The configuration is inside curly brackets and comma is added on the end. + * This mean it can be directly used to init array of interface configurations. + * + * @param iface_config Single interface configuration. + * @param N Currently processed configuration. + * @param iface_configs All interfaces configuration in brackets. + */ + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_(iface_config, N, iface_configs) \ + CONCAT_2(APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_, \ + NUM_VA_ARGS_IS_MORE_THAN_1(BRACKET_EXTRACT(iface_config))) \ + (N, iface_configs, BRACKET_EXTRACT(iface_config)) + + /** + * @brief Macro used when there was an error extracting number of configs. + * + * Throws a syntax error. + */ + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_x(iface_config, N, iface_configs) \ + [N] = !!!iface_config!!! + /** + * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ + * + * This macro is called when interface has no endpoints. + */ + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0(N, iface_configs, iface_nr) \ + APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0_(N, iface_configs, iface_nr) + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0_(N, iface_configs, iface_nr) \ + { .number = iface_nr, .ep_cnt = 0, .ep_offset = 0 }, + + /** + * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ + * + * This macro is called when interface has at last one endpoint. + */ + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1(N, iface_configs, ...) \ + APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1_(N, iface_configs, __VA_ARGS__) + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1_(N, iface_configs, iface_nr, ...) \ + { .number = iface_nr, .ep_cnt = NUM_VA_ARGS(__VA_ARGS__), \ + .ep_offset = APP_USBD_CLASS_CONF_TOTAL_EP_COUNT_N(N, iface_configs) * \ + sizeof(app_usbd_class_ep_conf_t) \ + + ((NUM_VA_ARGS(BRACKET_EXTRACT(iface_configs)) - N) * \ + sizeof(app_usbd_class_iface_conf_t)) \ + }, + +/** @} */ + + +/** + * @name Macros that uses mapping macros internally + * + * Auxiliary macros that uses mapping macros to make some calculations or realize other functionality. + * Mapped here for easier unit testing and to hide complex mapping functions calling. + * @{ + */ + +/** + * @brief Count total number of endpoints. + * + * @param iface_configs List of interface configurations like explained + * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * + * @return The equation to calculate the number of endpoints by compiler. + */ +#define APP_USBD_CLASS_CONF_TOTAL_EP_COUNT(iface_configs) \ + (0 MACRO_MAP(APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_, BRACKET_EXTRACT(iface_configs))) + +/** + * @brief Count total number of endpoint up-to interface index. + * + * The version of @ref APP_USBD_CLASS_CONF_TOTAL_EP_COUNT macro which takes the + * number of interfaces to analyze. + * + * @param N Number of interfaces to analyze. + * @param iface_configs List of interface configurations like explained + * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * + * @return The equation to calculate the number of endpoints by compiler. + */ +#define APP_USBD_CLASS_CONF_TOTAL_EP_COUNT_N(N, iface_configs) \ + (0 MACRO_MAP_N(N, APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_, BRACKET_EXTRACT(iface_configs))) + +/** + * @brief Extract configurations for interfaces. + * + * This macro extracts the configurations for every interface. + * Basically uses the @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ macro on every + * configuration found. + * + * This should generate interface configuration initialization data + * in comma separated initializers in curly braces. + * + * @param iface_configs List of interface configurations like explained + * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * + * @return Comma separated initialization data for all interfaces. + */ +/*lint -emacro( (40), APP_USBD_CLASS_IFACES_CONFIG_EXTRACT) */ +#define APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(iface_configs) \ + MACRO_MAP_FOR_PARAM(iface_configs, \ + APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_, \ + BRACKET_EXTRACT(iface_configs)) + +/** + * @brief Extract all endpoints. + * + * Macro that extracts all endpoints from every interface. + * + * @param iface_configs List of interface configurations like explained + * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * + * @return Comma separated list of endpoints. + */ +/*lint -emacro( (40), APP_USBD_CLASS_IFACES_EP_EXTRACT) */ +#define APP_USBD_CLASS_IFACES_EP_EXTRACT(iface_configs) \ + MACRO_MAP(APP_USBD_CLASS_IFACE_EP_EXTRACT_, BRACKET_EXTRACT(iface_configs)) + + +/** @} */ + + +/** + * @brief USBD instance of class mnemonic. + * + * Macro that generates mnemonic for the name of the structure that describes instance for selected class. + * + * @param type_name The name of the instance without _t postfix. + * + * @return The name with the right postfix to create the name for the type for the class. + */ +#define APP_USBD_CLASS_INSTANCE_TYPE(type_name) CONCAT_2(type_name, _t) + +/** + * @brief USBD data for instance class mnemonic. + * + * The mnemonic of the variable type that holds writable part of the class instance. + * + * @param type_name The name of the instance without _t postfix. + * + * @return The name with the right postfix to create the name for the data type for the class. + */ +#define APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(type_name, _data_t) + +/** + * @brief Declare class specific member of class instance. + * + * @param type Type of the attached class configuration. + * + * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF + */ +#define APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC(type) type class_part; + +/** + * @brief Used if there is no class specific configuration. + * + * This constant can be used if there is no specific configuration inside created instance. + * + * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF + */ +#define APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE + +/** + * @brief Declare class specific member of class data. + * + * @param type Type of the attached class data. + * + * @sa APP_USBD_CLASS_DATA_TYPEDEF + */ +#define APP_USBD_CLASS_DATA_SPECIFIC_DEC(type) APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC(type) + +/** + * @brief Used if there is no class specific data. + * + * This constant can be used if there is no specific writable data inside created instance. + * + * @sa APP_USBD_CLASS_DATA_TYPEDEF + */ +#define APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE + + + + +/** + * @brief Instance structure declaration. + * + * The macro that declares a variable type that would be used to store given class instance. + * Class instance stores all the data from @ref app_usbd_class_inst_t and overlaid data for specified class. + * + * The structure of interface configuration data: + * @code + * ( + * (iface1_nr, (ep1, ep2, ep3)), + (iface2_nr), + (iface3_nr, (ep4)) + * ) + * @endcode + * + * @param type_name The name of the instance without _t postfix. + * @param interfaces_configs List of interface configurations like explained above. + * @param class_config_dec Result of the macro + * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC or + * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE + * + * @return The definition of the structure type that holds all the required data. + * + * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_DATA_TYPEDEF instead. + * + * @note APP_USBD_CLASS_DATA_TYPEDEF has to be called first for the compilation to success. + * + * @sa APP_USBD_CLASS_TYPEDEF + */ +#define APP_USBD_CLASS_INSTANCE_TYPEDEF(type_name, interfaces_configs, class_config_dec) \ + typedef union CONCAT_2(type_name, _u) \ + { \ + app_usbd_class_inst_t base; \ + struct \ + { \ + APP_USBD_CLASS_DATA_TYPE(type_name) * p_data; \ + app_usbd_class_methods_t const * p_class_methods; \ + struct \ + { \ + uint8_t cnt; \ + app_usbd_class_iface_conf_t \ + config[NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs))]; \ + app_usbd_class_ep_conf_t \ + ep[APP_USBD_CLASS_CONF_TOTAL_EP_COUNT(interfaces_configs)]; \ + } iface; \ + class_config_dec \ + } specific; \ + } APP_USBD_CLASS_INSTANCE_TYPE(type_name) + +/** + * @brief Same as @ref APP_USBD_CLASS_INSTANCE_TYPEDEF but for class with EP0 only. + */ +#define APP_USBD_CLASS_INSTANCE_NO_EP_TYPEDEF(type_name, interfaces_configs, class_config_dec) \ + typedef union CONCAT_2(type_name, _u) \ + { \ + app_usbd_class_inst_t base; \ + struct \ + { \ + APP_USBD_CLASS_DATA_TYPE(type_name) * p_data; \ + app_usbd_class_methods_t const * p_class_methods; \ + struct \ + { \ + uint8_t cnt; \ + app_usbd_class_iface_conf_t \ + config[NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs))]; \ + } iface; \ + class_config_dec \ + } specific; \ + } APP_USBD_CLASS_INSTANCE_TYPE(type_name) + +/** + * @brief Writable data structure declaration. + * + * The macro that declares a variable type that would be used to store given class writable data. + * Writable data contains base part of the type @ref app_usbd_class_data_t followed by + * class specific data. + * + * @param type_name The name of the type without _t postfix. + * @param class_data_dec Result of the macro + * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC or + * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE + * + * @return The definition of the structure type that holds all the required writable data. + * + * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_DATA_TYPEDEF instead. + * + * @sa APP_USBD_CLASS_TYPEDEF + */ +#define APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec) \ + typedef struct \ + { \ + app_usbd_class_data_t base; \ + class_data_dec \ + }APP_USBD_CLASS_DATA_TYPE(type_name) + + +/** + * @brief Declare all data types required by the class instance. + * + * Macro that declares data type first and then instance type. + * + * @param type_name The name of the type without _t postfix. + * @param interface_configs List of interface configurations like in @ref APP_USBD_CLASS_INSTANCE_TYPEDEF. + * @param class_config_dec Result of the macro + * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC or + * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE + * @param class_data_dec Result of the macro + * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC or + * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE + * + * @return Declaration of the data type for the instance and instance itself. + * + * @sa APP_USBD_CLASS_DATA_TYPEDEF + * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF + */ +#define APP_USBD_CLASS_TYPEDEF(type_name, interface_configs, class_config_dec, class_data_dec) \ + APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec); \ + APP_USBD_CLASS_INSTANCE_TYPEDEF(type_name, interface_configs, class_config_dec) + +/** + * @brief Same as @ref APP_USBD_CLASS_TYPEDEF but for class with EP0 only. + */ +#define APP_USBD_CLASS_NO_EP_TYPEDEF(type_name, \ + interface_configs, \ + class_config_dec, \ + class_data_dec) \ + APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec); \ + APP_USBD_CLASS_INSTANCE_NO_EP_TYPEDEF(type_name, interface_configs, class_config_dec) + +/** + * @brief Forward declaration of type defined by @ref APP_USBD_CLASS_TYPEDEF + * + * @param type_name The name of the type without _t postfix. + * */ +#define APP_USBD_CLASS_FORWARD(type_name) union CONCAT_2(type_name, _u) + +/** + * @brief Generate the initialization data for. + * + * Macro that generates the initialization data for instance. + * + * @param p_ram_data Pointer to writable instance data structure. + * @param class_methods Class methods. + * @param interfaces_configs Exactly the same interface config data that in @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * @param class_config_part Configuration part. The data should be inside brackets. + * Any data here would be removed from brackets and then put as an initialization + * data for class_part member of instance structure. + * + * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_INST_DEF instead. + */ +#define APP_USBD_CLASS_INSTANCE_INITVAL(p_ram_data, \ + class_methods, \ + interfaces_configs, \ + class_config_part) \ + { \ + .specific = { \ + .p_data = p_ram_data, \ + .p_class_methods = class_methods, \ + .iface = { \ + .cnt = NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs)), \ + .config = { APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(interfaces_configs) }, \ + .ep = { APP_USBD_CLASS_IFACES_EP_EXTRACT(interfaces_configs) } \ + }, \ + BRACKET_EXTRACT(class_config_part) \ + } \ + } + +/** + * @brief Same as @ref APP_USBD_CLASS_INSTANCE_INITVAL but for class with EP0 only. + */ +#define APP_USBD_CLASS_INSTANCE_NO_EP_INITVAL(p_ram_data, \ + class_methods, \ + interfaces_configs, \ + class_config_part) \ + { \ + .specific = { \ + .p_data = p_ram_data, \ + .p_class_methods = class_methods, \ + .iface = { \ + .cnt = NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs)), \ + .config = { APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(interfaces_configs) } \ + }, \ + BRACKET_EXTRACT(class_config_part) \ + } \ + } + +/** + * @brief Define the base class instance. + * + * Macro that defines whole instance variable and fill it with initialization data. + * + * The tricky part is @c class_config_part. + * The configuration data here has to be placed inside brackets. + * Then any type of values can be used depending on the type used in @ref APP_USBD_CLASS_TYPEDEF. + * If instance does not has any specyfic data, use just empty bracket here. + * @code + * APP_USBD_CLASS_TYPEDEF( + * some_base_class, + * CLASS_BASE_CONFIGURATION, + * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, + * APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE + * ); + * APP_USBD_CLASS_INST_DEF( + * some_base_class_inst, + * some_base_class, + * base_class_event_handler, + * CLASS_BASE_CONFIGURATION, + * () // Empty configuration + * ); + * @endcode + * + * If the type of instance configuration is simple type, just provide initialization value: + * @code + * APP_USBD_CLASS_TYPEDEF( + * some_base_class, + * CLASS_BASE_CONFIGURATION, + * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, + * APP_USBD_CLASS_DATA_SPECIFIC_DEC(uint8_t) + * ); + * APP_USBD_CLASS_INST_DEF( + * some_base_class_inst, + * some_base_class, + * base_class_event_handler, + * CLASS_BASE_CONFIGURATION, + * (12) // Example values + * ); + * @endcode + * + * If the type of instance configuration is structure, provide initialization value for the whole structure: + * @code + * typedef structure + * { + * uint32_t p1; + * uint8_t p2; + * }my_config_t; + * + * APP_USBD_CLASS_TYPEDEF( + * some_base_class, + * CLASS_BASE_CONFIGURATION, + * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, + * APP_USBD_CLASS_DATA_SPECIFIC_DEC(my_config_t) + * ); + * APP_USBD_CLASS_INST_DEF( + * some_base_class_inst, + * some_base_class, + * base_class_event_handler, + * CLASS_BASE_CONFIGURATION, + * ({12, 3}) // Example values + * ); + * @endcode + * + * @param instance_name The name of created instance variable. + * It would be constant variable and its type would be app_usbd_class_inst_t. + * @param type_name The name of the variable type. It has to be the same type that was passed to + * @ref APP_USBD_CLASS_TYPEDEF + * @param class_methods Class unified interface. + * @param interfaces_configs The same configuration data that the one passed to @ref APP_USBD_CLASS_TYPEDEF + * @param class_config_part Configuration data to the type that was declared by class_data_dec when calling + * @ref APP_USBD_CLASS_TYPEDEF. + * Configuration data has to be provided in brackets. + * It would be extracted from brackets and placed in initialization part of configuration structure. + * See detailed description of this macro for more informations. + */ +#define APP_USBD_CLASS_INST_DEF(instance_name, \ + type_name, \ + class_methods, \ + interfaces_configs, \ + class_config_part) \ + static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \ + static const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \ + APP_USBD_CLASS_INSTANCE_INITVAL( \ + &CONCAT_2(instance_name, _data), \ + class_methods, \ + interfaces_configs, \ + class_config_part) + + +/** + * @brief Define the base class instance in global scope. + * + * This is the same macro like @ref APP_USBD_CLASS_INST_DEF but it creates the instance + * without static keyword. + * + * @param instance_name See documentation for @ref APP_USBD_CLASS_INST_DEF + * @param type_name See documentation for @ref APP_USBD_CLASS_INST_DEF + * @param class_methods See documentation for @ref APP_USBD_CLASS_INST_DEF + * @param interfaces_configs See documentation for @ref APP_USBD_CLASS_INST_DEF + * @param class_config_part See documentation for @ref APP_USBD_CLASS_INST_DEF + */ +#define APP_USBD_CLASS_INST_GLOBAL_DEF(instance_name, \ + type_name, \ + class_methods, \ + interfaces_configs, \ + class_config_part) \ + static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \ + const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \ + APP_USBD_CLASS_INSTANCE_INITVAL( \ + &CONCAT_2(instance_name, _data), \ + class_methods, \ + interfaces_configs, \ + class_config_part) + +/** + * @brief Same as @ref APP_USBD_CLASS_INST_GLOBAL_DEF but for class with EP0 only. + */ +#define APP_USBD_CLASS_INST_NO_EP_GLOBAL_DEF(instance_name, \ + type_name, \ + class_methods, \ + interfaces_configs, \ + class_config_part) \ + static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \ + const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \ + APP_USBD_CLASS_INSTANCE_NO_EP_INITVAL( \ + &CONCAT_2(instance_name, _data), \ + class_methods, \ + interfaces_configs, \ + class_config_part) +/** + * @brief Access class specific configuration. + * + * Macro that returns class specific configuration. + * + * @param[in] p_inst Instance pointer. + * + * @return A pointer for class specific part of the instance. + * + * @note If macro is used on the instance that has no class specific configuration + * an error would be generated during compilation. + */ +#define APP_USBD_CLASS_GET_SPECIFIC_CONFIG(p_inst) (&((p_inst)->specific.class_part)) + +/** + * @brief Access class specific data. + * + * @param[in] p_inst Instance pointer. + * + * @return A pointer for class specific part of writable data. + * + * @note If macro is used on the instance that has no class specific data + * an error would be generated during compilation. + */ +#define APP_USBD_CLASS_GET_SPECIFIC_DATA(p_inst) (&(((p_inst)->specific.p_data)->class_part)) + +/** + * @brief Macro to get base instance from class specific instance. + * + * This macro may be used on class specific instance to get base instance that + * can be processed by base instance access functions. + * Class specific instance can be just casted to class base instance, + * but then we would totally lost type safety. + * + * A little more safe is to use pointer to base member of class instance. + * This would generate an error when used on any variable that has no base member + * and would generate also error if this base member is wrong type. + */ +#define APP_USBD_CLASS_BASE_INSTANCE(p_inst) (&((p_inst)->base)) + +/*lint -emacro(142 438 616 646, APP_USBD_CLASS_DESCRIPTOR_INIT, APP_USBD_CLASS_DESCRIPTOR_BEGIN, APP_USBD_CLASS_DESCRIPTOR_YIELD, APP_USBD_CLASS_DESCRIPTOR_END, APP_USBD_CLASS_DESCRIPTOR_WRITE)*/ + +/** + * @brief Initialize class descriptor. + * + * @param[in] p_ctx Class descriptor context. + */ + +#define APP_USBD_CLASS_DESCRIPTOR_INIT(p_ctx) \ + (p_ctx)->line = 0; + +/** + * @brief Begin class descriptor. + * + * @param[in] p_ctx Class descriptor context. + * @param[in] p_buff Buffer to write into. + * @param[in] max_size Size of the buffer. + */ + +#define APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size) \ + ASSERT((p_ctx) != NULL); \ + app_usbd_class_descriptor_state_t this_descriptor_feed; \ + this_descriptor_feed.p_buffer = (p_buff); \ + this_descriptor_feed.current_size = 0; \ + this_descriptor_feed.maximum_size = (max_size); \ + this_descriptor_feed.p_context = (p_ctx); \ + switch ((this_descriptor_feed.p_context)->line) \ + { \ + case 0: \ + ; + +/** + * @brief Yield class descriptor + * + */ + +#define APP_USBD_CLASS_DESCRIPTOR_YIELD() \ +do \ +{ \ + (this_descriptor_feed.p_context)->line = __LINE__; \ + return true; \ + case __LINE__: \ + ; \ +} while (0) + +/*lint -emacro(438 527, APP_USBD_CLASS_DESCRIPTOR_END)*/ + +/** + * @brief End class descriptor. + * + * This function has to be called at the end of class descriptor feeder function. + * No other operations in feeder function can be done after calling it. + */ + +#define APP_USBD_CLASS_DESCRIPTOR_END() \ + APP_USBD_CLASS_DESCRIPTOR_YIELD(); \ + } \ + (this_descriptor_feed.p_context)->line = 0; \ + return false; + + +/** + * @brief Write descriptor using protothreads. + * + * This function writes one byte to the buffer with offset. If buffer is full + * it yields. + * + * It is used by the class descriptor feeders internally. + * + * @ref APP_USBD_CLASS_DESCRIPTOR_BEGIN has to be called before using this function. + * @ref APP_USBD_CLASS_DESCRIPTOR_END has to be called after last use of this function. + * + * @param data Byte to be written to buffer. + */ +#define APP_USBD_CLASS_DESCRIPTOR_WRITE(data) \ +do \ +{ \ + (this_descriptor_feed.p_context)->data_buffer = (data); \ + if (this_descriptor_feed.current_size >= this_descriptor_feed.maximum_size) \ + { \ + APP_USBD_CLASS_DESCRIPTOR_YIELD(); \ + } \ + if(this_descriptor_feed.p_buffer != NULL) \ + { \ + *(this_descriptor_feed.p_buffer + this_descriptor_feed.current_size) = \ + (this_descriptor_feed.p_context)->data_buffer; \ + } \ + this_descriptor_feed.current_size++; \ +} while(0); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CLASS_BASE_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.c b/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.c index 0abcc17e3..8988679d5 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.c +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.c @@ -1,1235 +1,1235 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(APP_USBD) - -#include "app_usbd_core.h" -#include "app_usbd.h" -#include "app_usbd_request.h" -#include "app_usbd_string_desc.h" -#include "nrf.h" -#include "nrf_atomic.h" -#include "app_util_platform.h" -#include "app_usbd.h" -#include "app_usbd_class_base.h" - -#define NRF_LOG_MODULE_NAME app_usbd_core - -#if APP_USBD_CONFIG_LOG_ENABLED -#define NRF_LOG_LEVEL APP_USBD_CONFIG_LOG_LEVEL -#define NRF_LOG_INFO_COLOR APP_USBD_CONFIG_INFO_COLOR -#define NRF_LOG_DEBUG_COLOR APP_USBD_CONFIG_DEBUG_COLOR -#else //APP_USBD_CONFIG_LOG_ENABLED -#define NRF_LOG_LEVEL 0 -#endif //APP_USBD_CONFIG_LOG_ENABLED -#include "nrf_log.h" -NRF_LOG_MODULE_REGISTER(); - -/* Test if VID was configured */ -#ifndef APP_USBD_VID -#error APP_USBD_VID not properly defined. -#endif - - -/* Device version checking */ -#if defined(APP_USBD_DEVICE_VER_MAJOR) && defined(APP_USBD_DEVICE_VER_MINOR) - #if ((APP_USBD_DEVICE_VER_MAJOR)) > 99 || ((APP_USBD_DEVICE_VER_MINOR) > 99) - #error Major and minor device version value have to be limited to 99. - #endif -#else - #error The definition of a pair APP_USBD_DEVICE_VER_MAJOR and APP_USBD_DEVICE_VER_MINOR required. -#endif - -/** - * @internal - * @defgroup app_usbd_core_internals USB Device high level library core module internals - * @ingroup app_usbd_core - * - * Internal variables, auxiliary macros and functions of USBD high level core module. - * @{ - */ - -/** @brief Make USB power value */ -#define APP_USBD_POWER_MAKE(ma) (((ma) + 1) / 2) - -/** - @brief Default device descriptor initializer @ref app_usbd_descriptor_device_t -* */ -#define APP_USBD_CORE_DEVICE_DESCRIPTOR { \ - .bLength = sizeof(app_usbd_descriptor_device_t), /* descriptor size */ \ - .bDescriptorType = APP_USBD_DESCRIPTOR_DEVICE, /* descriptor type */ \ - .bcdUSB = APP_USBD_BCD_VER_MAKE(2,0), /* USB BCD version: 2.0 */ \ - .bDeviceClass = 0, /* device class: 0 - specified by interface */ \ - .bDeviceSubClass = 0, /* device subclass: 0 - specified by interface */ \ - .bDeviceProtocol = 0, /* device protocol: 0 - specified by interface */ \ - .bMaxPacketSize0 = NRF_DRV_USBD_EPSIZE, /* endpoint size: fixed to: NRF_DRV_USBD_EPSIZE*/ \ - .idVendor = APP_USBD_VID, /* Vendor ID*/ \ - .idProduct = APP_USBD_PID, /* Product ID*/ \ - .bcdDevice = APP_USBD_BCD_VER_MAKE( /* Device version BCD */ \ - APP_USBD_DEVICE_VER_MAJOR, \ - APP_USBD_DEVICE_VER_MINOR), \ - .iManufacturer = APP_USBD_STRING_ID_MANUFACTURER, /* String ID: manufacturer */ \ - .iProduct = APP_USBD_STRING_ID_PRODUCT, /* String ID: product */ \ - .iSerialNumber = APP_USBD_STRING_ID_SERIAL, /* String ID: serial */ \ - .bNumConfigurations = 1 /* Fixed value: only one configuration supported*/\ -} - - -#define APP_USBD_CORE_CONFIGURATION_DESCRIPTOR { \ - .bLength = sizeof(app_usbd_descriptor_configuration_t), \ - .bDescriptorType = APP_USBD_DESCRIPTOR_CONFIGURATION, \ - .wTotalLength = 0, /*Calculated dynamically*/ \ - .bNumInterfaces = 0, /*Calculated dynamically*/ \ - .bConfigurationValue = 1, /*Value passed to set configuration*/ \ - .iConfiguration = APP_USBD_STRING_ID_CONFIGURATION, /*Configuration ID*/ \ - .bmAttributes = APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_ALWAYS_SET_MASK | \ - ((APP_USBD_CONFIG_SELF_POWERED) ? \ - APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_SELF_POWERED_MASK \ - : \ - 0), \ - .bMaxPower = APP_USBD_POWER_MAKE(APP_USBD_CONFIG_MAX_POWER), \ -} - -/** - * @brief Device descriptor instance. - * - * @note - * Constant part of the device descriptor. - * Values that must be calculated are updated directly in the buffer - * just before the transmission. - */ -static const app_usbd_descriptor_device_t m_device_dsc = - APP_USBD_CORE_DEVICE_DESCRIPTOR; - -/** - * @brief Configuration descriptor instance. - * - * @note - * Constant part of the device descriptor. - * Values that must be calculated are updated directly in the buffer - * just before the transmission. - */ -static const app_usbd_descriptor_configuration_t m_configuration_dsc = - APP_USBD_CORE_CONFIGURATION_DESCRIPTOR; - -/* Required early declaration of event handler function */ -static ret_code_t app_usbd_core_event_handler(app_usbd_class_inst_t const * const p_inst, - app_usbd_complex_evt_t const * const p_event); - -/** - * @brief Current USB device state. - * - * This variable is updated automatically by core library. - */ -static app_usbd_state_t m_app_usbd_state = APP_USBD_STATE_Disabled; - -/** - * @brief Active device features. - * - * @note Only @ref APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP is supported for device. - */ -static uint8_t m_device_features_state; - -/** - * @brief Remote wake-up pending flag. - */ -static nrf_atomic_flag_t m_rwu_pending; - - -/** - * @brief Core class methods. - * - * Base methods interface for core class. - * This is quite specific class - it would be only connected into endpoint 0. - * Not connected into instances list. - */ -static const app_usbd_class_methods_t m_core_methods = { - .event_handler = app_usbd_core_event_handler, - .feed_descriptors = NULL, -}; - -/** - * @brief Setup transfer buffer. - */ -static uint8_t m_setup_transfer_buff[NRF_DRV_USBD_EPSIZE]; - - -/** - * @brief Handler for outgoing setup data. - * - */ -static app_usbd_core_setup_data_handler_desc_t m_ep0_handler_desc; - -#define APP_USBD_CORE_CLASS_INSTANCE_CONFIG () - - -/*lint -u -save -e26 -e40 -e64 -e123 -e505 -e651*/ - -/** - * @brief Core instance. - * - * Create instance that would be connected into endpoints in USBD library. - */ -APP_USBD_CLASS_INST_GLOBAL_DEF( - app_usbd_core_inst, - app_usbd_core, - &m_core_methods, - APP_USBD_CORE_CLASS_CONFIGURATION, - () ); -/*lint -restore*/ - -/** - * @brief Set the new USB state. - * - * Function changes the internal status of the bus. - * If the bus status is different than the one configured, an event is passed to all - * the instances. - * - * @param state New state to be set. - * - * @sa usbd_core_state_get - */ -static void usbd_core_state_set(app_usbd_state_t state) -{ - if (m_app_usbd_state != state) - { - m_app_usbd_state = state; - if(state != APP_USBD_STATE_Configured) - { - CLR_BIT(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP); - } - static const app_usbd_evt_t evt_data = { - .type = APP_USBD_EVT_STATE_CHANGED - }; - app_usbd_event_execute((app_usbd_internal_evt_t const *)&evt_data); - } -} - -/** - * @brief Get the current USB state - internal function. - * - * This is just a wrapper for @ref app_usbd_core_state_get - * to make symmetrical function to the internal @ref usbd_core_state_set. - * - * @return Current USB state. - * - * @sa usbd_core_state_set - * @sa app_usbd_core_state_get - */ -static inline app_usbd_state_t usbd_core_state_get(void) -{ - return m_app_usbd_state; -} - -/** - * @brief Check current USBD power connection status. - * - */ -static inline bool usbd_core_power_is_detected(void) -{ - return 0 != ( (NRF_POWER->USBREGSTATUS) & POWER_USBREGSTATUS_VBUSDETECT_Msk); -} - -/** - * @brief Clear current EP0 handler. - * - * Function just clears the EP0 handler without calling it. - */ -static inline void usbd_core_ep0_handler_clear(void) -{ - m_ep0_handler_desc.handler = NULL; -} - -/** - * @brief Safely call EP0 handler. - * - * Function calls EP0 handler only if its pointer is non-zero. - * - * @param status Status to send as a handler parameter. - */ -static inline ret_code_t usbd_core_ep0_handler_call_and_clear(nrf_drv_usbd_ep_status_t status) -{ - app_usbd_core_setup_data_handler_t handler = m_ep0_handler_desc.handler; - if (NULL != handler) - { - usbd_core_ep0_handler_clear(); - return handler(status, m_ep0_handler_desc.p_context); - } - - return NRF_ERROR_NULL; -} - -/** - * @brief Check if EP0 handler is configured. - * - * EP0 handler is configured is any instance that has processed SETUP command - * expects some incoming / outgoing data. - * - * EP0 handler should be cleared automatically just before it is called - * (see @ref usbd_core_ep0_handler_call_and_clear). - * If instance requires more data - it has to setup EP0 handler once more time - * (see @ref app_usbd_core_setup_data_handler_set). - * - * This function adds small layer of abstraction for checking if EP0 handler - * is already configured. - * - * @retval true EP0 handler is set. - * @retval false EP0 handler is cleared. - */ -static inline bool usb_core_ep0_handler_check(void) -{ - return (NULL != m_ep0_handler_desc.handler); -} - -/** - * @brief Empty data handler. - * - * Data handler used only to mark that there is requested data during SETUP. - * - * @return Always NRF_SUCCESS - * @sa setup_empty_data_handler_desc - */ -static ret_code_t setup_data_handler_empty(nrf_drv_usbd_ep_status_t status, void * p_contex) -{ - UNUSED_PARAMETER(status); - UNUSED_PARAMETER(p_contex); - return NRF_SUCCESS; -} - -/** - * @brief - * - * Empty EP0 transfer transfer handler. - */ -static app_usbd_core_setup_data_handler_desc_t const m_setup_data_handler_empty_desc = -{ - .handler = setup_data_handler_empty, - .p_context = NULL -}; - -/** - * @brief Structure used as a context for descriptor feeder. - * - * Structure with all the data required to process instances to generate descriptor - * data chunk. - */ -typedef struct -{ - app_usbd_class_inst_t const * p_cinst; //!< The class instance that is to be processed next. - const uint8_t * p_desc; //!< Pointer at current descriptor or NULL if finished. - /**< - * If the value passed by @ref p_desc is NULL on transfer function enter it means that ZLP is required. - * Or it is time to finish the transfer (depending on @c total_left). - */ - size_t desc_left; //!< Number of bytes left in the current class descriptor to send - size_t total_left; //!< Number of bytes left that was requested by the host - app_usbd_class_descriptor_ctx_t feed_thread; //!< Class descriptor context -} app_usbd_core_descriptor_conf_feed_data_t; - -/** - * @brief Default data used by the feeder. - * - * - */ -static app_usbd_core_descriptor_conf_feed_data_t m_descriptor_conf_feed_data; - -/** - * @brief Descriptor feeder. - * - * Descriptor feeder is used as an callback function when descriptors are - * transfered and buffer is ready for next data. - * It prepares next chunk of data to be sent. - * - * @param p_next See @ref nrf_drv_usbd_next_transfer_handler_t documentation. - * @param p_context Pointer to @ref app_usbd_core_descriptor_feed_data_t data type. - * @param ep_size The size of the endpoint. - * - * @return See @ref nrf_drv_usbd_next_transfer_handler_t documentation. - */ -static bool usbd_descriptor_conf_feeder( - nrf_drv_usbd_ep_transfer_t * p_next, - void * p_context, - size_t ep_size) -{ - bool continue_req = true; - - app_usbd_core_descriptor_conf_feed_data_t * p_data = p_context; - - - if ((p_data->p_desc == NULL) && (app_usbd_class_next_get(p_data->p_cinst) == NULL) - && (p_data->desc_left == 0)) - { - /* ZLP */ - continue_req = false; - p_next->p_data.tx = NULL; - p_next->size = 0; - } - else - { - ASSERT(ep_size <= NRF_DRV_USBD_FEEDER_BUFFER_SIZE); - uint8_t * p_tx_buff; - size_t size = 0; /* Currently added number of bytes */ - size_t tx_size; /* Number of bytes to send right now */ - bool feeding = false; - - /* Feeder function can use the USBD driver internal buffer */ - p_tx_buff = nrf_drv_usbd_feeder_buffer_get(); - - tx_size = MIN(ep_size, p_data->total_left); - - while (0 != tx_size) - { - size_t to_copy = MIN(tx_size, p_data->desc_left); - - /* First transfer */ - if (p_data->p_desc != NULL) - { - memcpy(p_tx_buff + size, p_data->p_desc, to_copy); - p_data->p_desc = NULL; - } - /* Starting with second transfer */ - else if (0 < p_data->desc_left) - { - UNUSED_RETURN_VALUE(p_data->p_cinst->p_class_methods->feed_descriptors( - &p_data->feed_thread, p_data->p_cinst, - (uint8_t *)p_tx_buff + size, to_copy)); - feeding = true; - } - else - { - ; - } - - p_data->desc_left -= to_copy; - p_data->total_left -= to_copy; - tx_size -= to_copy; - size += to_copy; - - /* Switch to next class if no descriptor left and first feeding was done */ - if(p_data->desc_left == 0 && feeding) - { - p_data->p_cinst = app_usbd_class_next_get(p_data->p_cinst); - } - - if (0 == p_data->total_left) - { - continue_req = false; - } - else if (0 == p_data->desc_left) - { - if (NULL == p_data->p_cinst) - { - p_data->p_desc = NULL; - /* No more data - check if ZLP is required */ - if (size > 0) - { - if (size < ep_size) - { - continue_req = false; - } - } - break; - } - else - { - /* New class - count descriptor size and initialize feeding thread */ - app_usbd_class_descriptor_ctx_t desiz; - APP_USBD_CLASS_DESCRIPTOR_INIT(&desiz); - while(p_data->p_cinst->p_class_methods->feed_descriptors( - &desiz, p_data->p_cinst, NULL, sizeof(uint8_t))) - { - p_data->desc_left++; - } - APP_USBD_CLASS_DESCRIPTOR_INIT(&p_data->feed_thread); - } - } - else - { - /* Nothing to do */ - } - } - p_next->p_data.tx = p_tx_buff; - p_next->size = size; - } - return continue_req; -} - -/** - * @brief Standard endpoint request handle. - * - * @param[in] p_setup_ev Setup event. - * - * @return Standard error code. - */ -static ret_code_t setup_endpoint_req_std(app_usbd_setup_evt_t const * p_setup_ev) -{ - if (APP_USBD_SETUP_REQTYPE_STD != app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) - { - return NRF_ERROR_NOT_SUPPORTED; - } - - nrf_drv_usbd_ep_t ep_addr = (nrf_drv_usbd_ep_t)(p_setup_ev->setup.wIndex.lb); - app_usbd_state_t usb_state = usbd_core_state_get(); - - switch (p_setup_ev->setup.bmRequest) - { - case APP_USBD_SETUP_STDREQ_GET_STATUS: - { - if ((usb_state == APP_USBD_STATE_Configured) || (NRF_USBD_EP_NR_GET(ep_addr) == 0)) - { - size_t tx_size; - uint16_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size); - - p_tx_buff[0] = nrf_drv_usbd_ep_stall_check(ep_addr) ? 1 : 0; - return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint16_t)); - } - else - { - return NRF_ERROR_INVALID_STATE; - } - } - case APP_USBD_SETUP_STDREQ_SET_FEATURE: - { - if ((!NRF_USBD_EPISO_CHECK(ep_addr)) && - (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT)) - { - if ((usb_state == APP_USBD_STATE_Configured) || (NRF_USBD_EP_NR_GET(ep_addr) == 0)) - { - nrf_drv_usbd_ep_stall(ep_addr); - return NRF_SUCCESS; - } - else - { - return NRF_ERROR_INVALID_STATE; - } - } - break; - } - case APP_USBD_SETUP_STDREQ_CLEAR_FEATURE: - { - if ((!NRF_USBD_EPISO_CHECK(ep_addr)) && - (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT)) - { - if ((usb_state == APP_USBD_STATE_Configured) || (NRF_USBD_EP_NR_GET(ep_addr) == 0)) - { - nrf_drv_usbd_ep_dtoggle_clear(ep_addr); - nrf_drv_usbd_ep_stall_clear(ep_addr); - return NRF_SUCCESS; - } - else - { - return NRF_ERROR_INVALID_STATE; - } - } - break; - } - default: - break; - } - return NRF_ERROR_NOT_SUPPORTED; -} - -/** - * @brief Standard interface request handle. - * - * @param[in,out] p_class_inst Class instance that holds selected interface. - * @param[in] iface_idx Index of the interface in class structure. - * @param[in] p_event Event structure to be processed. - * - * @return Operation status. - */ -static ret_code_t setup_interface_req_std_handle( - app_usbd_class_inst_t const * const p_class_inst, - uint8_t iface_idx, - app_usbd_setup_evt_t const * p_setup_ev) -{ - if (APP_USBD_SETUP_REQTYPE_STD != app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) - { - return NRF_ERROR_NOT_SUPPORTED; - } - - app_usbd_state_t usb_state = usbd_core_state_get(); - - if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN) - { - switch (p_setup_ev->setup.bmRequest) - { - case APP_USBD_SETUP_STDREQ_GET_STATUS: - { - if (!(usb_state == APP_USBD_STATE_Configured)) - { - return NRF_ERROR_INVALID_STATE; - } - size_t tx_size; - uint16_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size); - p_tx_buff[0] = 0; - return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint16_t)); - } - case APP_USBD_SETUP_STDREQ_GET_INTERFACE: - { - if (!(usb_state == APP_USBD_STATE_Configured)) - { - return NRF_ERROR_INVALID_STATE; - } - size_t tx_size; - uint8_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size); - p_tx_buff[0] = app_usbd_iface_selection_get(p_class_inst, iface_idx); - return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint8_t)); - } - } - } - else /* APP_USBD_SETUP_REQDIR_OUT */ - { - switch (p_setup_ev->setup.bmRequest) - { - case APP_USBD_SETUP_STDREQ_SET_INTERFACE: - { - if (!(usb_state == APP_USBD_STATE_Configured)) - { - return NRF_ERROR_INVALID_STATE; - } - - if(p_setup_ev->setup.wValue.w > UINT8_MAX) - { - return NRF_ERROR_INVALID_PARAM; - } - uint8_t alt = p_setup_ev->setup.wValue.lb; - return app_usbd_iface_select(p_class_inst, iface_idx, alt); - } - default: - break; - } - } - return NRF_ERROR_NOT_SUPPORTED; -} - -/** - * @brief - * - * Descriptors feeder handle structure. - */ -static const nrf_drv_usbd_handler_desc_t usbd_descriptor_feeder_desc = -{ - .handler = { .feeder = usbd_descriptor_conf_feeder }, - .p_context = &m_descriptor_conf_feed_data -}; - -static ret_code_t setup_device_req_get_status( - app_usbd_class_inst_t const * const p_inst, - app_usbd_setup_evt_t const * const p_setup_ev) -{ - size_t max_size; - uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size); - ASSERT(sizeof(uint16_t) <= max_size); - - memset(p_trans_buff, 0, sizeof(uint16_t)); - if (m_configuration_dsc.bmAttributes & - APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_SELF_POWERED_MASK) - { - SET_BIT(p_trans_buff[0], 0); - } - if (IS_SET(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP)) - { - SET_BIT(p_trans_buff[0], 1); - } - return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_trans_buff, sizeof(uint16_t)); -} - -static ret_code_t setup_device_req_get_descriptor(app_usbd_class_inst_t const * const p_inst, - app_usbd_setup_evt_t const * const p_setup_ev) -{ - switch (p_setup_ev->setup.wValue.hb) - { - case APP_USBD_DESCRIPTOR_DEVICE: - { - return app_usbd_core_setup_rsp(&(p_setup_ev->setup), - &m_device_dsc, - sizeof(m_device_dsc)); - } - case APP_USBD_DESCRIPTOR_CONFIGURATION: - { - /* The size equals the size of configuration descriptor and all classes descriptors */ - const size_t size = MIN( - sizeof(app_usbd_descriptor_configuration_t), - p_setup_ev->setup.wLength.w); - size_t total_length = sizeof(app_usbd_descriptor_configuration_t); - uint8_t iface_count = 0; - - /* Iterate over all registered classes count descriptors and total size */ - app_usbd_class_inst_t const * p_class; - for (p_class = app_usbd_class_first_get(); p_class != NULL; - p_class = app_usbd_class_next_get(p_class)) - { - ASSERT(NULL != (p_class->p_class_methods)); - ASSERT(NULL != (p_class->p_class_methods->feed_descriptors)); - size_t dsc_size = 0; - app_usbd_class_descriptor_ctx_t siz_desc; - APP_USBD_CLASS_DESCRIPTOR_INIT(&siz_desc); - while(p_class->p_class_methods->feed_descriptors(&siz_desc, - p_class, - NULL, - sizeof(uint8_t)) - ) - { - dsc_size++; - } - total_length += dsc_size; - iface_count += app_usbd_class_iface_count_get(p_class); - } - - /* Access transmission buffer */ - size_t max_size; - app_usbd_descriptor_configuration_t * p_trans_buff = - app_usbd_core_setup_transfer_buff_get(&max_size); - /* Copy the configuration descriptor and update the fields that require it */ - ASSERT(size <= max_size); - memcpy(p_trans_buff, &m_configuration_dsc, size); - - p_trans_buff->bNumInterfaces = iface_count; - p_trans_buff->wTotalLength = total_length; - if (app_usbd_class_rwu_enabled_check()) - { - p_trans_buff->bmAttributes |= - APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_REMOTE_WAKEUP_MASK; - } - - - m_descriptor_conf_feed_data.p_cinst = app_usbd_class_first_get(); - m_descriptor_conf_feed_data.p_desc = (void *)p_trans_buff; - m_descriptor_conf_feed_data.desc_left = size; - m_descriptor_conf_feed_data.total_left = p_setup_ev->setup.wLength.w; - - /* Start first transfer */ - ret_code_t ret; - CRITICAL_REGION_ENTER(); - - ret = app_usbd_ep_handled_transfer( - NRF_DRV_USBD_EPIN0, - &usbd_descriptor_feeder_desc); - - if (NRF_SUCCESS == ret) - { - ret = app_usbd_core_setup_data_handler_set( - NRF_DRV_USBD_EPIN0, - &m_setup_data_handler_empty_desc); - } - CRITICAL_REGION_EXIT(); - - return ret; - } - case APP_USBD_DESCRIPTOR_STRING: - { - app_usbd_string_desc_idx_t id = - (app_usbd_string_desc_idx_t)(p_setup_ev->setup.wValue.lb); - uint16_t langid = p_setup_ev->setup.wIndex.w; - uint16_t const * p_string_dsc = app_usbd_string_desc_get(id, langid); - if (p_string_dsc == NULL) - { - return NRF_ERROR_NOT_SUPPORTED; - } - - return app_usbd_core_setup_rsp( - &p_setup_ev->setup, - p_string_dsc, - app_usbd_string_desc_length(p_string_dsc)); - } - default: - break; - } - - - return NRF_ERROR_NOT_SUPPORTED; -} - -static ret_code_t setup_device_req_get_configuration( - app_usbd_class_inst_t const * const p_inst, - app_usbd_setup_evt_t const * const p_setup_ev) -{ - size_t max_size; - uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size); - app_usbd_state_t usb_state = usbd_core_state_get(); - if (usb_state == APP_USBD_STATE_Configured) - { - p_trans_buff[0] = 1; - } - else if (usb_state == APP_USBD_STATE_Addressed) - { - p_trans_buff[0] = 0; - } - else - { - return NRF_ERROR_NOT_SUPPORTED; - } - - return app_usbd_core_setup_rsp(&p_setup_ev->setup, p_trans_buff, sizeof(p_trans_buff[0])); -} - -static ret_code_t setup_device_req_set_configuration( - app_usbd_class_inst_t const * const p_inst, - app_usbd_setup_evt_t const * const p_setup_ev) -{ - app_usbd_state_t usb_state = usbd_core_state_get(); - if (!((usb_state == APP_USBD_STATE_Configured) || - (usb_state == APP_USBD_STATE_Addressed))) - { - return NRF_ERROR_INVALID_STATE; - } - - if (p_setup_ev->setup.wValue.lb == 0) - { - app_usbd_all_iface_deselect(); - usbd_core_state_set(APP_USBD_STATE_Addressed); - } - else if (p_setup_ev->setup.wValue.lb == 1) - { - /*Clear all bulk/interrupt endpoint status and set toggle to DATA0*/ - app_usbd_all_iface_select_0(); - usbd_core_state_set(APP_USBD_STATE_Configured); - } - else - { - /*In this driver only one configuration is supported.*/ - return NRF_ERROR_INVALID_PARAM; - } - - return NRF_SUCCESS; -} - -/** - * @brief Internal SETUP event handler. - * @param[in] p_inst Instance of the class. - * @param[in] p_setup_ev Setup request. - * @return Standard error code. - * @retval NRF_SUCCESS Request handled correctly. - * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported. - */ -static ret_code_t setup_device_req_std_handler(app_usbd_class_inst_t const * const p_inst, - app_usbd_setup_evt_t const * const p_setup_ev) -{ - ASSERT(p_inst != NULL); - ASSERT(p_setup_ev != NULL); - - if (APP_USBD_SETUP_REQTYPE_STD != app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) - { - return NRF_ERROR_NOT_SUPPORTED; - } - - if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN) - { - switch (p_setup_ev->setup.bmRequest) - { - case APP_USBD_SETUP_STDREQ_GET_STATUS: - { - return setup_device_req_get_status(p_inst, p_setup_ev); - } - case APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR: - { - return setup_device_req_get_descriptor(p_inst, p_setup_ev); - } - case APP_USBD_SETUP_STDREQ_GET_CONFIGURATION: - { - return setup_device_req_get_configuration(p_inst, p_setup_ev); - } - default: - /*Not supported*/ - break; - } - return NRF_ERROR_NOT_SUPPORTED; - } - else /* APP_USBD_SETUP_REQDIR_OUT */ - { - switch (p_setup_ev->setup.bmRequest) - { - case APP_USBD_SETUP_STDREQ_SET_ADDRESS: - { - ASSERT(0); /* should never reach this point */ - break; - } - case APP_USBD_SETUP_STDREQ_SET_FEATURE: - { - if (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP) - { - if (!app_usbd_class_rwu_enabled_check()) - { - return NRF_ERROR_FORBIDDEN; - } - SET_BIT(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP); - return NRF_SUCCESS; - } - break; - } - case APP_USBD_SETUP_STDREQ_CLEAR_FEATURE: - { - if (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP) - { - if (!app_usbd_class_rwu_enabled_check()) - { - return NRF_ERROR_FORBIDDEN; - } - CLR_BIT(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP); - return NRF_SUCCESS; - } - break; - } - case APP_USBD_SETUP_STDREQ_SET_CONFIGURATION: - { - return setup_device_req_set_configuration(p_inst, p_setup_ev); - } - case APP_USBD_SETUP_STDREQ_SET_DESCRIPTOR: - { - /*Not supported yet.*/ - break; - } - default: - /*Not supported*/ - break; - } - return NRF_ERROR_NOT_SUPPORTED; - } -} - -/** - * @brief Process SETUP command. - * - * Auxiliary function for SETUP command processing. - */ -static inline ret_code_t app_usbd_core_setup_req_handler(app_usbd_class_inst_t const * const p_inst) -{ - app_usbd_setup_evt_t setup_ev; - ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; /* Final result of request processing function */ - - setup_ev.type = APP_USBD_EVT_DRV_SETUP; - nrf_drv_usbd_setup_get((nrf_drv_usbd_setup_t *)&(setup_ev.setup)); - - NRF_LOG_DEBUG("SETUP: t: 0x%.2x r: 0x%.2x", - setup_ev.setup.bmRequestType, - setup_ev.setup.bmRequest); - if (usb_core_ep0_handler_check()) - { - NRF_LOG_WARNING("Previous setup not finished!"); - } - /* Clear EP0 handler if there is anything in progress */ - usbd_core_ep0_handler_clear(); - - switch (app_usbd_setup_req_rec(setup_ev.setup.bmRequestType)) - { - case APP_USBD_SETUP_REQREC_DEVICE: - { - /* Endpoint 0 has core instance (that process device requests) connected */ - ret = setup_device_req_std_handler(p_inst, &setup_ev); - if (ret == NRF_ERROR_NOT_SUPPORTED) - { - ret = app_usbd_all_until_served_call((app_usbd_complex_evt_t const *)&setup_ev); - } - break; - } - case APP_USBD_SETUP_REQREC_INTERFACE: - { - uint8_t const iface_number = setup_ev.setup.wIndex.lb; - uint8_t iface_idx; - app_usbd_class_inst_t const * p_inst_found = app_usbd_iface_find( - iface_number, - &iface_idx); - if (p_inst_found == NULL) - { - ret = NRF_ERROR_INVALID_ADDR; - } - else - { - ret = app_usbd_iface_call( - p_inst_found, iface_idx, - (app_usbd_complex_evt_t const *)&setup_ev); - if (ret == NRF_ERROR_NOT_SUPPORTED) - { - ret = setup_interface_req_std_handle(p_inst_found, iface_idx, &setup_ev); - } - } - break; - } - case APP_USBD_SETUP_REQREC_ENDPOINT: - { - ret = NRF_ERROR_NOT_SUPPORTED; - nrf_drv_usbd_ep_t ep = (nrf_drv_usbd_ep_t)setup_ev.setup.wIndex.lb; - if ((NRF_USBD_EP_NR_GET(ep) != 0)) /* For EP0 we would call this function again! */ - { - ret = app_usbd_ep_call(ep, (app_usbd_complex_evt_t const *)&setup_ev); - } - if (ret == NRF_ERROR_NOT_SUPPORTED) - { - ret = setup_endpoint_req_std(&setup_ev); - } - break; - } - case APP_USBD_SETUP_REQREC_OTHER: - { - /* Try to process via every instance */ - ret = app_usbd_all_until_served_call((app_usbd_complex_evt_t const *)&setup_ev); - break; - } - default: - break; - } - - /* Processing result */ - if (ret == NRF_SUCCESS) - { - if (usb_core_ep0_handler_check()) - { - if (NRF_DRV_USBD_EPOUT0 == nrf_drv_usbd_last_setup_dir_get()) - { - /* Request processed successfully and requires SETUP data */ - nrf_drv_usbd_setup_data_clear(); - } - } - else - { - /* Request processed successfully */ - nrf_drv_usbd_setup_clear(); - } - } - else - { - /* Request finished with error */ - nrf_drv_usbd_setup_stall(); - } - return ret; -} - -/** - * @brief Event handler for core module. - * - * The event handler that would process all events directed to device. - * - */ -static ret_code_t app_usbd_core_event_handler(app_usbd_class_inst_t const * const p_inst, - app_usbd_complex_evt_t const * const p_event) -{ - ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; - switch (p_event->type) - { - case APP_USBD_EVT_DRV_RESET: - { - usbd_core_state_set(APP_USBD_STATE_Default); - break; - } - case APP_USBD_EVT_DRV_SUSPEND: - { - ret = NRF_SUCCESS; - break; - } - case APP_USBD_EVT_DRV_RESUME: - { - if (nrf_atomic_flag_clear_fetch(&m_rwu_pending) != 0) - { - nrf_usbd_task_trigger(NRF_USBD_TASK_NODRIVEDPDM); - } - - ASSERT(usbd_core_state_get() >= APP_USBD_STATE_Unattached); - ret = NRF_SUCCESS; - break; - } - case APP_USBD_EVT_SETUP_SETADDRESS: - { - app_usbd_state_t usb_state = usbd_core_state_get(); - if (usb_state == APP_USBD_STATE_Default) - { - usbd_core_state_set(APP_USBD_STATE_Addressed); - } - break; - } - case APP_USBD_EVT_DRV_SETUP: - { - ret = app_usbd_core_setup_req_handler(p_inst); - break; - } - case APP_USBD_EVT_INST_APPEND: - { - ASSERT(usbd_core_state_get() == APP_USBD_STATE_Disabled); - ret = NRF_SUCCESS; - break; - } - case APP_USBD_EVT_INST_REMOVE: - { - ASSERT(usbd_core_state_get() == APP_USBD_STATE_Unattached); - usbd_core_state_set(APP_USBD_STATE_Disabled); - ret = NRF_SUCCESS; - break; - } - case APP_USBD_EVT_STARTED: - { - if (usbd_core_power_is_detected()) - { - usbd_core_state_set(APP_USBD_STATE_Powered); - } - else - { - usbd_core_state_set(APP_USBD_STATE_Unattached); - } - ret = NRF_SUCCESS; - break; - } - case APP_USBD_EVT_STOPPED: - { - ASSERT(usbd_core_state_get() >= APP_USBD_STATE_Powered); - usbd_core_state_set(APP_USBD_STATE_Unattached); - ret = NRF_SUCCESS; - break; - } - /* Data transfer on endpoint 0 */ - case APP_USBD_EVT_DRV_EPTRANSFER: - { - if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_ABORTED) - { - /* Just ignore aborting */ - break; - } - /* This EPTRANSFER event has to be called only for EP0 */ - ASSERT((p_event->drv_evt.data.eptransfer.ep == NRF_DRV_USBD_EPOUT0) || - (p_event->drv_evt.data.eptransfer.ep == NRF_DRV_USBD_EPIN0)); - ret = usbd_core_ep0_handler_call_and_clear(p_event->drv_evt.data.eptransfer.status); - /* Processing result */ - if (ret == NRF_SUCCESS) - { - if (usb_core_ep0_handler_check()) - { - if (p_event->drv_evt.data.eptransfer.ep == NRF_DRV_USBD_EPOUT0) - { - /* Request processed successfully and requires SETUP data */ - nrf_drv_usbd_setup_data_clear(); - } - } - else - { - if (!nrf_drv_usbd_errata_154()) - { - nrf_drv_usbd_setup_clear(); - } - } - } - else - { - /* Request finished with error */ - nrf_drv_usbd_setup_stall(); - } - break; - } - default: - break; - } - - return ret; -} - -/** @} */ - -void app_usbd_core_ep0_enable(void) -{ - app_usbd_ep_enable(NRF_DRV_USBD_EPOUT0); - app_usbd_ep_enable(NRF_DRV_USBD_EPIN0); -} - -void app_usbd_core_ep0_disable(void) -{ - app_usbd_ep_disable(NRF_DRV_USBD_EPOUT0); - app_usbd_ep_disable(NRF_DRV_USBD_EPIN0); -} - - -ret_code_t app_usbd_core_setup_rsp(app_usbd_setup_t const * p_setup, - void const * p_data, - size_t size) -{ - size_t req_size = p_setup->wLength.w; - size_t tx_size = MIN(req_size, size); - bool zlp_required = (size < req_size) && - (0 == (size % nrf_drv_usbd_ep_max_packet_size_get(NRF_DRV_USBD_EPIN0))); - - NRF_DRV_USBD_TRANSFER_IN_FLAGS( - transfer, - p_data, - tx_size, - zlp_required ? NRF_DRV_USBD_TRANSFER_ZLP_FLAG : 0); - - ret_code_t ret; - CRITICAL_REGION_ENTER(); - ret = app_usbd_ep_transfer(NRF_DRV_USBD_EPIN0, &transfer); - if (NRF_SUCCESS == ret) - { - ret = app_usbd_core_setup_data_handler_set(NRF_DRV_USBD_EPIN0, - &m_setup_data_handler_empty_desc); - } - CRITICAL_REGION_EXIT(); - - return ret; -} - -ret_code_t app_usbd_core_setup_data_handler_set( - nrf_drv_usbd_ep_t ep, - app_usbd_core_setup_data_handler_desc_t const * const p_handler_desc) -{ - if (nrf_drv_usbd_last_setup_dir_get() != ep) - { - return NRF_ERROR_INVALID_ADDR; - } - - m_ep0_handler_desc = *p_handler_desc; - return NRF_SUCCESS; -} - -void * app_usbd_core_setup_transfer_buff_get(size_t * p_size) -{ - if (p_size != NULL) - *p_size = sizeof(m_setup_transfer_buff); - - return m_setup_transfer_buff; -} - -app_usbd_state_t app_usbd_core_state_get(void) -{ - return usbd_core_state_get(); -} - - -bool app_usbd_core_feature_state_get(app_usbd_setup_stdfeature_t feature) -{ - return IS_SET(m_device_features_state, feature) ? true : false; -} - -#endif //NRF_MODULE_ENABLED(APP_USBD) +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_USBD) + +#include "app_usbd_core.h" +#include "app_usbd.h" +#include "app_usbd_request.h" +#include "app_usbd_string_desc.h" +#include "nrf.h" +#include "nrf_atomic.h" +#include "app_util_platform.h" +#include "app_usbd.h" +#include "app_usbd_class_base.h" + +#define NRF_LOG_MODULE_NAME app_usbd_core + +#if APP_USBD_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL APP_USBD_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR APP_USBD_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR APP_USBD_CONFIG_DEBUG_COLOR +#else //APP_USBD_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //APP_USBD_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/* Test if VID was configured */ +#ifndef APP_USBD_VID +#error APP_USBD_VID not properly defined. +#endif + + +/* Device version checking */ +#if defined(APP_USBD_DEVICE_VER_MAJOR) && defined(APP_USBD_DEVICE_VER_MINOR) + #if ((APP_USBD_DEVICE_VER_MAJOR)) > 99 || ((APP_USBD_DEVICE_VER_MINOR) > 99) + #error Major and minor device version value have to be limited to 99. + #endif +#else + #error The definition of a pair APP_USBD_DEVICE_VER_MAJOR and APP_USBD_DEVICE_VER_MINOR required. +#endif + +/** + * @internal + * @defgroup app_usbd_core_internals USB Device high level library core module internals + * @ingroup app_usbd_core + * + * Internal variables, auxiliary macros and functions of USBD high level core module. + * @{ + */ + +/** @brief Make USB power value */ +#define APP_USBD_POWER_MAKE(ma) (((ma) + 1) / 2) + +/** + @brief Default device descriptor initializer @ref app_usbd_descriptor_device_t +* */ +#define APP_USBD_CORE_DEVICE_DESCRIPTOR { \ + .bLength = sizeof(app_usbd_descriptor_device_t), /* descriptor size */ \ + .bDescriptorType = APP_USBD_DESCRIPTOR_DEVICE, /* descriptor type */ \ + .bcdUSB = APP_USBD_BCD_VER_MAKE(2,0), /* USB BCD version: 2.0 */ \ + .bDeviceClass = 0, /* device class: 0 - specified by interface */ \ + .bDeviceSubClass = 0, /* device subclass: 0 - specified by interface */ \ + .bDeviceProtocol = 0, /* device protocol: 0 - specified by interface */ \ + .bMaxPacketSize0 = NRF_DRV_USBD_EPSIZE, /* endpoint size: fixed to: NRF_DRV_USBD_EPSIZE*/ \ + .idVendor = APP_USBD_VID, /* Vendor ID*/ \ + .idProduct = APP_USBD_PID, /* Product ID*/ \ + .bcdDevice = APP_USBD_BCD_VER_MAKE( /* Device version BCD */ \ + APP_USBD_DEVICE_VER_MAJOR, \ + APP_USBD_DEVICE_VER_MINOR), \ + .iManufacturer = APP_USBD_STRING_ID_MANUFACTURER, /* String ID: manufacturer */ \ + .iProduct = APP_USBD_STRING_ID_PRODUCT, /* String ID: product */ \ + .iSerialNumber = APP_USBD_STRING_ID_SERIAL, /* String ID: serial */ \ + .bNumConfigurations = 1 /* Fixed value: only one configuration supported*/\ +} + + +#define APP_USBD_CORE_CONFIGURATION_DESCRIPTOR { \ + .bLength = sizeof(app_usbd_descriptor_configuration_t), \ + .bDescriptorType = APP_USBD_DESCRIPTOR_CONFIGURATION, \ + .wTotalLength = 0, /*Calculated dynamically*/ \ + .bNumInterfaces = 0, /*Calculated dynamically*/ \ + .bConfigurationValue = 1, /*Value passed to set configuration*/ \ + .iConfiguration = APP_USBD_STRING_ID_CONFIGURATION, /*Configuration ID*/ \ + .bmAttributes = APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_ALWAYS_SET_MASK | \ + ((APP_USBD_CONFIG_SELF_POWERED) ? \ + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_SELF_POWERED_MASK \ + : \ + 0), \ + .bMaxPower = APP_USBD_POWER_MAKE(APP_USBD_CONFIG_MAX_POWER), \ +} + +/** + * @brief Device descriptor instance. + * + * @note + * Constant part of the device descriptor. + * Values that must be calculated are updated directly in the buffer + * just before the transmission. + */ +static const app_usbd_descriptor_device_t m_device_dsc = + APP_USBD_CORE_DEVICE_DESCRIPTOR; + +/** + * @brief Configuration descriptor instance. + * + * @note + * Constant part of the device descriptor. + * Values that must be calculated are updated directly in the buffer + * just before the transmission. + */ +static const app_usbd_descriptor_configuration_t m_configuration_dsc = + APP_USBD_CORE_CONFIGURATION_DESCRIPTOR; + +/* Required early declaration of event handler function */ +static ret_code_t app_usbd_core_event_handler(app_usbd_class_inst_t const * const p_inst, + app_usbd_complex_evt_t const * const p_event); + +/** + * @brief Current USB device state. + * + * This variable is updated automatically by core library. + */ +static app_usbd_state_t m_app_usbd_state = APP_USBD_STATE_Disabled; + +/** + * @brief Active device features. + * + * @note Only @ref APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP is supported for device. + */ +static uint8_t m_device_features_state; + +/** + * @brief Remote wake-up pending flag. + */ +static nrf_atomic_flag_t m_rwu_pending; + + +/** + * @brief Core class methods. + * + * Base methods interface for core class. + * This is quite specific class - it would be only connected into endpoint 0. + * Not connected into instances list. + */ +static const app_usbd_class_methods_t m_core_methods = { + .event_handler = app_usbd_core_event_handler, + .feed_descriptors = NULL, +}; + +/** + * @brief Setup transfer buffer. + */ +static uint8_t m_setup_transfer_buff[NRF_DRV_USBD_EPSIZE]; + + +/** + * @brief Handler for outgoing setup data. + * + */ +static app_usbd_core_setup_data_handler_desc_t m_ep0_handler_desc; + +#define APP_USBD_CORE_CLASS_INSTANCE_CONFIG () + + +/*lint -u -save -e26 -e40 -e64 -e123 -e505 -e651*/ + +/** + * @brief Core instance. + * + * Create instance that would be connected into endpoints in USBD library. + */ +APP_USBD_CLASS_INST_GLOBAL_DEF( + app_usbd_core_inst, + app_usbd_core, + &m_core_methods, + APP_USBD_CORE_CLASS_CONFIGURATION, + () ); +/*lint -restore*/ + +/** + * @brief Set the new USB state. + * + * Function changes the internal status of the bus. + * If the bus status is different than the one configured, an event is passed to all + * the instances. + * + * @param state New state to be set. + * + * @sa usbd_core_state_get + */ +static void usbd_core_state_set(app_usbd_state_t state) +{ + if (m_app_usbd_state != state) + { + m_app_usbd_state = state; + if(state != APP_USBD_STATE_Configured) + { + CLR_BIT(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP); + } + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_STATE_CHANGED + }; + app_usbd_event_execute((app_usbd_internal_evt_t const *)&evt_data); + } +} + +/** + * @brief Get the current USB state - internal function. + * + * This is just a wrapper for @ref app_usbd_core_state_get + * to make symmetrical function to the internal @ref usbd_core_state_set. + * + * @return Current USB state. + * + * @sa usbd_core_state_set + * @sa app_usbd_core_state_get + */ +static inline app_usbd_state_t usbd_core_state_get(void) +{ + return m_app_usbd_state; +} + +/** + * @brief Check current USBD power connection status. + * + */ +static inline bool usbd_core_power_is_detected(void) +{ + return 0 != ( (NRF_POWER->USBREGSTATUS) & POWER_USBREGSTATUS_VBUSDETECT_Msk); +} + +/** + * @brief Clear current EP0 handler. + * + * Function just clears the EP0 handler without calling it. + */ +static inline void usbd_core_ep0_handler_clear(void) +{ + m_ep0_handler_desc.handler = NULL; +} + +/** + * @brief Safely call EP0 handler. + * + * Function calls EP0 handler only if its pointer is non-zero. + * + * @param status Status to send as a handler parameter. + */ +static inline ret_code_t usbd_core_ep0_handler_call_and_clear(nrf_drv_usbd_ep_status_t status) +{ + app_usbd_core_setup_data_handler_t handler = m_ep0_handler_desc.handler; + if (NULL != handler) + { + usbd_core_ep0_handler_clear(); + return handler(status, m_ep0_handler_desc.p_context); + } + + return NRF_ERROR_NULL; +} + +/** + * @brief Check if EP0 handler is configured. + * + * EP0 handler is configured is any instance that has processed SETUP command + * expects some incoming / outgoing data. + * + * EP0 handler should be cleared automatically just before it is called + * (see @ref usbd_core_ep0_handler_call_and_clear). + * If instance requires more data - it has to setup EP0 handler once more time + * (see @ref app_usbd_core_setup_data_handler_set). + * + * This function adds small layer of abstraction for checking if EP0 handler + * is already configured. + * + * @retval true EP0 handler is set. + * @retval false EP0 handler is cleared. + */ +static inline bool usb_core_ep0_handler_check(void) +{ + return (NULL != m_ep0_handler_desc.handler); +} + +/** + * @brief Empty data handler. + * + * Data handler used only to mark that there is requested data during SETUP. + * + * @return Always NRF_SUCCESS + * @sa setup_empty_data_handler_desc + */ +static ret_code_t setup_data_handler_empty(nrf_drv_usbd_ep_status_t status, void * p_contex) +{ + UNUSED_PARAMETER(status); + UNUSED_PARAMETER(p_contex); + return NRF_SUCCESS; +} + +/** + * @brief + * + * Empty EP0 transfer transfer handler. + */ +static app_usbd_core_setup_data_handler_desc_t const m_setup_data_handler_empty_desc = +{ + .handler = setup_data_handler_empty, + .p_context = NULL +}; + +/** + * @brief Structure used as a context for descriptor feeder. + * + * Structure with all the data required to process instances to generate descriptor + * data chunk. + */ +typedef struct +{ + app_usbd_class_inst_t const * p_cinst; //!< The class instance that is to be processed next. + const uint8_t * p_desc; //!< Pointer at current descriptor or NULL if finished. + /**< + * If the value passed by @ref p_desc is NULL on transfer function enter it means that ZLP is required. + * Or it is time to finish the transfer (depending on @c total_left). + */ + size_t desc_left; //!< Number of bytes left in the current class descriptor to send + size_t total_left; //!< Number of bytes left that was requested by the host + app_usbd_class_descriptor_ctx_t feed_thread; //!< Class descriptor context +} app_usbd_core_descriptor_conf_feed_data_t; + +/** + * @brief Default data used by the feeder. + * + * + */ +static app_usbd_core_descriptor_conf_feed_data_t m_descriptor_conf_feed_data; + +/** + * @brief Descriptor feeder. + * + * Descriptor feeder is used as an callback function when descriptors are + * transfered and buffer is ready for next data. + * It prepares next chunk of data to be sent. + * + * @param p_next See @ref nrf_drv_usbd_next_transfer_handler_t documentation. + * @param p_context Pointer to @ref app_usbd_core_descriptor_feed_data_t data type. + * @param ep_size The size of the endpoint. + * + * @return See @ref nrf_drv_usbd_next_transfer_handler_t documentation. + */ +static bool usbd_descriptor_conf_feeder( + nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size) +{ + bool continue_req = true; + + app_usbd_core_descriptor_conf_feed_data_t * p_data = p_context; + + + if ((p_data->p_desc == NULL) && (app_usbd_class_next_get(p_data->p_cinst) == NULL) + && (p_data->desc_left == 0)) + { + /* ZLP */ + continue_req = false; + p_next->p_data.tx = NULL; + p_next->size = 0; + } + else + { + ASSERT(ep_size <= NRF_DRV_USBD_FEEDER_BUFFER_SIZE); + uint8_t * p_tx_buff; + size_t size = 0; /* Currently added number of bytes */ + size_t tx_size; /* Number of bytes to send right now */ + bool feeding = false; + + /* Feeder function can use the USBD driver internal buffer */ + p_tx_buff = nrf_drv_usbd_feeder_buffer_get(); + + tx_size = MIN(ep_size, p_data->total_left); + + while (0 != tx_size) + { + size_t to_copy = MIN(tx_size, p_data->desc_left); + + /* First transfer */ + if (p_data->p_desc != NULL) + { + memcpy(p_tx_buff + size, p_data->p_desc, to_copy); + p_data->p_desc = NULL; + } + /* Starting with second transfer */ + else if (0 < p_data->desc_left) + { + UNUSED_RETURN_VALUE(p_data->p_cinst->p_class_methods->feed_descriptors( + &p_data->feed_thread, p_data->p_cinst, + (uint8_t *)p_tx_buff + size, to_copy)); + feeding = true; + } + else + { + ; + } + + p_data->desc_left -= to_copy; + p_data->total_left -= to_copy; + tx_size -= to_copy; + size += to_copy; + + /* Switch to next class if no descriptor left and first feeding was done */ + if(p_data->desc_left == 0 && feeding) + { + p_data->p_cinst = app_usbd_class_next_get(p_data->p_cinst); + } + + if (0 == p_data->total_left) + { + continue_req = false; + } + else if (0 == p_data->desc_left) + { + if (NULL == p_data->p_cinst) + { + p_data->p_desc = NULL; + /* No more data - check if ZLP is required */ + if (size > 0) + { + if (size < ep_size) + { + continue_req = false; + } + } + break; + } + else + { + /* New class - count descriptor size and initialize feeding thread */ + app_usbd_class_descriptor_ctx_t desiz; + APP_USBD_CLASS_DESCRIPTOR_INIT(&desiz); + while(p_data->p_cinst->p_class_methods->feed_descriptors( + &desiz, p_data->p_cinst, NULL, sizeof(uint8_t))) + { + p_data->desc_left++; + } + APP_USBD_CLASS_DESCRIPTOR_INIT(&p_data->feed_thread); + } + } + else + { + /* Nothing to do */ + } + } + p_next->p_data.tx = p_tx_buff; + p_next->size = size; + } + return continue_req; +} + +/** + * @brief Standard endpoint request handle. + * + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_endpoint_req_std(app_usbd_setup_evt_t const * p_setup_ev) +{ + if (APP_USBD_SETUP_REQTYPE_STD != app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + nrf_drv_usbd_ep_t ep_addr = (nrf_drv_usbd_ep_t)(p_setup_ev->setup.wIndex.lb); + app_usbd_state_t usb_state = usbd_core_state_get(); + + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_GET_STATUS: + { + if ((usb_state == APP_USBD_STATE_Configured) || (NRF_USBD_EP_NR_GET(ep_addr) == 0)) + { + size_t tx_size; + uint16_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size); + + p_tx_buff[0] = nrf_drv_usbd_ep_stall_check(ep_addr) ? 1 : 0; + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint16_t)); + } + else + { + return NRF_ERROR_INVALID_STATE; + } + } + case APP_USBD_SETUP_STDREQ_SET_FEATURE: + { + if ((!NRF_USBD_EPISO_CHECK(ep_addr)) && + (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT)) + { + if ((usb_state == APP_USBD_STATE_Configured) || (NRF_USBD_EP_NR_GET(ep_addr) == 0)) + { + nrf_drv_usbd_ep_stall(ep_addr); + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_INVALID_STATE; + } + } + break; + } + case APP_USBD_SETUP_STDREQ_CLEAR_FEATURE: + { + if ((!NRF_USBD_EPISO_CHECK(ep_addr)) && + (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT)) + { + if ((usb_state == APP_USBD_STATE_Configured) || (NRF_USBD_EP_NR_GET(ep_addr) == 0)) + { + nrf_drv_usbd_ep_dtoggle_clear(ep_addr); + nrf_drv_usbd_ep_stall_clear(ep_addr); + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_INVALID_STATE; + } + } + break; + } + default: + break; + } + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Standard interface request handle. + * + * @param[in,out] p_class_inst Class instance that holds selected interface. + * @param[in] iface_idx Index of the interface in class structure. + * @param[in] p_event Event structure to be processed. + * + * @return Operation status. + */ +static ret_code_t setup_interface_req_std_handle( + app_usbd_class_inst_t const * const p_class_inst, + uint8_t iface_idx, + app_usbd_setup_evt_t const * p_setup_ev) +{ + if (APP_USBD_SETUP_REQTYPE_STD != app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + app_usbd_state_t usb_state = usbd_core_state_get(); + + if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN) + { + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_GET_STATUS: + { + if (!(usb_state == APP_USBD_STATE_Configured)) + { + return NRF_ERROR_INVALID_STATE; + } + size_t tx_size; + uint16_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size); + p_tx_buff[0] = 0; + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint16_t)); + } + case APP_USBD_SETUP_STDREQ_GET_INTERFACE: + { + if (!(usb_state == APP_USBD_STATE_Configured)) + { + return NRF_ERROR_INVALID_STATE; + } + size_t tx_size; + uint8_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size); + p_tx_buff[0] = app_usbd_iface_selection_get(p_class_inst, iface_idx); + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint8_t)); + } + } + } + else /* APP_USBD_SETUP_REQDIR_OUT */ + { + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_SET_INTERFACE: + { + if (!(usb_state == APP_USBD_STATE_Configured)) + { + return NRF_ERROR_INVALID_STATE; + } + + if(p_setup_ev->setup.wValue.w > UINT8_MAX) + { + return NRF_ERROR_INVALID_PARAM; + } + uint8_t alt = p_setup_ev->setup.wValue.lb; + return app_usbd_iface_select(p_class_inst, iface_idx, alt); + } + default: + break; + } + } + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief + * + * Descriptors feeder handle structure. + */ +static const nrf_drv_usbd_handler_desc_t usbd_descriptor_feeder_desc = +{ + .handler = { .feeder = usbd_descriptor_conf_feeder }, + .p_context = &m_descriptor_conf_feed_data +}; + +static ret_code_t setup_device_req_get_status( + app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + size_t max_size; + uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size); + ASSERT(sizeof(uint16_t) <= max_size); + + memset(p_trans_buff, 0, sizeof(uint16_t)); + if (m_configuration_dsc.bmAttributes & + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_SELF_POWERED_MASK) + { + SET_BIT(p_trans_buff[0], 0); + } + if (IS_SET(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP)) + { + SET_BIT(p_trans_buff[0], 1); + } + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_trans_buff, sizeof(uint16_t)); +} + +static ret_code_t setup_device_req_get_descriptor(app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + switch (p_setup_ev->setup.wValue.hb) + { + case APP_USBD_DESCRIPTOR_DEVICE: + { + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), + &m_device_dsc, + sizeof(m_device_dsc)); + } + case APP_USBD_DESCRIPTOR_CONFIGURATION: + { + /* The size equals the size of configuration descriptor and all classes descriptors */ + const size_t size = MIN( + sizeof(app_usbd_descriptor_configuration_t), + p_setup_ev->setup.wLength.w); + size_t total_length = sizeof(app_usbd_descriptor_configuration_t); + uint8_t iface_count = 0; + + /* Iterate over all registered classes count descriptors and total size */ + app_usbd_class_inst_t const * p_class; + for (p_class = app_usbd_class_first_get(); p_class != NULL; + p_class = app_usbd_class_next_get(p_class)) + { + ASSERT(NULL != (p_class->p_class_methods)); + ASSERT(NULL != (p_class->p_class_methods->feed_descriptors)); + size_t dsc_size = 0; + app_usbd_class_descriptor_ctx_t siz_desc; + APP_USBD_CLASS_DESCRIPTOR_INIT(&siz_desc); + while(p_class->p_class_methods->feed_descriptors(&siz_desc, + p_class, + NULL, + sizeof(uint8_t)) + ) + { + dsc_size++; + } + total_length += dsc_size; + iface_count += app_usbd_class_iface_count_get(p_class); + } + + /* Access transmission buffer */ + size_t max_size; + app_usbd_descriptor_configuration_t * p_trans_buff = + app_usbd_core_setup_transfer_buff_get(&max_size); + /* Copy the configuration descriptor and update the fields that require it */ + ASSERT(size <= max_size); + memcpy(p_trans_buff, &m_configuration_dsc, size); + + p_trans_buff->bNumInterfaces = iface_count; + p_trans_buff->wTotalLength = total_length; + if (app_usbd_class_rwu_enabled_check()) + { + p_trans_buff->bmAttributes |= + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_REMOTE_WAKEUP_MASK; + } + + + m_descriptor_conf_feed_data.p_cinst = app_usbd_class_first_get(); + m_descriptor_conf_feed_data.p_desc = (void *)p_trans_buff; + m_descriptor_conf_feed_data.desc_left = size; + m_descriptor_conf_feed_data.total_left = p_setup_ev->setup.wLength.w; + + /* Start first transfer */ + ret_code_t ret; + CRITICAL_REGION_ENTER(); + + ret = app_usbd_ep_handled_transfer( + NRF_DRV_USBD_EPIN0, + &usbd_descriptor_feeder_desc); + + if (NRF_SUCCESS == ret) + { + ret = app_usbd_core_setup_data_handler_set( + NRF_DRV_USBD_EPIN0, + &m_setup_data_handler_empty_desc); + } + CRITICAL_REGION_EXIT(); + + return ret; + } + case APP_USBD_DESCRIPTOR_STRING: + { + app_usbd_string_desc_idx_t id = + (app_usbd_string_desc_idx_t)(p_setup_ev->setup.wValue.lb); + uint16_t langid = p_setup_ev->setup.wIndex.w; + uint16_t const * p_string_dsc = app_usbd_string_desc_get(id, langid); + if (p_string_dsc == NULL) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + return app_usbd_core_setup_rsp( + &p_setup_ev->setup, + p_string_dsc, + app_usbd_string_desc_length(p_string_dsc)); + } + default: + break; + } + + + return NRF_ERROR_NOT_SUPPORTED; +} + +static ret_code_t setup_device_req_get_configuration( + app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + size_t max_size; + uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size); + app_usbd_state_t usb_state = usbd_core_state_get(); + if (usb_state == APP_USBD_STATE_Configured) + { + p_trans_buff[0] = 1; + } + else if (usb_state == APP_USBD_STATE_Addressed) + { + p_trans_buff[0] = 0; + } + else + { + return NRF_ERROR_NOT_SUPPORTED; + } + + return app_usbd_core_setup_rsp(&p_setup_ev->setup, p_trans_buff, sizeof(p_trans_buff[0])); +} + +static ret_code_t setup_device_req_set_configuration( + app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + app_usbd_state_t usb_state = usbd_core_state_get(); + if (!((usb_state == APP_USBD_STATE_Configured) || + (usb_state == APP_USBD_STATE_Addressed))) + { + return NRF_ERROR_INVALID_STATE; + } + + if (p_setup_ev->setup.wValue.lb == 0) + { + app_usbd_all_iface_deselect(); + usbd_core_state_set(APP_USBD_STATE_Addressed); + } + else if (p_setup_ev->setup.wValue.lb == 1) + { + /*Clear all bulk/interrupt endpoint status and set toggle to DATA0*/ + app_usbd_all_iface_select_0(); + usbd_core_state_set(APP_USBD_STATE_Configured); + } + else + { + /*In this driver only one configuration is supported.*/ + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + +/** + * @brief Internal SETUP event handler. + * @param[in] p_inst Instance of the class. + * @param[in] p_setup_ev Setup request. + * @return Standard error code. + * @retval NRF_SUCCESS Request handled correctly. + * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported. + */ +static ret_code_t setup_device_req_std_handler(app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + ASSERT(p_inst != NULL); + ASSERT(p_setup_ev != NULL); + + if (APP_USBD_SETUP_REQTYPE_STD != app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN) + { + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_GET_STATUS: + { + return setup_device_req_get_status(p_inst, p_setup_ev); + } + case APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR: + { + return setup_device_req_get_descriptor(p_inst, p_setup_ev); + } + case APP_USBD_SETUP_STDREQ_GET_CONFIGURATION: + { + return setup_device_req_get_configuration(p_inst, p_setup_ev); + } + default: + /*Not supported*/ + break; + } + return NRF_ERROR_NOT_SUPPORTED; + } + else /* APP_USBD_SETUP_REQDIR_OUT */ + { + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_SET_ADDRESS: + { + ASSERT(0); /* should never reach this point */ + break; + } + case APP_USBD_SETUP_STDREQ_SET_FEATURE: + { + if (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP) + { + if (!app_usbd_class_rwu_enabled_check()) + { + return NRF_ERROR_FORBIDDEN; + } + SET_BIT(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP); + return NRF_SUCCESS; + } + break; + } + case APP_USBD_SETUP_STDREQ_CLEAR_FEATURE: + { + if (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP) + { + if (!app_usbd_class_rwu_enabled_check()) + { + return NRF_ERROR_FORBIDDEN; + } + CLR_BIT(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP); + return NRF_SUCCESS; + } + break; + } + case APP_USBD_SETUP_STDREQ_SET_CONFIGURATION: + { + return setup_device_req_set_configuration(p_inst, p_setup_ev); + } + case APP_USBD_SETUP_STDREQ_SET_DESCRIPTOR: + { + /*Not supported yet.*/ + break; + } + default: + /*Not supported*/ + break; + } + return NRF_ERROR_NOT_SUPPORTED; + } +} + +/** + * @brief Process SETUP command. + * + * Auxiliary function for SETUP command processing. + */ +static inline ret_code_t app_usbd_core_setup_req_handler(app_usbd_class_inst_t const * const p_inst) +{ + app_usbd_setup_evt_t setup_ev; + ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; /* Final result of request processing function */ + + setup_ev.type = APP_USBD_EVT_DRV_SETUP; + nrf_drv_usbd_setup_get((nrf_drv_usbd_setup_t *)&(setup_ev.setup)); + + NRF_LOG_DEBUG("SETUP: t: 0x%.2x r: 0x%.2x", + setup_ev.setup.bmRequestType, + setup_ev.setup.bmRequest); + if (usb_core_ep0_handler_check()) + { + NRF_LOG_WARNING("Previous setup not finished!"); + } + /* Clear EP0 handler if there is anything in progress */ + usbd_core_ep0_handler_clear(); + + switch (app_usbd_setup_req_rec(setup_ev.setup.bmRequestType)) + { + case APP_USBD_SETUP_REQREC_DEVICE: + { + /* Endpoint 0 has core instance (that process device requests) connected */ + ret = setup_device_req_std_handler(p_inst, &setup_ev); + if (ret == NRF_ERROR_NOT_SUPPORTED) + { + ret = app_usbd_all_until_served_call((app_usbd_complex_evt_t const *)&setup_ev); + } + break; + } + case APP_USBD_SETUP_REQREC_INTERFACE: + { + uint8_t const iface_number = setup_ev.setup.wIndex.lb; + uint8_t iface_idx; + app_usbd_class_inst_t const * p_inst_found = app_usbd_iface_find( + iface_number, + &iface_idx); + if (p_inst_found == NULL) + { + ret = NRF_ERROR_INVALID_ADDR; + } + else + { + ret = app_usbd_iface_call( + p_inst_found, iface_idx, + (app_usbd_complex_evt_t const *)&setup_ev); + if (ret == NRF_ERROR_NOT_SUPPORTED) + { + ret = setup_interface_req_std_handle(p_inst_found, iface_idx, &setup_ev); + } + } + break; + } + case APP_USBD_SETUP_REQREC_ENDPOINT: + { + ret = NRF_ERROR_NOT_SUPPORTED; + nrf_drv_usbd_ep_t ep = (nrf_drv_usbd_ep_t)setup_ev.setup.wIndex.lb; + if ((NRF_USBD_EP_NR_GET(ep) != 0)) /* For EP0 we would call this function again! */ + { + ret = app_usbd_ep_call(ep, (app_usbd_complex_evt_t const *)&setup_ev); + } + if (ret == NRF_ERROR_NOT_SUPPORTED) + { + ret = setup_endpoint_req_std(&setup_ev); + } + break; + } + case APP_USBD_SETUP_REQREC_OTHER: + { + /* Try to process via every instance */ + ret = app_usbd_all_until_served_call((app_usbd_complex_evt_t const *)&setup_ev); + break; + } + default: + break; + } + + /* Processing result */ + if (ret == NRF_SUCCESS) + { + if (usb_core_ep0_handler_check()) + { + if (NRF_DRV_USBD_EPOUT0 == nrf_drv_usbd_last_setup_dir_get()) + { + /* Request processed successfully and requires SETUP data */ + nrf_drv_usbd_setup_data_clear(); + } + } + else + { + /* Request processed successfully */ + nrf_drv_usbd_setup_clear(); + } + } + else + { + /* Request finished with error */ + nrf_drv_usbd_setup_stall(); + } + return ret; +} + +/** + * @brief Event handler for core module. + * + * The event handler that would process all events directed to device. + * + */ +static ret_code_t app_usbd_core_event_handler(app_usbd_class_inst_t const * const p_inst, + app_usbd_complex_evt_t const * const p_event) +{ + ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; + switch (p_event->type) + { + case APP_USBD_EVT_DRV_RESET: + { + usbd_core_state_set(APP_USBD_STATE_Default); + break; + } + case APP_USBD_EVT_DRV_SUSPEND: + { + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_DRV_RESUME: + { + if (nrf_atomic_flag_clear_fetch(&m_rwu_pending) != 0) + { + nrf_usbd_task_trigger(NRF_USBD_TASK_NODRIVEDPDM); + } + + ASSERT(usbd_core_state_get() >= APP_USBD_STATE_Unattached); + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_SETUP_SETADDRESS: + { + app_usbd_state_t usb_state = usbd_core_state_get(); + if (usb_state == APP_USBD_STATE_Default) + { + usbd_core_state_set(APP_USBD_STATE_Addressed); + } + break; + } + case APP_USBD_EVT_DRV_SETUP: + { + ret = app_usbd_core_setup_req_handler(p_inst); + break; + } + case APP_USBD_EVT_INST_APPEND: + { + ASSERT(usbd_core_state_get() == APP_USBD_STATE_Disabled); + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_INST_REMOVE: + { + ASSERT(usbd_core_state_get() == APP_USBD_STATE_Unattached); + usbd_core_state_set(APP_USBD_STATE_Disabled); + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_STARTED: + { + if (usbd_core_power_is_detected()) + { + usbd_core_state_set(APP_USBD_STATE_Powered); + } + else + { + usbd_core_state_set(APP_USBD_STATE_Unattached); + } + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_STOPPED: + { + ASSERT(usbd_core_state_get() >= APP_USBD_STATE_Powered); + usbd_core_state_set(APP_USBD_STATE_Unattached); + ret = NRF_SUCCESS; + break; + } + /* Data transfer on endpoint 0 */ + case APP_USBD_EVT_DRV_EPTRANSFER: + { + if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_ABORTED) + { + /* Just ignore aborting */ + break; + } + /* This EPTRANSFER event has to be called only for EP0 */ + ASSERT((p_event->drv_evt.data.eptransfer.ep == NRF_DRV_USBD_EPOUT0) || + (p_event->drv_evt.data.eptransfer.ep == NRF_DRV_USBD_EPIN0)); + ret = usbd_core_ep0_handler_call_and_clear(p_event->drv_evt.data.eptransfer.status); + /* Processing result */ + if (ret == NRF_SUCCESS) + { + if (usb_core_ep0_handler_check()) + { + if (p_event->drv_evt.data.eptransfer.ep == NRF_DRV_USBD_EPOUT0) + { + /* Request processed successfully and requires SETUP data */ + nrf_drv_usbd_setup_data_clear(); + } + } + else + { + if (!nrf_drv_usbd_errata_154()) + { + nrf_drv_usbd_setup_clear(); + } + } + } + else + { + /* Request finished with error */ + nrf_drv_usbd_setup_stall(); + } + break; + } + default: + break; + } + + return ret; +} + +/** @} */ + +void app_usbd_core_ep0_enable(void) +{ + app_usbd_ep_enable(NRF_DRV_USBD_EPOUT0); + app_usbd_ep_enable(NRF_DRV_USBD_EPIN0); +} + +void app_usbd_core_ep0_disable(void) +{ + app_usbd_ep_disable(NRF_DRV_USBD_EPOUT0); + app_usbd_ep_disable(NRF_DRV_USBD_EPIN0); +} + + +ret_code_t app_usbd_core_setup_rsp(app_usbd_setup_t const * p_setup, + void const * p_data, + size_t size) +{ + size_t req_size = p_setup->wLength.w; + size_t tx_size = MIN(req_size, size); + bool zlp_required = (size < req_size) && + (0 == (size % nrf_drv_usbd_ep_max_packet_size_get(NRF_DRV_USBD_EPIN0))); + + NRF_DRV_USBD_TRANSFER_IN_FLAGS( + transfer, + p_data, + tx_size, + zlp_required ? NRF_DRV_USBD_TRANSFER_ZLP_FLAG : 0); + + ret_code_t ret; + CRITICAL_REGION_ENTER(); + ret = app_usbd_ep_transfer(NRF_DRV_USBD_EPIN0, &transfer); + if (NRF_SUCCESS == ret) + { + ret = app_usbd_core_setup_data_handler_set(NRF_DRV_USBD_EPIN0, + &m_setup_data_handler_empty_desc); + } + CRITICAL_REGION_EXIT(); + + return ret; +} + +ret_code_t app_usbd_core_setup_data_handler_set( + nrf_drv_usbd_ep_t ep, + app_usbd_core_setup_data_handler_desc_t const * const p_handler_desc) +{ + if (nrf_drv_usbd_last_setup_dir_get() != ep) + { + return NRF_ERROR_INVALID_ADDR; + } + + m_ep0_handler_desc = *p_handler_desc; + return NRF_SUCCESS; +} + +void * app_usbd_core_setup_transfer_buff_get(size_t * p_size) +{ + if (p_size != NULL) + *p_size = sizeof(m_setup_transfer_buff); + + return m_setup_transfer_buff; +} + +app_usbd_state_t app_usbd_core_state_get(void) +{ + return usbd_core_state_get(); +} + + +bool app_usbd_core_feature_state_get(app_usbd_setup_stdfeature_t feature) +{ + return IS_SET(m_device_features_state, feature) ? true : false; +} + +#endif //NRF_MODULE_ENABLED(APP_USBD) diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.h index 36b62c2ef..bdbf861dd 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.h +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.h @@ -1,222 +1,222 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef APP_USBD_CORE_H__ -#define APP_USBD_CORE_H__ - -#include - -#include "sdk_common.h" -#include "nrf_drv_usbd.h" -#include "app_usbd_types.h" -#include "app_usbd_class_base.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @defgroup app_usbd_core USB Device high level library core module - * @ingroup app_usbd - * - * @brief @tagAPI52840 Core module that manages current USB state and process device requests. - * @{ - */ - -/** - * @brief Core interface configuration. - * - * Core instance would have 2 endpoints (IN0 and OUT0). - * The interface number does not matter because it is not used. - */ -#define APP_USBD_CORE_CLASS_CONFIGURATION ((0, NRF_DRV_USBD_EPOUT0, NRF_DRV_USBD_EPIN0)) - -/** - * @brief USB Device state. - * - * Possible USB Device states according to specification. - */ -typedef enum -{ - APP_USBD_STATE_Disabled , /**< The whole USBD library is disabled */ - APP_USBD_STATE_Unattached, /**< Device is currently not connected to the host */ - APP_USBD_STATE_Powered , /**< Device is connected to the host but has not been enumerated */ - APP_USBD_STATE_Default , /**< USB Reset condition detected, waiting for the address */ - APP_USBD_STATE_Addressed , /**< Device has been addressed but has not been configured */ - APP_USBD_STATE_Configured, /**< Device is addressed and configured */ -}app_usbd_state_t; - -/** - * @brief EP0 handler function pointer. - * - * Type of the variable that would hold the pointer to the handler for - * endpoint 0 messages processing. - * - * @param p_contex Context variable configured with the transmission request. - */ -typedef ret_code_t (*app_usbd_core_setup_data_handler_t)(nrf_drv_usbd_ep_status_t status, - void * p_context); - -/** - * @brief Variable type used to register EP0 transfer handler. - * - * EP0 messages are processed by core instance. - * Another class can register itself to receive messages from EP0 when requesting - * for Setup data transfer. - */ -typedef struct -{ - app_usbd_core_setup_data_handler_t handler; //!< Event handler to be called when transmission is ready - void * p_context; //!< Context pointer to be send to every called event. -} app_usbd_core_setup_data_handler_desc_t; - -/*lint -save -e10 -e26 -e93 -e123 -e505 */ -/** - * @brief Declare Core instance type. - * - * USBD core instance type definition. - */ -APP_USBD_CLASS_TYPEDEF(app_usbd_core, - APP_USBD_CORE_CLASS_CONFIGURATION, - APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, - APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE); -/*lint -restore*/ - -/** - * @brief Access to core instance. - * - * Function that returns pointer to the USBD core instance. - * - * @return pointer to the core instance. - */ -static inline app_usbd_class_inst_t const * app_usbd_core_instance_access(void) -{ - extern const APP_USBD_CLASS_INSTANCE_TYPE(app_usbd_core) app_usbd_core_inst; - return (app_usbd_class_inst_t const *)&app_usbd_core_inst; -} - -/** - * @brief Enable endpoint 0 - * - * Function enables endpoint OUT0 and IN0. - * This makes the USB respond to SETUP transfers. - */ -void app_usbd_core_ep0_enable(void); - -/** - * @brief Disable endpoint 0 - * - * Function disables endpoint OUT0 and IN0. - * This makes the USB ignore SETUP transfers. - */ -void app_usbd_core_ep0_disable(void); - -/** - * @brief Default simple response to setup command. - * - * This function generates default simple response. - * It sends ZLP when required and on takes care on allowing status stage when - * transfer is finished. - * - * @param p_setup Pointer to original setup message. - * @param p_data Pointer to the response. This has to be globaly aviable data. - * @param size Total size of the answer - The function takes care about - * limiting the size of transfered data to the size required - * by setup command. - */ -ret_code_t app_usbd_core_setup_rsp(app_usbd_setup_t const * p_setup, - void const * p_data, - size_t size); - -/** - * @brief Configure the handler for the nearest setup data endpoint transfer. - * - * This function would be called on incomming setup data. - * The correct place to set the handler for a data is when SETUP command - * was received. - * - * @param ep Endpoint number (only IN0 and OUT0 are supported). - * @param p_handler_desc Descriptor of the handler to be called. - * - * @retval NRF_SUCCESS Successfully configured. - * @retval NRF_ERROR_INVALID_ADDR Last received setup direction does not match - * configured endpoint. - */ -ret_code_t app_usbd_core_setup_data_handler_set( - nrf_drv_usbd_ep_t ep, - app_usbd_core_setup_data_handler_desc_t const * const p_handler_desc); - -/** - * @brief Set up a data transfer buffer. - * - * Returns special internal buffer that can be used in setup transfer. - * @return Internal buffer pointer. - */ -void * app_usbd_core_setup_transfer_buff_get(size_t * p_size); - - -/**@brief Return internal USBD core state. - * - * @return Check @ref app_usbd_state_t to find possible USBD core states. - */ -app_usbd_state_t app_usbd_core_state_get(void); - - -/** - * @brief Check current feature state. - * - * Function checks the state of the selected feature that was configured by the host. - * - * @param feature Feature to check. @ref app_usbd_setup_stdfeature_t - * Only features related to the device should be checked by this function. - * - * @retval true Selected feature is set. - * @retval false Selected feature is cleared. - */ -bool app_usbd_core_feature_state_get(app_usbd_setup_stdfeature_t feature); - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_CORE_H__ */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef APP_USBD_CORE_H__ +#define APP_USBD_CORE_H__ + +#include + +#include "sdk_common.h" +#include "nrf_drv_usbd.h" +#include "app_usbd_types.h" +#include "app_usbd_class_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @defgroup app_usbd_core USB Device high level library core module + * @ingroup app_usbd + * + * @brief @tagAPI52840 Core module that manages current USB state and process device requests. + * @{ + */ + +/** + * @brief Core interface configuration. + * + * Core instance would have 2 endpoints (IN0 and OUT0). + * The interface number does not matter because it is not used. + */ +#define APP_USBD_CORE_CLASS_CONFIGURATION ((0, NRF_DRV_USBD_EPOUT0, NRF_DRV_USBD_EPIN0)) + +/** + * @brief USB Device state. + * + * Possible USB Device states according to specification. + */ +typedef enum +{ + APP_USBD_STATE_Disabled , /**< The whole USBD library is disabled */ + APP_USBD_STATE_Unattached, /**< Device is currently not connected to the host */ + APP_USBD_STATE_Powered , /**< Device is connected to the host but has not been enumerated */ + APP_USBD_STATE_Default , /**< USB Reset condition detected, waiting for the address */ + APP_USBD_STATE_Addressed , /**< Device has been addressed but has not been configured */ + APP_USBD_STATE_Configured, /**< Device is addressed and configured */ +}app_usbd_state_t; + +/** + * @brief EP0 handler function pointer. + * + * Type of the variable that would hold the pointer to the handler for + * endpoint 0 messages processing. + * + * @param p_contex Context variable configured with the transmission request. + */ +typedef ret_code_t (*app_usbd_core_setup_data_handler_t)(nrf_drv_usbd_ep_status_t status, + void * p_context); + +/** + * @brief Variable type used to register EP0 transfer handler. + * + * EP0 messages are processed by core instance. + * Another class can register itself to receive messages from EP0 when requesting + * for Setup data transfer. + */ +typedef struct +{ + app_usbd_core_setup_data_handler_t handler; //!< Event handler to be called when transmission is ready + void * p_context; //!< Context pointer to be send to every called event. +} app_usbd_core_setup_data_handler_desc_t; + +/*lint -save -e10 -e26 -e93 -e123 -e505 */ +/** + * @brief Declare Core instance type. + * + * USBD core instance type definition. + */ +APP_USBD_CLASS_TYPEDEF(app_usbd_core, + APP_USBD_CORE_CLASS_CONFIGURATION, + APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, + APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE); +/*lint -restore*/ + +/** + * @brief Access to core instance. + * + * Function that returns pointer to the USBD core instance. + * + * @return pointer to the core instance. + */ +static inline app_usbd_class_inst_t const * app_usbd_core_instance_access(void) +{ + extern const APP_USBD_CLASS_INSTANCE_TYPE(app_usbd_core) app_usbd_core_inst; + return (app_usbd_class_inst_t const *)&app_usbd_core_inst; +} + +/** + * @brief Enable endpoint 0 + * + * Function enables endpoint OUT0 and IN0. + * This makes the USB respond to SETUP transfers. + */ +void app_usbd_core_ep0_enable(void); + +/** + * @brief Disable endpoint 0 + * + * Function disables endpoint OUT0 and IN0. + * This makes the USB ignore SETUP transfers. + */ +void app_usbd_core_ep0_disable(void); + +/** + * @brief Default simple response to setup command. + * + * This function generates default simple response. + * It sends ZLP when required and on takes care on allowing status stage when + * transfer is finished. + * + * @param p_setup Pointer to original setup message. + * @param p_data Pointer to the response. This has to be globaly aviable data. + * @param size Total size of the answer - The function takes care about + * limiting the size of transfered data to the size required + * by setup command. + */ +ret_code_t app_usbd_core_setup_rsp(app_usbd_setup_t const * p_setup, + void const * p_data, + size_t size); + +/** + * @brief Configure the handler for the nearest setup data endpoint transfer. + * + * This function would be called on incomming setup data. + * The correct place to set the handler for a data is when SETUP command + * was received. + * + * @param ep Endpoint number (only IN0 and OUT0 are supported). + * @param p_handler_desc Descriptor of the handler to be called. + * + * @retval NRF_SUCCESS Successfully configured. + * @retval NRF_ERROR_INVALID_ADDR Last received setup direction does not match + * configured endpoint. + */ +ret_code_t app_usbd_core_setup_data_handler_set( + nrf_drv_usbd_ep_t ep, + app_usbd_core_setup_data_handler_desc_t const * const p_handler_desc); + +/** + * @brief Set up a data transfer buffer. + * + * Returns special internal buffer that can be used in setup transfer. + * @return Internal buffer pointer. + */ +void * app_usbd_core_setup_transfer_buff_get(size_t * p_size); + + +/**@brief Return internal USBD core state. + * + * @return Check @ref app_usbd_state_t to find possible USBD core states. + */ +app_usbd_state_t app_usbd_core_state_get(void); + + +/** + * @brief Check current feature state. + * + * Function checks the state of the selected feature that was configured by the host. + * + * @param feature Feature to check. @ref app_usbd_setup_stdfeature_t + * Only features related to the device should be checked by this function. + * + * @retval true Selected feature is set. + * @retval false Selected feature is cleared. + */ +bool app_usbd_core_feature_state_get(app_usbd_setup_stdfeature_t feature); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CORE_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_descriptor.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_descriptor.h index 5c0d551be..3cffc74e9 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_descriptor.h +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_descriptor.h @@ -1,337 +1,337 @@ -/** - * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef APP_USBD_DESCRIPTOR_H__ -#define APP_USBD_DESCRIPTOR_H__ - -#include "nrf.h" -#include "nrf_drv_usbd.h" -#include "app_usbd_langid.h" -#include "app_util_platform.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Compiler support for anonymous unions */ -ANON_UNIONS_ENABLE; - -/** - * @defgroup app_usbd_descriptor USB standard descriptors - * @ingroup app_usbd - * - * @brief @tagAPI52840 Module with types definitions used for standard descriptors. - * @{ - */ - -/** - * @brief Helper macro for translating unsigned 24 bit value to 2 byte raw descriptor. - * */ -#define APP_USBD_U16_TO_RAW_DSC(val) (uint8_t)(val), \ - (uint8_t)(((val) / (256))) - -/** - * @brief Helper macro for translating unsigned 24 bit value to 3 byte raw descriptor. - * */ -#define APP_USBD_U24_TO_RAW_DSC(val) (uint8_t)(val), \ - (uint8_t)(((val) / (256))), \ - (uint8_t)(((val) / (256 * 256))) - -/** - * @brief Helper macro for translating unsigned 32 bit value to 4 byte raw descriptor. - * */ -#define APP_USBD_U32_TO_RAW_DSC(val) (uint8_t)(val), \ - (uint8_t)(((val) / (256))), \ - (uint8_t)(((val) / (256 * 256))) \ - (uint8_t)(((val) / (256 * 256 * 256))) -/** - * @brief Descriptor types. - * - * Descriptor types used in two situations: - * - when processing @ref APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR SETUP request, - * the required descriptor type may be placed in wValue in HighByte. - * - As a descriptor identifier itself inside descriptor stream. - * - * According to chapter 9.6 of USB 2.0 specification, following descriptors may - * be requested directly by GetDescriptor method: - * - @ref APP_USBD_DESCRIPTOR_DEVICE - * - @ref APP_USBD_DESCRIPTOR_DEVICE_QUALIFIER (not used for FullSpeed only device) - * - @ref APP_USBD_DESCRIPTOR_CONFIGURATION - * - @ref APP_USBD_DESCRIPTOR_STRING - */ -typedef enum -{ - APP_USBD_DESCRIPTOR_DEVICE = 1, /**< Device descriptor. */ - APP_USBD_DESCRIPTOR_CONFIGURATION = 2, /**< - * Specific configuration descriptor. - * Configuration descriptor is always followed by all the related interface - * and endpoints descriptors. - */ - APP_USBD_DESCRIPTOR_STRING = 3, /**< String descriptor. */ - APP_USBD_DESCRIPTOR_INTERFACE = 4, /**< - * Interface descriptor followed by all the related endpoints descriptors. - * - * @note It is returned together with @ref APP_USBD_DESCRIPTOR_CONFIGURATION. - * Cannot be accessed by GetDescriptor or SetDescriptor - */ - APP_USBD_DESCRIPTOR_ENDPOINT = 5, /**< - * Endpoint descriptor. - * - * @note It is returned together with @ref APP_USBD_DESCRIPTOR_CONFIGURATION. - * Cannot be accessed by GetDescriptor or SetDescriptor - */ - APP_USBD_DESCRIPTOR_DEVICE_QUALIFIER = 6, /**< @note Not supported - used only in HighSpeed capable devices. */ - APP_USBD_DESCRIPTOR_OTHER_SPEED_CONFIGURATION = 7, /**< @note Not supported - our USB implementation supports only one speed. */ - APP_USBD_DESCRIPTOR_INTERFACE_POWER = 8, /**< @note Not supported */ - APP_USBD_DESCRIPTOR_OTG = 9, /**< @note Not supported - Our USB have not OTG functionality */ - APP_USBD_DESCRIPTOR_DEBUG = 10, /**< Debug channel descriptor if available, can be only reached by GetDescriptor */ - APP_USBD_DESCRIPTOR_INTERFACE_ASSOCIATION = 11, /**< - * Descriptor used to describe that two or more interfaces are associated to the same function. - * - * @note It is returned together with @ref APP_USBD_DESCRIPTOR_CONFIGURATION. - * Cannot be accessed by GetDescriptor or SetDescriptor - */ - APP_USBD_DESCRIPTOR_REPORT = 34, /**< HID Report descriptor. */ - APP_USBD_DESCRIPTOR_PHYSICAL = 35 /**< HID Physical descriptor. */ - -} app_usbd_descriptor_t; - -/* Make all descriptors packed */ -#pragma pack(push, 1) - -/** - * @brief Common descriptor header. - * - * The header that we can find on the beginning of all descriptors that contains - * the descriptor length and type. - */ -typedef struct -{ - uint8_t bLength; //!< Size of the descriptor in bytes. - uint8_t bDescriptorType; //!< Should equal one of @ref app_usbd_descriptor_t. - /** Class specific descriptors values are defined inside classes. */ -} app_usbd_descriptor_header_t; - -/** - * @brief Device descriptor. - * - * Descriptor used for the whole device. - */ -typedef struct -{ - uint8_t bLength; //!< Size of the descriptor in bytes. - uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_DEVICE. - uint16_t bcdUSB; //!< USB Specification Release Number in Binary-Coded Decimal - uint8_t bDeviceClass; //!< Device class code. - /**< If 0, each interface specifies its own class information. - * 0xFF for vendor-specific. - */ - uint8_t bDeviceSubClass; //!< Subclass code. - /**< If bDevice Class is set to value other than 0xFF, - * all values here are reserved for assignment by USB-IF. - */ - uint8_t bDeviceProtocol; //!< Subclass code. - /**< If 0, no specific protocol is defined on device basis. - * Each interface may define its own protocol then. - * If set to 0xFF, vendor-specific protocol is used. - */ - uint8_t bMaxPacketSize0; //!< Maximum packet size for endpoint zero. - uint16_t idVendor; //!< Vendor ID (Assigned by the USB-IF). - uint16_t idProduct; //!< Product ID (assigned by manufacturer). - uint16_t bcdDevice; //!< Device release number in binary-coded decimal. - uint8_t iManufacturer; //!< Index of string descriptor in describing manufacturer. - uint8_t iProduct; //!< Index of string descriptor in describing product. - uint8_t iSerialNumber; //!< Index of string descriptor in describing the device's serial number. - uint8_t bNumConfigurations; //!< Number of possible configurations. -} app_usbd_descriptor_device_t; - -/** - * @brief Attributes masks. - * - * Masks used for attributes in configuration. - */ -typedef enum -{ - /** This is reserved descriptor that has always to be set */ - APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_ALWAYS_SET_MASK = 1U << 7, - /** Attribute that informs that device is self powered */ - APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_SELF_POWERED_MASK = 1U << 6, - /** Attribute that informs that device has Remove Wakeup functionality */ - APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_REMOTE_WAKEUP_MASK = 1U << 5 -} app_usbd_descriptor_configuration_attributes_t; - -/** - * @brief Configuration descriptor. - * - * Descriptor used at the beginning of configuration response. - */ -typedef struct -{ - uint8_t bLength; //!< Size of the descriptor in bytes. - uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_DEVICE. - uint16_t wTotalLength; //!< Total length of configuration data, including all descriptors returned after configuration itself. - uint8_t bNumInterfaces; //!< Number of interfaces supportedf by this configuration - uint8_t bConfigurationValue; //!< Value to use as an argument to the SetConfiguration request. - uint8_t iConfiguration; //!< Index of string descriptor describing this configuration. - uint8_t bmAttributes; //!< Configuration characteristics. - uint8_t bMaxPower; //!< Maximum power consumption. Expressed in 2 mA units. -} app_usbd_descriptor_configuration_t; - -/** - * @brief Raw descriptor - String descriptor zero. - * - * String descriptor sent only as a response for GetDescriptor. - */ -typedef struct -{ - uint8_t bLength; //!< Size of the descriptor in bytes. - uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_STRING. - uint16_t wLANGID[]; //!< The array of LANGID codes supported by the device. -} app_usbd_descriptor_string0_t; - -/** - * @brief Raw descriptor - Any normal string. - * - * String descriptor sent only as a response for GetDescriptor. - */ -typedef struct -{ - uint8_t bLength; //!< Size of the descriptor in bytes. - uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_STRING. - uint16_t bString[]; //!< UNICODE encoded string. -} app_usbd_descriptor_string_t; - - -/** - * @brief Interface descriptor. - * - * Interface descriptor, returned as a part of configuration descriptor. - */ -typedef struct -{ - uint8_t bLength; //!< Size of the descriptor in bytes. - uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_INTERFACE. - uint8_t bInterfaceNumber; //!< Number of this interface. - uint8_t bAlternateSetting; //!< Value used to select this alternate setting. - uint8_t bNumEndpoints; //!< Number of endpoints used by this interface. - uint8_t bInterfaceClass; //!< Class code (assigned by the USB-IF). 0xff for vendor specific. - uint8_t bInterfaceSubClass; //!< Subclass code (assigned by the USB-IF). - uint8_t bInterfaceProtocol; //!< Protocol code (assigned by the USB-IF). 0xff for vendor specific. - uint8_t iInterface; //!< Index of string descriptor describing this interface. -} app_usbd_descriptor_iface_t; - -/** Offset of endpoint type attribute bits */ -#define APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET 0 -/** Mask of endpoint type attribute bits */ -#define APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_MASK BF_MASK(2, APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET) - -/** Offset of endpoint synchronization type attribute bits */ -#define APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET 2 -/** Mask of endpoint synchronization type attribute bits */ -#define APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_MASK BF_MASK(2, APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET) - -/** Offset of endpoint usage type attribute bits */ -#define APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET 4 -/** Mask of endpoint usage type attribute bits */ -#define APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_MASK BF_MASK(2, APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET) - -/** - * @brief Endpoint attributes mnemonics. - * - * @sa APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_MASK - * @sa APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_MASK - * @sa APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_MASK - */ -typedef enum -{ - APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_CONTROL = 0 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, - APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_ISOCHRONOUS = 1 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, - APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK = 2 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, - APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_INTERRUPT = 3 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, - - APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_NONE = 0 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, - APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_ASYNCHRONOUS = 1 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, - APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_ADAPTIVE = 2 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, - APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_SYNCHRONOUS = 3 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, - - APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_DATA = 0 << APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET, - APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_FEEDBACK = 1 << APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET, - APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_IMPLICIT = 2 << APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET -} app_usbd_descriptor_ep_attr_bitmap_t; - -/** - * @brief Endpoint descriptor. - * - * Endpoint descriptor, returned as a part of configuration descriptor. - */ -typedef struct -{ - uint8_t bLength; //!< Size of the descriptor in bytes. - uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_ENDPOINT. - uint8_t bEndpointAddress; //!< Endpoint address - uint8_t bmAttributes; //!< Endpoint attributes - uint16_t wMaxPacketSize; //!< Maximum packet size this endpoint is capable of handling. - uint8_t bInterval; //!< Interval for pooling endpoint for data transfers. -} app_usbd_descriptor_ep_t; - -/** - * @brief Interface association descriptor. - */ -typedef struct -{ - uint8_t bLength; //!< size of this descriptor in bytes - uint8_t bDescriptorType; //!< INTERFACE descriptor type - uint8_t bFirstInterface; //!< Number of interface - uint8_t bInterfaceCount; //!< value to select alternate setting - uint8_t bFunctionClass; //!< Class code assigned by the USB - uint8_t bFunctionSubClass;//!< Sub-class code assigned by the USB - uint8_t bFunctionProtocol;//!< Protocol code assigned by the USB - uint8_t iFunction; //!< Index of string descriptor -} app_usbd_descriptor_iad_t; - -#pragma pack(pop) -ANON_UNIONS_DISABLE; - -#ifdef __cplusplus -} -#endif - -/** @} */ -#endif /* APP_USBD_DESCRIPTOR_H__ */ +/** + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef APP_USBD_DESCRIPTOR_H__ +#define APP_USBD_DESCRIPTOR_H__ + +#include "nrf.h" +#include "nrf_drv_usbd.h" +#include "app_usbd_langid.h" +#include "app_util_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Compiler support for anonymous unions */ +ANON_UNIONS_ENABLE; + +/** + * @defgroup app_usbd_descriptor USB standard descriptors + * @ingroup app_usbd + * + * @brief @tagAPI52840 Module with types definitions used for standard descriptors. + * @{ + */ + +/** + * @brief Helper macro for translating unsigned 24 bit value to 2 byte raw descriptor. + * */ +#define APP_USBD_U16_TO_RAW_DSC(val) (uint8_t)(val), \ + (uint8_t)(((val) / (256))) + +/** + * @brief Helper macro for translating unsigned 24 bit value to 3 byte raw descriptor. + * */ +#define APP_USBD_U24_TO_RAW_DSC(val) (uint8_t)(val), \ + (uint8_t)(((val) / (256))), \ + (uint8_t)(((val) / (256 * 256))) + +/** + * @brief Helper macro for translating unsigned 32 bit value to 4 byte raw descriptor. + * */ +#define APP_USBD_U32_TO_RAW_DSC(val) (uint8_t)(val), \ + (uint8_t)(((val) / (256))), \ + (uint8_t)(((val) / (256 * 256))) \ + (uint8_t)(((val) / (256 * 256 * 256))) +/** + * @brief Descriptor types. + * + * Descriptor types used in two situations: + * - when processing @ref APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR SETUP request, + * the required descriptor type may be placed in wValue in HighByte. + * - As a descriptor identifier itself inside descriptor stream. + * + * According to chapter 9.6 of USB 2.0 specification, following descriptors may + * be requested directly by GetDescriptor method: + * - @ref APP_USBD_DESCRIPTOR_DEVICE + * - @ref APP_USBD_DESCRIPTOR_DEVICE_QUALIFIER (not used for FullSpeed only device) + * - @ref APP_USBD_DESCRIPTOR_CONFIGURATION + * - @ref APP_USBD_DESCRIPTOR_STRING + */ +typedef enum +{ + APP_USBD_DESCRIPTOR_DEVICE = 1, /**< Device descriptor. */ + APP_USBD_DESCRIPTOR_CONFIGURATION = 2, /**< + * Specific configuration descriptor. + * Configuration descriptor is always followed by all the related interface + * and endpoints descriptors. + */ + APP_USBD_DESCRIPTOR_STRING = 3, /**< String descriptor. */ + APP_USBD_DESCRIPTOR_INTERFACE = 4, /**< + * Interface descriptor followed by all the related endpoints descriptors. + * + * @note It is returned together with @ref APP_USBD_DESCRIPTOR_CONFIGURATION. + * Cannot be accessed by GetDescriptor or SetDescriptor + */ + APP_USBD_DESCRIPTOR_ENDPOINT = 5, /**< + * Endpoint descriptor. + * + * @note It is returned together with @ref APP_USBD_DESCRIPTOR_CONFIGURATION. + * Cannot be accessed by GetDescriptor or SetDescriptor + */ + APP_USBD_DESCRIPTOR_DEVICE_QUALIFIER = 6, /**< @note Not supported - used only in HighSpeed capable devices. */ + APP_USBD_DESCRIPTOR_OTHER_SPEED_CONFIGURATION = 7, /**< @note Not supported - our USB implementation supports only one speed. */ + APP_USBD_DESCRIPTOR_INTERFACE_POWER = 8, /**< @note Not supported */ + APP_USBD_DESCRIPTOR_OTG = 9, /**< @note Not supported - Our USB have not OTG functionality */ + APP_USBD_DESCRIPTOR_DEBUG = 10, /**< Debug channel descriptor if available, can be only reached by GetDescriptor */ + APP_USBD_DESCRIPTOR_INTERFACE_ASSOCIATION = 11, /**< + * Descriptor used to describe that two or more interfaces are associated to the same function. + * + * @note It is returned together with @ref APP_USBD_DESCRIPTOR_CONFIGURATION. + * Cannot be accessed by GetDescriptor or SetDescriptor + */ + APP_USBD_DESCRIPTOR_REPORT = 34, /**< HID Report descriptor. */ + APP_USBD_DESCRIPTOR_PHYSICAL = 35 /**< HID Physical descriptor. */ + +} app_usbd_descriptor_t; + +/* Make all descriptors packed */ +#pragma pack(push, 1) + +/** + * @brief Common descriptor header. + * + * The header that we can find on the beginning of all descriptors that contains + * the descriptor length and type. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal one of @ref app_usbd_descriptor_t. + /** Class specific descriptors values are defined inside classes. */ +} app_usbd_descriptor_header_t; + +/** + * @brief Device descriptor. + * + * Descriptor used for the whole device. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_DEVICE. + uint16_t bcdUSB; //!< USB Specification Release Number in Binary-Coded Decimal + uint8_t bDeviceClass; //!< Device class code. + /**< If 0, each interface specifies its own class information. + * 0xFF for vendor-specific. + */ + uint8_t bDeviceSubClass; //!< Subclass code. + /**< If bDevice Class is set to value other than 0xFF, + * all values here are reserved for assignment by USB-IF. + */ + uint8_t bDeviceProtocol; //!< Subclass code. + /**< If 0, no specific protocol is defined on device basis. + * Each interface may define its own protocol then. + * If set to 0xFF, vendor-specific protocol is used. + */ + uint8_t bMaxPacketSize0; //!< Maximum packet size for endpoint zero. + uint16_t idVendor; //!< Vendor ID (Assigned by the USB-IF). + uint16_t idProduct; //!< Product ID (assigned by manufacturer). + uint16_t bcdDevice; //!< Device release number in binary-coded decimal. + uint8_t iManufacturer; //!< Index of string descriptor in describing manufacturer. + uint8_t iProduct; //!< Index of string descriptor in describing product. + uint8_t iSerialNumber; //!< Index of string descriptor in describing the device's serial number. + uint8_t bNumConfigurations; //!< Number of possible configurations. +} app_usbd_descriptor_device_t; + +/** + * @brief Attributes masks. + * + * Masks used for attributes in configuration. + */ +typedef enum +{ + /** This is reserved descriptor that has always to be set */ + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_ALWAYS_SET_MASK = 1U << 7, + /** Attribute that informs that device is self powered */ + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_SELF_POWERED_MASK = 1U << 6, + /** Attribute that informs that device has Remove Wakeup functionality */ + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_REMOTE_WAKEUP_MASK = 1U << 5 +} app_usbd_descriptor_configuration_attributes_t; + +/** + * @brief Configuration descriptor. + * + * Descriptor used at the beginning of configuration response. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_DEVICE. + uint16_t wTotalLength; //!< Total length of configuration data, including all descriptors returned after configuration itself. + uint8_t bNumInterfaces; //!< Number of interfaces supportedf by this configuration + uint8_t bConfigurationValue; //!< Value to use as an argument to the SetConfiguration request. + uint8_t iConfiguration; //!< Index of string descriptor describing this configuration. + uint8_t bmAttributes; //!< Configuration characteristics. + uint8_t bMaxPower; //!< Maximum power consumption. Expressed in 2 mA units. +} app_usbd_descriptor_configuration_t; + +/** + * @brief Raw descriptor - String descriptor zero. + * + * String descriptor sent only as a response for GetDescriptor. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_STRING. + uint16_t wLANGID[]; //!< The array of LANGID codes supported by the device. +} app_usbd_descriptor_string0_t; + +/** + * @brief Raw descriptor - Any normal string. + * + * String descriptor sent only as a response for GetDescriptor. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_STRING. + uint16_t bString[]; //!< UNICODE encoded string. +} app_usbd_descriptor_string_t; + + +/** + * @brief Interface descriptor. + * + * Interface descriptor, returned as a part of configuration descriptor. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_INTERFACE. + uint8_t bInterfaceNumber; //!< Number of this interface. + uint8_t bAlternateSetting; //!< Value used to select this alternate setting. + uint8_t bNumEndpoints; //!< Number of endpoints used by this interface. + uint8_t bInterfaceClass; //!< Class code (assigned by the USB-IF). 0xff for vendor specific. + uint8_t bInterfaceSubClass; //!< Subclass code (assigned by the USB-IF). + uint8_t bInterfaceProtocol; //!< Protocol code (assigned by the USB-IF). 0xff for vendor specific. + uint8_t iInterface; //!< Index of string descriptor describing this interface. +} app_usbd_descriptor_iface_t; + +/** Offset of endpoint type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET 0 +/** Mask of endpoint type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_MASK BF_MASK(2, APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET) + +/** Offset of endpoint synchronization type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET 2 +/** Mask of endpoint synchronization type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_MASK BF_MASK(2, APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET) + +/** Offset of endpoint usage type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET 4 +/** Mask of endpoint usage type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_MASK BF_MASK(2, APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET) + +/** + * @brief Endpoint attributes mnemonics. + * + * @sa APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_MASK + * @sa APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_MASK + * @sa APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_MASK + */ +typedef enum +{ + APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_CONTROL = 0 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_ISOCHRONOUS = 1 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK = 2 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_INTERRUPT = 3 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, + + APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_NONE = 0 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_ASYNCHRONOUS = 1 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_ADAPTIVE = 2 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_SYNCHRONOUS = 3 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, + + APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_DATA = 0 << APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_FEEDBACK = 1 << APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_IMPLICIT = 2 << APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET +} app_usbd_descriptor_ep_attr_bitmap_t; + +/** + * @brief Endpoint descriptor. + * + * Endpoint descriptor, returned as a part of configuration descriptor. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_ENDPOINT. + uint8_t bEndpointAddress; //!< Endpoint address + uint8_t bmAttributes; //!< Endpoint attributes + uint16_t wMaxPacketSize; //!< Maximum packet size this endpoint is capable of handling. + uint8_t bInterval; //!< Interval for pooling endpoint for data transfers. +} app_usbd_descriptor_ep_t; + +/** + * @brief Interface association descriptor. + */ +typedef struct +{ + uint8_t bLength; //!< size of this descriptor in bytes + uint8_t bDescriptorType; //!< INTERFACE descriptor type + uint8_t bFirstInterface; //!< Number of interface + uint8_t bInterfaceCount; //!< value to select alternate setting + uint8_t bFunctionClass; //!< Class code assigned by the USB + uint8_t bFunctionSubClass;//!< Sub-class code assigned by the USB + uint8_t bFunctionProtocol;//!< Protocol code assigned by the USB + uint8_t iFunction; //!< Index of string descriptor +} app_usbd_descriptor_iad_t; + +#pragma pack(pop) +ANON_UNIONS_DISABLE; + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* APP_USBD_DESCRIPTOR_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_langid.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_langid.h index 716050295..b38cddf2b 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_langid.h +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_langid.h @@ -1,300 +1,300 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef APP_USBD_LANGID_H__ -#define APP_USBD_LANGID_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file - * @brief This file contains LANGID variable type with all defined values. - * - * This file was created using Language Identifiers (LANGIDs) 3/29/00 Version 1.0, - * available on USB web page: - * http://www.usb.org/developers/docs/USB_LANGIDs.pdf - * - * @note - * Do not include this file directly to the project. - * It is included by @file app_usbd_request.h. - */ - -/** - * Offset of the lowest bit of primary language identifier. - * @sa app_usbd_langid_t - */ -#define APP_USB_LANG_OFFSET 0 - -/** - * Bitmask for a primary language identifier. - * @sa app_usbd_langid_t - */ -#define APP_USB_LANG_MASK BF_MASK(10, APP_USB_LANG_OFFSET) - -/** - * Macro for defining language identifier. - * - * @param x Language identifier value. - */ -#define APP_USB_LANG_DEF(x) ((x) << (APP_USB_LANG_OFFSET)) - -/** - * Offset of the lowest bit of sublanguage identifier. - * @sa app_usbd_langid_t - */ -#define APP_USB_SUBLANG_OFFSET 10 - -/** - * Bitmask for a sublanguage identifier. - * @sa app_usbd_langid_t - */ -#define APP_USB_SUBLANG_MASK BF_MASK(6, APP_USB_SUBLANG_OFFSET) - -/** - * Macro for defining language identifier. - * - * @param x Language identifier value. - */ -#define APP_USB_SUBLANG_DEF(x) ((x) << (APP_USB_SUBLANG_OFFSET)) - -/** - * @brief Primary language identifiers. - * - * Mnemonics for primary language identifiers. - * This mnemonics can be combined using the logical OR operator with @ref app_usbd_langid_sub_t. - */ -typedef enum -{ - APP_USBD_LANG_ARABIC = APP_USB_LANG_DEF(0x01U), /**< Arabic */ - APP_USBD_LANG_BULGARIAN = APP_USB_LANG_DEF(0x02U), /**< Bulgarian */ - APP_USBD_LANG_CATALAN = APP_USB_LANG_DEF(0x03U), /**< Catalan */ - APP_USBD_LANG_CHINESE = APP_USB_LANG_DEF(0x04U), /**< Chinese */ - APP_USBD_LANG_CZECH = APP_USB_LANG_DEF(0x05U), /**< Czech */ - APP_USBD_LANG_DANISH = APP_USB_LANG_DEF(0x06U), /**< Danish */ - APP_USBD_LANG_GERMAN = APP_USB_LANG_DEF(0x07U), /**< German */ - APP_USBD_LANG_GREEK = APP_USB_LANG_DEF(0x08U), /**< Greek */ - APP_USBD_LANG_ENGLISH = APP_USB_LANG_DEF(0x09U), /**< English */ - APP_USBD_LANG_SPANISH = APP_USB_LANG_DEF(0x0aU), /**< Spanish */ - APP_USBD_LANG_FINNISH = APP_USB_LANG_DEF(0x0bU), /**< Finnish */ - APP_USBD_LANG_FRENCH = APP_USB_LANG_DEF(0x0cU), /**< French */ - APP_USBD_LANG_HEBREW = APP_USB_LANG_DEF(0x0dU), /**< Hebrew */ - APP_USBD_LANG_HUNGARIAN = APP_USB_LANG_DEF(0x0eU), /**< Hungarian */ - APP_USBD_LANG_ICELANDIC = APP_USB_LANG_DEF(0x0fU), /**< Icelandic */ - APP_USBD_LANG_ITALIAN = APP_USB_LANG_DEF(0x10U), /**< Italian */ - APP_USBD_LANG_JAPANESE = APP_USB_LANG_DEF(0x11U), /**< Japanese */ - APP_USBD_LANG_KOREAN = APP_USB_LANG_DEF(0x12U), /**< Korean */ - APP_USBD_LANG_DUTCH = APP_USB_LANG_DEF(0x13U), /**< Dutch */ - APP_USBD_LANG_NORWEGIAN = APP_USB_LANG_DEF(0x14U), /**< Norwegian */ - APP_USBD_LANG_POLISH = APP_USB_LANG_DEF(0x15U), /**< Polish */ - APP_USBD_LANG_PORTUGUESE = APP_USB_LANG_DEF(0x16U), /**< Portuguese */ - APP_USBD_LANG_ROMANIAN = APP_USB_LANG_DEF(0x18U), /**< Romanian */ - APP_USBD_LANG_RUSSIAN = APP_USB_LANG_DEF(0x19U), /**< Russian */ - APP_USBD_LANG_CROATIAN = APP_USB_LANG_DEF(0x1aU), /**< Croatian */ - APP_USBD_LANG_SERBIAN = APP_USB_LANG_DEF(0x1aU), /**< Serbian */ - APP_USBD_LANG_SLOVAK = APP_USB_LANG_DEF(0x1bU), /**< Slovak */ - APP_USBD_LANG_ALBANIAN = APP_USB_LANG_DEF(0x1cU), /**< Albanian */ - APP_USBD_LANG_SWEDISH = APP_USB_LANG_DEF(0x1dU), /**< Swedish */ - APP_USBD_LANG_THAI = APP_USB_LANG_DEF(0x1eU), /**< Thai */ - APP_USBD_LANG_TURKISH = APP_USB_LANG_DEF(0x1fU), /**< Turkish */ - APP_USBD_LANG_URDU = APP_USB_LANG_DEF(0x20U), /**< Urdu */ - APP_USBD_LANG_INDONESIAN = APP_USB_LANG_DEF(0x21U), /**< Indonesian */ - APP_USBD_LANG_UKRANIAN = APP_USB_LANG_DEF(0x22U), /**< Ukrainian */ - APP_USBD_LANG_BELARUSIAN = APP_USB_LANG_DEF(0x23U), /**< Belarusian */ - APP_USBD_LANG_SLOVENIAN = APP_USB_LANG_DEF(0x24U), /**< Slovenian */ - APP_USBD_LANG_ESTONIAN = APP_USB_LANG_DEF(0x25U), /**< Estonian */ - APP_USBD_LANG_LATVIAN = APP_USB_LANG_DEF(0x26U), /**< Latvian */ - APP_USBD_LANG_LITHUANIAN = APP_USB_LANG_DEF(0x27U), /**< Lithuanian */ - APP_USBD_LANG_FARSI = APP_USB_LANG_DEF(0x29U), /**< Farsi */ - APP_USBD_LANG_VIETNAMESE = APP_USB_LANG_DEF(0x2aU), /**< Vietnamese */ - APP_USBD_LANG_ARMENIAN = APP_USB_LANG_DEF(0x2bU), /**< Armenian */ - APP_USBD_LANG_AZERI = APP_USB_LANG_DEF(0x2cU), /**< Azeri */ - APP_USBD_LANG_BASQUE = APP_USB_LANG_DEF(0x2dU), /**< Basque */ - APP_USBD_LANG_MACEDONIAN = APP_USB_LANG_DEF(0x2fU), /**< Macedonian */ - APP_USBD_LANG_AFRIKAANS = APP_USB_LANG_DEF(0x36U), /**< Afrikaans */ - APP_USBD_LANG_GEORGIAN = APP_USB_LANG_DEF(0x37U), /**< Georgian */ - APP_USBD_LANG_FAEROESE = APP_USB_LANG_DEF(0x38U), /**< Faeroese */ - APP_USBD_LANG_HINDI = APP_USB_LANG_DEF(0x39U), /**< Hindi */ - APP_USBD_LANG_MALAY = APP_USB_LANG_DEF(0x3eU), /**< Malay */ - APP_USBD_LANG_KAZAK = APP_USB_LANG_DEF(0x3fU), /**< Kazak */ - APP_USBD_LANG_SWAHILI = APP_USB_LANG_DEF(0x41U), /**< Swahili */ - APP_USBD_LANG_UZBEK = APP_USB_LANG_DEF(0x43U), /**< Uzbek */ - APP_USBD_LANG_TATAR = APP_USB_LANG_DEF(0x44U), /**< Tatar */ - APP_USBD_LANG_BENGALI = APP_USB_LANG_DEF(0x45U), /**< Bengali */ - APP_USBD_LANG_PUNJABI = APP_USB_LANG_DEF(0x46U), /**< Punjabi */ - APP_USBD_LANG_GUJARATI = APP_USB_LANG_DEF(0x47U), /**< Gujarati */ - APP_USBD_LANG_ORIYA = APP_USB_LANG_DEF(0x48U), /**< Oriya */ - APP_USBD_LANG_TAMIL = APP_USB_LANG_DEF(0x49U), /**< Tamil */ - APP_USBD_LANG_TELUGU = APP_USB_LANG_DEF(0x4aU), /**< Telugu */ - APP_USBD_LANG_KANNADA = APP_USB_LANG_DEF(0x4bU), /**< Kannada */ - APP_USBD_LANG_MALAYALAM = APP_USB_LANG_DEF(0x4cU), /**< Malayalam */ - APP_USBD_LANG_ASSAMESE = APP_USB_LANG_DEF(0x4dU), /**< Assamese */ - APP_USBD_LANG_MARATHI = APP_USB_LANG_DEF(0x4eU), /**< Marathi */ - APP_USBD_LANG_SANSKRIT = APP_USB_LANG_DEF(0x4fU), /**< Sanskrit */ - APP_USBD_LANG_KONKANI = APP_USB_LANG_DEF(0x57U), /**< Konkani */ - APP_USBD_LANG_MANIPURI = APP_USB_LANG_DEF(0x58U), /**< Manipuri */ - APP_USBD_LANG_SINDHI = APP_USB_LANG_DEF(0x59U), /**< Sindhi */ - APP_USBD_LANG_KASHMIRI = APP_USB_LANG_DEF(0x60U), /**< Kashmiri */ - APP_USBD_LANG_NEPALI = APP_USB_LANG_DEF(0x61U), /**< Nepali */ - APP_USBD_LANG_HID = APP_USB_LANG_DEF(0xffU), /**< Reserved for USB HID Class use. */ -} app_usbd_langid_primary_t; - -/** - * @brief Sublanguage identifiers. - * - * Mnemonics with sublanguage values. - * Use them in combination with @ref app_usbd_langid_primary_t. - */ -typedef enum -{ - APP_USBD_SUBLANG_ARABIC_SAUDI_ARABIA = APP_USB_SUBLANG_DEF(0x01U), /**< Arabic (Saudi Arabia) */ - APP_USBD_SUBLANG_ARABIC_IRAQ = APP_USB_SUBLANG_DEF(0x02U), /**< Arabic (Iraq) */ - APP_USBD_SUBLANG_ARABIC_EGYPT = APP_USB_SUBLANG_DEF(0x03U), /**< Arabic (Egypt) */ - APP_USBD_SUBLANG_ARABIC_LIBYA = APP_USB_SUBLANG_DEF(0x04U), /**< Arabic (Libya) */ - APP_USBD_SUBLANG_ARABIC_ALGERIA = APP_USB_SUBLANG_DEF(0x05U), /**< Arabic (Algeria) */ - APP_USBD_SUBLANG_ARABIC_MOROCCO = APP_USB_SUBLANG_DEF(0x06U), /**< Arabic (Morocco) */ - APP_USBD_SUBLANG_ARABIC_TUNISIA = APP_USB_SUBLANG_DEF(0x07U), /**< Arabic (Tunisia) */ - APP_USBD_SUBLANG_ARABIC_OMAN = APP_USB_SUBLANG_DEF(0x08U), /**< Arabic (Oman) */ - APP_USBD_SUBLANG_ARABIC_YEMEN = APP_USB_SUBLANG_DEF(0x09U), /**< Arabic (Yemen) */ - APP_USBD_SUBLANG_ARABIC_SYRIA = APP_USB_SUBLANG_DEF(0x10U), /**< Arabic (Syria) */ - APP_USBD_SUBLANG_ARABIC_JORDAN = APP_USB_SUBLANG_DEF(0x11U), /**< Arabic (Jordan) */ - APP_USBD_SUBLANG_ARABIC_LEBANON = APP_USB_SUBLANG_DEF(0x12U), /**< Arabic (Lebanon) */ - APP_USBD_SUBLANG_ARABIC_KUWAIT = APP_USB_SUBLANG_DEF(0x13U), /**< Arabic (Kuwait) */ - APP_USBD_SUBLANG_ARABIC_UAE = APP_USB_SUBLANG_DEF(0x14U), /**< Arabic (U.A.E.) */ - APP_USBD_SUBLANG_ARABIC_BAHRAIN = APP_USB_SUBLANG_DEF(0x15U), /**< Arabic (Bahrain) */ - APP_USBD_SUBLANG_ARABIC_QATAR = APP_USB_SUBLANG_DEF(0x16U), /**< Arabic (Qatar) */ - APP_USBD_SUBLANG_AZERI_CYRILLIC = APP_USB_SUBLANG_DEF(0x01U), /**< Azeri (Cyrillic) */ - APP_USBD_SUBLANG_AZERI_LATIN = APP_USB_SUBLANG_DEF(0x02U), /**< Azeri (Latin) */ - APP_USBD_SUBLANG_CHINESE_TRADITIONAL = APP_USB_SUBLANG_DEF(0x01U), /**< Chinese (Traditional) */ - APP_USBD_SUBLANG_CHINESE_SIMPLIFIED = APP_USB_SUBLANG_DEF(0x02U), /**< Chinese (Simplified) */ - APP_USBD_SUBLANG_CHINESE_HONGKONG = APP_USB_SUBLANG_DEF(0x03U), /**< Chinese (Hong Kong SAR, PRC) */ - APP_USBD_SUBLANG_CHINESE_SINGAPORE = APP_USB_SUBLANG_DEF(0x04U), /**< Chinese (Singapore) */ - APP_USBD_SUBLANG_CHINESE_MACAU = APP_USB_SUBLANG_DEF(0x05U), /**< Chinese (Macau SAR) */ - APP_USBD_SUBLANG_DUTCH = APP_USB_SUBLANG_DEF(0x01U), /**< Dutch */ - APP_USBD_SUBLANG_DUTCH_BELGIAN = APP_USB_SUBLANG_DEF(0x02U), /**< Dutch (Belgian) */ - APP_USBD_SUBLANG_ENGLISH_US = APP_USB_SUBLANG_DEF(0x01U), /**< English (US) */ - APP_USBD_SUBLANG_ENGLISH_UK = APP_USB_SUBLANG_DEF(0x02U), /**< English (UK) */ - APP_USBD_SUBLANG_ENGLISH_AUS = APP_USB_SUBLANG_DEF(0x03U), /**< English (Australian) */ - APP_USBD_SUBLANG_ENGLISH_CAN = APP_USB_SUBLANG_DEF(0x04U), /**< English (Canadian) */ - APP_USBD_SUBLANG_ENGLISH_NZ = APP_USB_SUBLANG_DEF(0x05U), /**< English (New Zealand) */ - APP_USBD_SUBLANG_ENGLISH_EIRE = APP_USB_SUBLANG_DEF(0x06U), /**< English (Ireland) */ - APP_USBD_SUBLANG_ENGLISH_SOUTH_AFRICA = APP_USB_SUBLANG_DEF(0x07U), /**< English (South Africa) */ - APP_USBD_SUBLANG_ENGLISH_JAMAICA = APP_USB_SUBLANG_DEF(0x08U), /**< English (Jamaica) */ - APP_USBD_SUBLANG_ENGLISH_CARIBBEAN = APP_USB_SUBLANG_DEF(0x09U), /**< English (Caribbean) */ - APP_USBD_SUBLANG_ENGLISH_BELIZE = APP_USB_SUBLANG_DEF(0x0aU), /**< English (Belize) */ - APP_USBD_SUBLANG_ENGLISH_TRINIDAD = APP_USB_SUBLANG_DEF(0x0bU), /**< English (Trinidad) */ - APP_USBD_SUBLANG_ENGLISH_PHILIPPINES = APP_USB_SUBLANG_DEF(0x0cU), /**< English (Zimbabwe) */ - APP_USBD_SUBLANG_ENGLISH_ZIMBABWE = APP_USB_SUBLANG_DEF(0x0dU), /**< English (Philippines) */ - APP_USBD_SUBLANG_FRENCH = APP_USB_SUBLANG_DEF(0x01U), /**< French */ - APP_USBD_SUBLANG_FRENCH_BELGIAN = APP_USB_SUBLANG_DEF(0x02U), /**< French (Belgian) */ - APP_USBD_SUBLANG_FRENCH_CANADIAN = APP_USB_SUBLANG_DEF(0x03U), /**< French (Canadian) */ - APP_USBD_SUBLANG_FRENCH_SWISS = APP_USB_SUBLANG_DEF(0x04U), /**< French (Switzerland) */ - APP_USBD_SUBLANG_FRENCH_LUXEMBOURG = APP_USB_SUBLANG_DEF(0x05U), /**< French (Luxembourg) */ - APP_USBD_SUBLANG_FRENCH_MONACO = APP_USB_SUBLANG_DEF(0x06U), /**< French (Monaco) */ - APP_USBD_SUBLANG_GERMAN = APP_USB_SUBLANG_DEF(0x01U), /**< German */ - APP_USBD_SUBLANG_GERMAN_SWISS = APP_USB_SUBLANG_DEF(0x02U), /**< German (Switzerland) */ - APP_USBD_SUBLANG_GERMAN_AUSTRIAN = APP_USB_SUBLANG_DEF(0x03U), /**< German (Austria) */ - APP_USBD_SUBLANG_GERMAN_LUXEMBOURG = APP_USB_SUBLANG_DEF(0x04U), /**< German (Luxembourg) */ - APP_USBD_SUBLANG_GERMAN_LIECHTENSTEIN = APP_USB_SUBLANG_DEF(0x05U), /**< German (Liechtenstein) */ - APP_USBD_SUBLANG_ITALIAN = APP_USB_SUBLANG_DEF(0x01U), /**< Italian */ - APP_USBD_SUBLANG_ITALIAN_SWISS = APP_USB_SUBLANG_DEF(0x02U), /**< Italian (Switzerland) */ - APP_USBD_SUBLANG_KASHMIRI_INDIA = APP_USB_SUBLANG_DEF(0x02U), /**< Kashmiri (India) */ - APP_USBD_SUBLANG_KOREAN = APP_USB_SUBLANG_DEF(0x01U), /**< Korean */ - APP_USBD_SUBLANG_LITHUANIAN = APP_USB_SUBLANG_DEF(0x01U), /**< Lithuanian */ - APP_USBD_SUBLANG_MALAY_MALAYSIA = APP_USB_SUBLANG_DEF(0x01U), /**< Malay (Malaysia) */ - APP_USBD_SUBLANG_MALAY_BRUNEI_DARUSSALAM = APP_USB_SUBLANG_DEF(0x02U), /**< Malay (Brunei Darassalam) */ - APP_USBD_SUBLANG_NEPALI_INDIA = APP_USB_SUBLANG_DEF(0x02U), /**< Nepali (India) */ - APP_USBD_SUBLANG_NORWEGIAN_BOKMAL = APP_USB_SUBLANG_DEF(0x01U), /**< Norwegian (Bokmal) */ - APP_USBD_SUBLANG_NORWEGIAN_NYNORSK = APP_USB_SUBLANG_DEF(0x02U), /**< Norwegian (Nynorsk) */ - APP_USBD_SUBLANG_PORTUGUESE = APP_USB_SUBLANG_DEF(0x01U), /**< Portuguese */ - APP_USBD_SUBLANG_PORTUGUESE_BRAZILIAN = APP_USB_SUBLANG_DEF(0x02U), /**< Portuguese (Brazil) */ - APP_USBD_SUBLANG_SERBIAN_LATIN = APP_USB_SUBLANG_DEF(0x02U), /**< Serbian (Latin) */ - APP_USBD_SUBLANG_SERBIAN_CYRILLIC = APP_USB_SUBLANG_DEF(0x03U), /**< Serbian (Cyrillic) */ - APP_USBD_SUBLANG_SPANISH = APP_USB_SUBLANG_DEF(0x01U), /**< Spanish (Traditional) */ - APP_USBD_SUBLANG_SPANISH_MEXICAN = APP_USB_SUBLANG_DEF(0x02U), /**< Spanish (Mexican) */ - APP_USBD_SUBLANG_SPANISH_MODERN = APP_USB_SUBLANG_DEF(0x03U), /**< Spanish (Modern) */ - APP_USBD_SUBLANG_SPANISH_GUATEMALA = APP_USB_SUBLANG_DEF(0x04U), /**< Spanish (Guatemala) */ - APP_USBD_SUBLANG_SPANISH_COSTA_RICA = APP_USB_SUBLANG_DEF(0x05U), /**< Spanish (Costa Rica) */ - APP_USBD_SUBLANG_SPANISH_PANAMA = APP_USB_SUBLANG_DEF(0x06U), /**< Spanish (Panama) */ - APP_USBD_SUBLANG_SPANISH_DOMINICAN_REPUBLIC = APP_USB_SUBLANG_DEF(0x07U), /**< Spanish (Dominican Republic) */ - APP_USBD_SUBLANG_SPANISH_VENEZUELA = APP_USB_SUBLANG_DEF(0x08U), /**< Spanish (Venezuela) */ - APP_USBD_SUBLANG_SPANISH_COLOMBIA = APP_USB_SUBLANG_DEF(0x09U), /**< Spanish (Colombia) */ - APP_USBD_SUBLANG_SPANISH_PERU = APP_USB_SUBLANG_DEF(0x0aU), /**< Spanish (Peru) */ - APP_USBD_SUBLANG_SPANISH_ARGENTINA = APP_USB_SUBLANG_DEF(0x0bU), /**< Spanish (Argentina) */ - APP_USBD_SUBLANG_SPANISH_ECUADOR = APP_USB_SUBLANG_DEF(0x0cU), /**< Spanish (Ecuador) */ - APP_USBD_SUBLANG_SPANISH_CHILE = APP_USB_SUBLANG_DEF(0x0dU), /**< Spanish (Chile) */ - APP_USBD_SUBLANG_SPANISH_URUGUAY = APP_USB_SUBLANG_DEF(0x0eU), /**< Spanish (Uruguay) */ - APP_USBD_SUBLANG_SPANISH_PARAGUAY = APP_USB_SUBLANG_DEF(0x0fU), /**< Spanish (Paraguay) */ - APP_USBD_SUBLANG_SPANISH_BOLIVIA = APP_USB_SUBLANG_DEF(0x10U), /**< Spanish (Bolivia) */ - APP_USBD_SUBLANG_SPANISH_EL_SALVADOR = APP_USB_SUBLANG_DEF(0x11U), /**< Spanish (El Salvador) */ - APP_USBD_SUBLANG_SPANISH_HONDURAS = APP_USB_SUBLANG_DEF(0x12U), /**< Spanish (Honduras) */ - APP_USBD_SUBLANG_SPANISH_NICARAGUA = APP_USB_SUBLANG_DEF(0x13U), /**< Spanish (Nicaragua) */ - APP_USBD_SUBLANG_SPANISH_PUERTO_RICO = APP_USB_SUBLANG_DEF(0x14U), /**< Spanish (Puerto Rico) */ - APP_USBD_SUBLANG_SWEDISH = APP_USB_SUBLANG_DEF(0x01U), /**< Swedish */ - APP_USBD_SUBLANG_SWEDISH_FINLAND = APP_USB_SUBLANG_DEF(0x02U), /**< Swedish (Finland) */ - APP_USBD_SUBLANG_URDU_PAKISTAN = APP_USB_SUBLANG_DEF(0x01U), /**< Urdu (Pakistan) */ - APP_USBD_SUBLANG_URDU_INDIA = APP_USB_SUBLANG_DEF(0x02U), /**< Urdu (India) */ - APP_USBD_SUBLANG_UZBEK_LATIN = APP_USB_SUBLANG_DEF(0x01U), /**< Uzbek (Latin) */ - APP_USBD_SUBLANG_UZBEK_CYRILLIC = APP_USB_SUBLANG_DEF(0x02U), /**< Uzbek (Cyrillic) */ - APP_USBD_SUBLANG_HID_USAGE_DATA_DESCRIPTOR = APP_USB_SUBLANG_DEF(0x01U), /**< HID (Usage Data Descriptor) */ - APP_USBD_SUBLANG_HID_VENDOR_DEFINED_1 = APP_USB_SUBLANG_DEF(0x3cU), /**< HID (Vendor Defined 1) */ - APP_USBD_SUBLANG_HID_VENDOR_DEFINED_2 = APP_USB_SUBLANG_DEF(0x3dU), /**< HID (Vendor Defined 2) */ - APP_USBD_SUBLANG_HID_VENDOR_DEFINED_3 = APP_USB_SUBLANG_DEF(0x3eU), /**< HID (Vendor Defined 3) */ - APP_USBD_SUBLANG_HID_VENDOR_DEFINED_4 = APP_USB_SUBLANG_DEF(0x3fU), /**< HID (Vendor Defined 4) */ -} app_usbd_langid_sub_t; - -/** - * @brief LANGID variable. - * - * The LANGID value is composed of: - * - 10 bits (9-0) of Primary Language Identifier, - * - 6 bits (15-10) of Sublanguage Identifier. - * - * @sa app_usbd_langid_primary_t - * @sa app_usbd_langid_sub_t - */ -typedef uint16_t app_usbd_langid_t; - -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_LANGID_H__ */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef APP_USBD_LANGID_H__ +#define APP_USBD_LANGID_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @brief This file contains LANGID variable type with all defined values. + * + * This file was created using Language Identifiers (LANGIDs) 3/29/00 Version 1.0, + * available on USB web page: + * http://www.usb.org/developers/docs/USB_LANGIDs.pdf + * + * @note + * Do not include this file directly to the project. + * It is included by @file app_usbd_request.h. + */ + +/** + * Offset of the lowest bit of primary language identifier. + * @sa app_usbd_langid_t + */ +#define APP_USB_LANG_OFFSET 0 + +/** + * Bitmask for a primary language identifier. + * @sa app_usbd_langid_t + */ +#define APP_USB_LANG_MASK BF_MASK(10, APP_USB_LANG_OFFSET) + +/** + * Macro for defining language identifier. + * + * @param x Language identifier value. + */ +#define APP_USB_LANG_DEF(x) ((x) << (APP_USB_LANG_OFFSET)) + +/** + * Offset of the lowest bit of sublanguage identifier. + * @sa app_usbd_langid_t + */ +#define APP_USB_SUBLANG_OFFSET 10 + +/** + * Bitmask for a sublanguage identifier. + * @sa app_usbd_langid_t + */ +#define APP_USB_SUBLANG_MASK BF_MASK(6, APP_USB_SUBLANG_OFFSET) + +/** + * Macro for defining language identifier. + * + * @param x Language identifier value. + */ +#define APP_USB_SUBLANG_DEF(x) ((x) << (APP_USB_SUBLANG_OFFSET)) + +/** + * @brief Primary language identifiers. + * + * Mnemonics for primary language identifiers. + * This mnemonics can be combined using the logical OR operator with @ref app_usbd_langid_sub_t. + */ +typedef enum +{ + APP_USBD_LANG_ARABIC = APP_USB_LANG_DEF(0x01U), /**< Arabic */ + APP_USBD_LANG_BULGARIAN = APP_USB_LANG_DEF(0x02U), /**< Bulgarian */ + APP_USBD_LANG_CATALAN = APP_USB_LANG_DEF(0x03U), /**< Catalan */ + APP_USBD_LANG_CHINESE = APP_USB_LANG_DEF(0x04U), /**< Chinese */ + APP_USBD_LANG_CZECH = APP_USB_LANG_DEF(0x05U), /**< Czech */ + APP_USBD_LANG_DANISH = APP_USB_LANG_DEF(0x06U), /**< Danish */ + APP_USBD_LANG_GERMAN = APP_USB_LANG_DEF(0x07U), /**< German */ + APP_USBD_LANG_GREEK = APP_USB_LANG_DEF(0x08U), /**< Greek */ + APP_USBD_LANG_ENGLISH = APP_USB_LANG_DEF(0x09U), /**< English */ + APP_USBD_LANG_SPANISH = APP_USB_LANG_DEF(0x0aU), /**< Spanish */ + APP_USBD_LANG_FINNISH = APP_USB_LANG_DEF(0x0bU), /**< Finnish */ + APP_USBD_LANG_FRENCH = APP_USB_LANG_DEF(0x0cU), /**< French */ + APP_USBD_LANG_HEBREW = APP_USB_LANG_DEF(0x0dU), /**< Hebrew */ + APP_USBD_LANG_HUNGARIAN = APP_USB_LANG_DEF(0x0eU), /**< Hungarian */ + APP_USBD_LANG_ICELANDIC = APP_USB_LANG_DEF(0x0fU), /**< Icelandic */ + APP_USBD_LANG_ITALIAN = APP_USB_LANG_DEF(0x10U), /**< Italian */ + APP_USBD_LANG_JAPANESE = APP_USB_LANG_DEF(0x11U), /**< Japanese */ + APP_USBD_LANG_KOREAN = APP_USB_LANG_DEF(0x12U), /**< Korean */ + APP_USBD_LANG_DUTCH = APP_USB_LANG_DEF(0x13U), /**< Dutch */ + APP_USBD_LANG_NORWEGIAN = APP_USB_LANG_DEF(0x14U), /**< Norwegian */ + APP_USBD_LANG_POLISH = APP_USB_LANG_DEF(0x15U), /**< Polish */ + APP_USBD_LANG_PORTUGUESE = APP_USB_LANG_DEF(0x16U), /**< Portuguese */ + APP_USBD_LANG_ROMANIAN = APP_USB_LANG_DEF(0x18U), /**< Romanian */ + APP_USBD_LANG_RUSSIAN = APP_USB_LANG_DEF(0x19U), /**< Russian */ + APP_USBD_LANG_CROATIAN = APP_USB_LANG_DEF(0x1aU), /**< Croatian */ + APP_USBD_LANG_SERBIAN = APP_USB_LANG_DEF(0x1aU), /**< Serbian */ + APP_USBD_LANG_SLOVAK = APP_USB_LANG_DEF(0x1bU), /**< Slovak */ + APP_USBD_LANG_ALBANIAN = APP_USB_LANG_DEF(0x1cU), /**< Albanian */ + APP_USBD_LANG_SWEDISH = APP_USB_LANG_DEF(0x1dU), /**< Swedish */ + APP_USBD_LANG_THAI = APP_USB_LANG_DEF(0x1eU), /**< Thai */ + APP_USBD_LANG_TURKISH = APP_USB_LANG_DEF(0x1fU), /**< Turkish */ + APP_USBD_LANG_URDU = APP_USB_LANG_DEF(0x20U), /**< Urdu */ + APP_USBD_LANG_INDONESIAN = APP_USB_LANG_DEF(0x21U), /**< Indonesian */ + APP_USBD_LANG_UKRANIAN = APP_USB_LANG_DEF(0x22U), /**< Ukrainian */ + APP_USBD_LANG_BELARUSIAN = APP_USB_LANG_DEF(0x23U), /**< Belarusian */ + APP_USBD_LANG_SLOVENIAN = APP_USB_LANG_DEF(0x24U), /**< Slovenian */ + APP_USBD_LANG_ESTONIAN = APP_USB_LANG_DEF(0x25U), /**< Estonian */ + APP_USBD_LANG_LATVIAN = APP_USB_LANG_DEF(0x26U), /**< Latvian */ + APP_USBD_LANG_LITHUANIAN = APP_USB_LANG_DEF(0x27U), /**< Lithuanian */ + APP_USBD_LANG_FARSI = APP_USB_LANG_DEF(0x29U), /**< Farsi */ + APP_USBD_LANG_VIETNAMESE = APP_USB_LANG_DEF(0x2aU), /**< Vietnamese */ + APP_USBD_LANG_ARMENIAN = APP_USB_LANG_DEF(0x2bU), /**< Armenian */ + APP_USBD_LANG_AZERI = APP_USB_LANG_DEF(0x2cU), /**< Azeri */ + APP_USBD_LANG_BASQUE = APP_USB_LANG_DEF(0x2dU), /**< Basque */ + APP_USBD_LANG_MACEDONIAN = APP_USB_LANG_DEF(0x2fU), /**< Macedonian */ + APP_USBD_LANG_AFRIKAANS = APP_USB_LANG_DEF(0x36U), /**< Afrikaans */ + APP_USBD_LANG_GEORGIAN = APP_USB_LANG_DEF(0x37U), /**< Georgian */ + APP_USBD_LANG_FAEROESE = APP_USB_LANG_DEF(0x38U), /**< Faeroese */ + APP_USBD_LANG_HINDI = APP_USB_LANG_DEF(0x39U), /**< Hindi */ + APP_USBD_LANG_MALAY = APP_USB_LANG_DEF(0x3eU), /**< Malay */ + APP_USBD_LANG_KAZAK = APP_USB_LANG_DEF(0x3fU), /**< Kazak */ + APP_USBD_LANG_SWAHILI = APP_USB_LANG_DEF(0x41U), /**< Swahili */ + APP_USBD_LANG_UZBEK = APP_USB_LANG_DEF(0x43U), /**< Uzbek */ + APP_USBD_LANG_TATAR = APP_USB_LANG_DEF(0x44U), /**< Tatar */ + APP_USBD_LANG_BENGALI = APP_USB_LANG_DEF(0x45U), /**< Bengali */ + APP_USBD_LANG_PUNJABI = APP_USB_LANG_DEF(0x46U), /**< Punjabi */ + APP_USBD_LANG_GUJARATI = APP_USB_LANG_DEF(0x47U), /**< Gujarati */ + APP_USBD_LANG_ORIYA = APP_USB_LANG_DEF(0x48U), /**< Oriya */ + APP_USBD_LANG_TAMIL = APP_USB_LANG_DEF(0x49U), /**< Tamil */ + APP_USBD_LANG_TELUGU = APP_USB_LANG_DEF(0x4aU), /**< Telugu */ + APP_USBD_LANG_KANNADA = APP_USB_LANG_DEF(0x4bU), /**< Kannada */ + APP_USBD_LANG_MALAYALAM = APP_USB_LANG_DEF(0x4cU), /**< Malayalam */ + APP_USBD_LANG_ASSAMESE = APP_USB_LANG_DEF(0x4dU), /**< Assamese */ + APP_USBD_LANG_MARATHI = APP_USB_LANG_DEF(0x4eU), /**< Marathi */ + APP_USBD_LANG_SANSKRIT = APP_USB_LANG_DEF(0x4fU), /**< Sanskrit */ + APP_USBD_LANG_KONKANI = APP_USB_LANG_DEF(0x57U), /**< Konkani */ + APP_USBD_LANG_MANIPURI = APP_USB_LANG_DEF(0x58U), /**< Manipuri */ + APP_USBD_LANG_SINDHI = APP_USB_LANG_DEF(0x59U), /**< Sindhi */ + APP_USBD_LANG_KASHMIRI = APP_USB_LANG_DEF(0x60U), /**< Kashmiri */ + APP_USBD_LANG_NEPALI = APP_USB_LANG_DEF(0x61U), /**< Nepali */ + APP_USBD_LANG_HID = APP_USB_LANG_DEF(0xffU), /**< Reserved for USB HID Class use. */ +} app_usbd_langid_primary_t; + +/** + * @brief Sublanguage identifiers. + * + * Mnemonics with sublanguage values. + * Use them in combination with @ref app_usbd_langid_primary_t. + */ +typedef enum +{ + APP_USBD_SUBLANG_ARABIC_SAUDI_ARABIA = APP_USB_SUBLANG_DEF(0x01U), /**< Arabic (Saudi Arabia) */ + APP_USBD_SUBLANG_ARABIC_IRAQ = APP_USB_SUBLANG_DEF(0x02U), /**< Arabic (Iraq) */ + APP_USBD_SUBLANG_ARABIC_EGYPT = APP_USB_SUBLANG_DEF(0x03U), /**< Arabic (Egypt) */ + APP_USBD_SUBLANG_ARABIC_LIBYA = APP_USB_SUBLANG_DEF(0x04U), /**< Arabic (Libya) */ + APP_USBD_SUBLANG_ARABIC_ALGERIA = APP_USB_SUBLANG_DEF(0x05U), /**< Arabic (Algeria) */ + APP_USBD_SUBLANG_ARABIC_MOROCCO = APP_USB_SUBLANG_DEF(0x06U), /**< Arabic (Morocco) */ + APP_USBD_SUBLANG_ARABIC_TUNISIA = APP_USB_SUBLANG_DEF(0x07U), /**< Arabic (Tunisia) */ + APP_USBD_SUBLANG_ARABIC_OMAN = APP_USB_SUBLANG_DEF(0x08U), /**< Arabic (Oman) */ + APP_USBD_SUBLANG_ARABIC_YEMEN = APP_USB_SUBLANG_DEF(0x09U), /**< Arabic (Yemen) */ + APP_USBD_SUBLANG_ARABIC_SYRIA = APP_USB_SUBLANG_DEF(0x10U), /**< Arabic (Syria) */ + APP_USBD_SUBLANG_ARABIC_JORDAN = APP_USB_SUBLANG_DEF(0x11U), /**< Arabic (Jordan) */ + APP_USBD_SUBLANG_ARABIC_LEBANON = APP_USB_SUBLANG_DEF(0x12U), /**< Arabic (Lebanon) */ + APP_USBD_SUBLANG_ARABIC_KUWAIT = APP_USB_SUBLANG_DEF(0x13U), /**< Arabic (Kuwait) */ + APP_USBD_SUBLANG_ARABIC_UAE = APP_USB_SUBLANG_DEF(0x14U), /**< Arabic (U.A.E.) */ + APP_USBD_SUBLANG_ARABIC_BAHRAIN = APP_USB_SUBLANG_DEF(0x15U), /**< Arabic (Bahrain) */ + APP_USBD_SUBLANG_ARABIC_QATAR = APP_USB_SUBLANG_DEF(0x16U), /**< Arabic (Qatar) */ + APP_USBD_SUBLANG_AZERI_CYRILLIC = APP_USB_SUBLANG_DEF(0x01U), /**< Azeri (Cyrillic) */ + APP_USBD_SUBLANG_AZERI_LATIN = APP_USB_SUBLANG_DEF(0x02U), /**< Azeri (Latin) */ + APP_USBD_SUBLANG_CHINESE_TRADITIONAL = APP_USB_SUBLANG_DEF(0x01U), /**< Chinese (Traditional) */ + APP_USBD_SUBLANG_CHINESE_SIMPLIFIED = APP_USB_SUBLANG_DEF(0x02U), /**< Chinese (Simplified) */ + APP_USBD_SUBLANG_CHINESE_HONGKONG = APP_USB_SUBLANG_DEF(0x03U), /**< Chinese (Hong Kong SAR, PRC) */ + APP_USBD_SUBLANG_CHINESE_SINGAPORE = APP_USB_SUBLANG_DEF(0x04U), /**< Chinese (Singapore) */ + APP_USBD_SUBLANG_CHINESE_MACAU = APP_USB_SUBLANG_DEF(0x05U), /**< Chinese (Macau SAR) */ + APP_USBD_SUBLANG_DUTCH = APP_USB_SUBLANG_DEF(0x01U), /**< Dutch */ + APP_USBD_SUBLANG_DUTCH_BELGIAN = APP_USB_SUBLANG_DEF(0x02U), /**< Dutch (Belgian) */ + APP_USBD_SUBLANG_ENGLISH_US = APP_USB_SUBLANG_DEF(0x01U), /**< English (US) */ + APP_USBD_SUBLANG_ENGLISH_UK = APP_USB_SUBLANG_DEF(0x02U), /**< English (UK) */ + APP_USBD_SUBLANG_ENGLISH_AUS = APP_USB_SUBLANG_DEF(0x03U), /**< English (Australian) */ + APP_USBD_SUBLANG_ENGLISH_CAN = APP_USB_SUBLANG_DEF(0x04U), /**< English (Canadian) */ + APP_USBD_SUBLANG_ENGLISH_NZ = APP_USB_SUBLANG_DEF(0x05U), /**< English (New Zealand) */ + APP_USBD_SUBLANG_ENGLISH_EIRE = APP_USB_SUBLANG_DEF(0x06U), /**< English (Ireland) */ + APP_USBD_SUBLANG_ENGLISH_SOUTH_AFRICA = APP_USB_SUBLANG_DEF(0x07U), /**< English (South Africa) */ + APP_USBD_SUBLANG_ENGLISH_JAMAICA = APP_USB_SUBLANG_DEF(0x08U), /**< English (Jamaica) */ + APP_USBD_SUBLANG_ENGLISH_CARIBBEAN = APP_USB_SUBLANG_DEF(0x09U), /**< English (Caribbean) */ + APP_USBD_SUBLANG_ENGLISH_BELIZE = APP_USB_SUBLANG_DEF(0x0aU), /**< English (Belize) */ + APP_USBD_SUBLANG_ENGLISH_TRINIDAD = APP_USB_SUBLANG_DEF(0x0bU), /**< English (Trinidad) */ + APP_USBD_SUBLANG_ENGLISH_PHILIPPINES = APP_USB_SUBLANG_DEF(0x0cU), /**< English (Zimbabwe) */ + APP_USBD_SUBLANG_ENGLISH_ZIMBABWE = APP_USB_SUBLANG_DEF(0x0dU), /**< English (Philippines) */ + APP_USBD_SUBLANG_FRENCH = APP_USB_SUBLANG_DEF(0x01U), /**< French */ + APP_USBD_SUBLANG_FRENCH_BELGIAN = APP_USB_SUBLANG_DEF(0x02U), /**< French (Belgian) */ + APP_USBD_SUBLANG_FRENCH_CANADIAN = APP_USB_SUBLANG_DEF(0x03U), /**< French (Canadian) */ + APP_USBD_SUBLANG_FRENCH_SWISS = APP_USB_SUBLANG_DEF(0x04U), /**< French (Switzerland) */ + APP_USBD_SUBLANG_FRENCH_LUXEMBOURG = APP_USB_SUBLANG_DEF(0x05U), /**< French (Luxembourg) */ + APP_USBD_SUBLANG_FRENCH_MONACO = APP_USB_SUBLANG_DEF(0x06U), /**< French (Monaco) */ + APP_USBD_SUBLANG_GERMAN = APP_USB_SUBLANG_DEF(0x01U), /**< German */ + APP_USBD_SUBLANG_GERMAN_SWISS = APP_USB_SUBLANG_DEF(0x02U), /**< German (Switzerland) */ + APP_USBD_SUBLANG_GERMAN_AUSTRIAN = APP_USB_SUBLANG_DEF(0x03U), /**< German (Austria) */ + APP_USBD_SUBLANG_GERMAN_LUXEMBOURG = APP_USB_SUBLANG_DEF(0x04U), /**< German (Luxembourg) */ + APP_USBD_SUBLANG_GERMAN_LIECHTENSTEIN = APP_USB_SUBLANG_DEF(0x05U), /**< German (Liechtenstein) */ + APP_USBD_SUBLANG_ITALIAN = APP_USB_SUBLANG_DEF(0x01U), /**< Italian */ + APP_USBD_SUBLANG_ITALIAN_SWISS = APP_USB_SUBLANG_DEF(0x02U), /**< Italian (Switzerland) */ + APP_USBD_SUBLANG_KASHMIRI_INDIA = APP_USB_SUBLANG_DEF(0x02U), /**< Kashmiri (India) */ + APP_USBD_SUBLANG_KOREAN = APP_USB_SUBLANG_DEF(0x01U), /**< Korean */ + APP_USBD_SUBLANG_LITHUANIAN = APP_USB_SUBLANG_DEF(0x01U), /**< Lithuanian */ + APP_USBD_SUBLANG_MALAY_MALAYSIA = APP_USB_SUBLANG_DEF(0x01U), /**< Malay (Malaysia) */ + APP_USBD_SUBLANG_MALAY_BRUNEI_DARUSSALAM = APP_USB_SUBLANG_DEF(0x02U), /**< Malay (Brunei Darassalam) */ + APP_USBD_SUBLANG_NEPALI_INDIA = APP_USB_SUBLANG_DEF(0x02U), /**< Nepali (India) */ + APP_USBD_SUBLANG_NORWEGIAN_BOKMAL = APP_USB_SUBLANG_DEF(0x01U), /**< Norwegian (Bokmal) */ + APP_USBD_SUBLANG_NORWEGIAN_NYNORSK = APP_USB_SUBLANG_DEF(0x02U), /**< Norwegian (Nynorsk) */ + APP_USBD_SUBLANG_PORTUGUESE = APP_USB_SUBLANG_DEF(0x01U), /**< Portuguese */ + APP_USBD_SUBLANG_PORTUGUESE_BRAZILIAN = APP_USB_SUBLANG_DEF(0x02U), /**< Portuguese (Brazil) */ + APP_USBD_SUBLANG_SERBIAN_LATIN = APP_USB_SUBLANG_DEF(0x02U), /**< Serbian (Latin) */ + APP_USBD_SUBLANG_SERBIAN_CYRILLIC = APP_USB_SUBLANG_DEF(0x03U), /**< Serbian (Cyrillic) */ + APP_USBD_SUBLANG_SPANISH = APP_USB_SUBLANG_DEF(0x01U), /**< Spanish (Traditional) */ + APP_USBD_SUBLANG_SPANISH_MEXICAN = APP_USB_SUBLANG_DEF(0x02U), /**< Spanish (Mexican) */ + APP_USBD_SUBLANG_SPANISH_MODERN = APP_USB_SUBLANG_DEF(0x03U), /**< Spanish (Modern) */ + APP_USBD_SUBLANG_SPANISH_GUATEMALA = APP_USB_SUBLANG_DEF(0x04U), /**< Spanish (Guatemala) */ + APP_USBD_SUBLANG_SPANISH_COSTA_RICA = APP_USB_SUBLANG_DEF(0x05U), /**< Spanish (Costa Rica) */ + APP_USBD_SUBLANG_SPANISH_PANAMA = APP_USB_SUBLANG_DEF(0x06U), /**< Spanish (Panama) */ + APP_USBD_SUBLANG_SPANISH_DOMINICAN_REPUBLIC = APP_USB_SUBLANG_DEF(0x07U), /**< Spanish (Dominican Republic) */ + APP_USBD_SUBLANG_SPANISH_VENEZUELA = APP_USB_SUBLANG_DEF(0x08U), /**< Spanish (Venezuela) */ + APP_USBD_SUBLANG_SPANISH_COLOMBIA = APP_USB_SUBLANG_DEF(0x09U), /**< Spanish (Colombia) */ + APP_USBD_SUBLANG_SPANISH_PERU = APP_USB_SUBLANG_DEF(0x0aU), /**< Spanish (Peru) */ + APP_USBD_SUBLANG_SPANISH_ARGENTINA = APP_USB_SUBLANG_DEF(0x0bU), /**< Spanish (Argentina) */ + APP_USBD_SUBLANG_SPANISH_ECUADOR = APP_USB_SUBLANG_DEF(0x0cU), /**< Spanish (Ecuador) */ + APP_USBD_SUBLANG_SPANISH_CHILE = APP_USB_SUBLANG_DEF(0x0dU), /**< Spanish (Chile) */ + APP_USBD_SUBLANG_SPANISH_URUGUAY = APP_USB_SUBLANG_DEF(0x0eU), /**< Spanish (Uruguay) */ + APP_USBD_SUBLANG_SPANISH_PARAGUAY = APP_USB_SUBLANG_DEF(0x0fU), /**< Spanish (Paraguay) */ + APP_USBD_SUBLANG_SPANISH_BOLIVIA = APP_USB_SUBLANG_DEF(0x10U), /**< Spanish (Bolivia) */ + APP_USBD_SUBLANG_SPANISH_EL_SALVADOR = APP_USB_SUBLANG_DEF(0x11U), /**< Spanish (El Salvador) */ + APP_USBD_SUBLANG_SPANISH_HONDURAS = APP_USB_SUBLANG_DEF(0x12U), /**< Spanish (Honduras) */ + APP_USBD_SUBLANG_SPANISH_NICARAGUA = APP_USB_SUBLANG_DEF(0x13U), /**< Spanish (Nicaragua) */ + APP_USBD_SUBLANG_SPANISH_PUERTO_RICO = APP_USB_SUBLANG_DEF(0x14U), /**< Spanish (Puerto Rico) */ + APP_USBD_SUBLANG_SWEDISH = APP_USB_SUBLANG_DEF(0x01U), /**< Swedish */ + APP_USBD_SUBLANG_SWEDISH_FINLAND = APP_USB_SUBLANG_DEF(0x02U), /**< Swedish (Finland) */ + APP_USBD_SUBLANG_URDU_PAKISTAN = APP_USB_SUBLANG_DEF(0x01U), /**< Urdu (Pakistan) */ + APP_USBD_SUBLANG_URDU_INDIA = APP_USB_SUBLANG_DEF(0x02U), /**< Urdu (India) */ + APP_USBD_SUBLANG_UZBEK_LATIN = APP_USB_SUBLANG_DEF(0x01U), /**< Uzbek (Latin) */ + APP_USBD_SUBLANG_UZBEK_CYRILLIC = APP_USB_SUBLANG_DEF(0x02U), /**< Uzbek (Cyrillic) */ + APP_USBD_SUBLANG_HID_USAGE_DATA_DESCRIPTOR = APP_USB_SUBLANG_DEF(0x01U), /**< HID (Usage Data Descriptor) */ + APP_USBD_SUBLANG_HID_VENDOR_DEFINED_1 = APP_USB_SUBLANG_DEF(0x3cU), /**< HID (Vendor Defined 1) */ + APP_USBD_SUBLANG_HID_VENDOR_DEFINED_2 = APP_USB_SUBLANG_DEF(0x3dU), /**< HID (Vendor Defined 2) */ + APP_USBD_SUBLANG_HID_VENDOR_DEFINED_3 = APP_USB_SUBLANG_DEF(0x3eU), /**< HID (Vendor Defined 3) */ + APP_USBD_SUBLANG_HID_VENDOR_DEFINED_4 = APP_USB_SUBLANG_DEF(0x3fU), /**< HID (Vendor Defined 4) */ +} app_usbd_langid_sub_t; + +/** + * @brief LANGID variable. + * + * The LANGID value is composed of: + * - 10 bits (9-0) of Primary Language Identifier, + * - 6 bits (15-10) of Sublanguage Identifier. + * + * @sa app_usbd_langid_primary_t + * @sa app_usbd_langid_sub_t + */ +typedef uint16_t app_usbd_langid_t; + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_LANGID_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_request.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_request.h index a6918a89b..27adcf140 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_request.h +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_request.h @@ -1,356 +1,356 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef APP_USBD_REQUEST_H__ -#define APP_USBD_REQUEST_H__ - -#include "sdk_common.h" -#include "nrf.h" -#include "nrf_drv_usbd.h" -#include "app_usbd_descriptor.h" -#include "app_util_platform.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Compiler support for anonymous unions */ -ANON_UNIONS_ENABLE; - -#pragma pack(push, 1) - -/** - * @defgroup app_usbd_request USB standard requests - * @ingroup app_usbd - * - * @brief @tagAPI52840 Module with types definitions used for standard requests processing. - * @{ - */ - -/** - * @brief Recipient bit-field in request type. - * - * Bits 4...0 - */ -#define APP_USBD_SETUP_REQ_BF_REC BF_CX(5, 0) - -/** - * @brief Type bit-field in request type. - * - * Bits 6...5 - */ -#define APP_USBD_SETUP_REQ_BF_TYP BF_CX(2, 5) - -/** - * @brief Direction bit-field in request type. - * - * Bit 7 - */ -#define APP_USBD_SETUP_REQ_BF_DIR BF_CX(1, 7) - -/** - * @brief Recipient enumerator. - * - * @note It is part of @ref app_usbd_setup_reqtype_t variable type. - */ -typedef enum { - APP_USBD_SETUP_REQREC_DEVICE = 0x0, /**< The whole device is a request target */ - APP_USBD_SETUP_REQREC_INTERFACE = 0x1, /**< Selected interface is a request target */ - APP_USBD_SETUP_REQREC_ENDPOINT = 0x2, /**< Selected endpoint is a request target */ - APP_USBD_SETUP_REQREC_OTHER = 0x3 /**< Other element is a request target */ -} app_usbd_setup_reqrec_t; - -/** - * @brief Request type enumerator. - * - * @note It is part of @ref app_usbd_setup_reqtype_t variable type. - */ -typedef enum { - APP_USBD_SETUP_REQTYPE_STD = 0x0, /**< Standard request */ - APP_USBD_SETUP_REQTYPE_CLASS = 0x1, /**< Class specific request */ - APP_USBD_SETUP_REQTYPE_VENDOR = 0x2 /**< Vendor specific request */ -} app_usbd_setup_reqtype_t; - -/** - * @brief Direction of setup command. - * - * @note It is part of @ref app_usbd_setup_reqtype_t variable type. - */ -typedef enum { - APP_USBD_SETUP_REQDIR_OUT = 0x0, /**< Host to device */ - APP_USBD_SETUP_REQDIR_IN = 0x1, /**< Device to host */ -} app_usbd_setup_reqdir_t; - - -/** - * @brief Standard requests. - * - * Enumerator for standard requests values. - */ -typedef enum { - APP_USBD_SETUP_STDREQ_GET_STATUS = 0x00, /**< - * Targets: Device, Interface, Endpoint - * Expected SETUP frame format: - * - wValue: Zero - * - wIndex: Zero, (lb): Interface or Endpoint - * - wLength: 2 - * - Data:2 bytes of data, depending on targets - * - Device: - * - D15..D2: Reserved (Reset to zero) - * - D1: Remove Wakeup - * - D0: Self Powered - * - Interface: - * - D15..D0: Reserved (Reset to zero) - * - Endpoint: - * - D15..D1: Reserved (Reset to zero) - * - D0: Halt - */ - APP_USBD_SETUP_STDREQ_CLEAR_FEATURE = 0x01, /**< - * Targets: Device, Interface, Endpoint - * Expected SETUP frame format: - * - wValue: Feature selector (@ref app_usbd_setup_stdfeature_t) - * - wIndex: Zero, Interface or Endpoint - * - wLength: 0 - * - Data: None - */ - APP_USBD_SETUP_STDREQ_SET_FEATURE = 0x03, /**< - * Targets: Device, Interface, Endpoint - * Expected SETUP frame format: - * - wValue: Feature selector (@ref app_usbd_setup_stdfeature_t) - * - wIndex: Zero, Interface or Endpoint - * - wLength: 0 - * - Data: None - */ - APP_USBD_SETUP_STDREQ_SET_ADDRESS = 0x05, /**< - * @note This SETUP request is processed in hardware. - * Use it only to mark current USB state. - * - * Targets: Device - * Expected SETUP frame format: - * - wValue: New device address - * - wIndex: 0 - * - wLength: 0 - * - Data: None - */ - APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR = 0x06, /**< - * Targets: Device - * - wValue: (hb): Descriptor Type and (lb): Descriptor Index - * - wIndex: Zero of Language ID - * - wLength: Descriptor Length - * - Data: Descriptor - */ - APP_USBD_SETUP_STDREQ_SET_DESCRIPTOR = 0x07, /**< - * Not supported - Stall when called. - */ - APP_USBD_SETUP_STDREQ_GET_CONFIGURATION = 0x08, /**< - * Target: Device - * Expected SETUP frame format: - * - wValue: 0 - * - wIndex: 0 - * - wLength: 1 - * - Data: Configuration value - */ - APP_USBD_SETUP_STDREQ_SET_CONFIGURATION = 0x09, /**< - * Target: Device - * Expected SETUP frame format: - * - wValue: (lb): Configuration value - * - wIndex: 0 - * - wLength: 0 - * - Data: None - */ - APP_USBD_SETUP_STDREQ_GET_INTERFACE = 0x0A, /**< - * Target: Interface - * Expected SETUP frame format: - * - wValue: 0 - * - wIndex: Interface - * - wLength: 1 - * - Data: Alternate setting - */ - APP_USBD_SETUP_STDREQ_SET_INTERFACE = 0x0B, /**< - * Target: Interface - * Expected SETUP frame format: - * - wValue: Alternate setting - * - wIndex: Interface - * - wLength: 0 - * - Data: None - */ - APP_USBD_SETUP_STDREQ_SYNCH_FRAME = 0x0C /**< - * Target: Endpoint - * Expected SETUP frame format: - * - wValue: 0 - * - wIndex: Endpoint - * - wLength: 2 - * - Data: Frame Number - * - * @note - * This request is used only in connection with isochronous endpoints. - * This is rarely used and probably we would not need to support it. - */ -} app_usbd_setup_stdrequest_t; - -/** - * @brief Standard feature selectors. - * - * Standard features that may be disabled or enabled by - * @ref APP_USBD_SETUP_STDREQ_CLEAR_FEATURE or @ref APP_USBD_SETUP_STDREQ_SET_FEATURE - */ -typedef enum { - APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP = 1, /**< - * Remote wakeup feature. - * Target: Device only - */ - APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT = 0, /**< - * Stall or clear the endpoint. - * Target: Endpoint different than default (0) - */ - APP_USBD_SETUP_STDFEATURE_TEST_MODE = 2 /**< - * Upstream port test mode. - * Power has to be cycled to exit test mode. - * This feature cannot be cleared. - * - * Target: Device only - * - * @note - * It should only be supported by HighSpeed capable devices. - * Not supported in this library. - */ -} app_usbd_setup_stdfeature_t; - - -/** - * @brief Universal way to access 16 bit values and its parts. - */ -typedef union { - uint16_t w; //!< 16 bit access - struct - { - uint8_t lb; //!< Low byte access - uint8_t hb; //!< High byte access - }; -} app_usbd_setup_w_t; - -/** - * @brief Internal redefinition of setup structure. - * - * Redefinition of the structure to simplify changes in the future - * if required - app_usbd API would present setup data using app_usbd_setup_t. - * - * The structure layout is always the same like @ref nrf_drv_usbd_setup_t - */ -typedef struct { - uint8_t bmRequestType; //!< Setup type bitfield - uint8_t bmRequest; //!< One of @ref app_usbd_setup_stdrequest_t values or class dependent one. - app_usbd_setup_w_t wValue; //!< byte 2, 3 - app_usbd_setup_w_t wIndex; //!< byte 4, 5 - app_usbd_setup_w_t wLength; //!< byte 6, 7 -} app_usbd_setup_t; - -#pragma pack(pop) - - -/** - * @brief Extract recipient from request type. - * - * @param[in] bmRequestType - * - * @return Extracted recipient field from request type value. - */ -static inline app_usbd_setup_reqrec_t app_usbd_setup_req_rec(uint8_t bmRequestType) -{ - return (app_usbd_setup_reqrec_t)BF_CX_GET(bmRequestType, APP_USBD_SETUP_REQ_BF_REC); -} - -/** - * @brief Extract type from request type. - * - * @param[in] bmRequestType - * - * @return Extracted type field from request type value. - */ -static inline app_usbd_setup_reqtype_t app_usbd_setup_req_typ(uint8_t bmRequestType) -{ - return (app_usbd_setup_reqtype_t)BF_CX_GET(bmRequestType, APP_USBD_SETUP_REQ_BF_TYP); -} - - -/** - * @brief Extract direction from request type. - * - * @param[in] bmRequestType - * - * @return Extracted direction field from request type value. - */ -static inline app_usbd_setup_reqdir_t app_usbd_setup_req_dir(uint8_t bmRequestType) -{ - return (app_usbd_setup_reqdir_t)BF_CX_GET(bmRequestType, APP_USBD_SETUP_REQ_BF_DIR); -} - -/** - * @brief Make request type value. - * - * @param[in] rec Recipient. - * @param[in] typ Request type. - * @param[in] dir Direction. - * - * @return Assembled request type value. - */ -static inline uint8_t app_usbd_setup_req_val(app_usbd_setup_reqrec_t rec, - app_usbd_setup_reqtype_t typ, - app_usbd_setup_reqdir_t dir) -{ - uint32_t bmRequestType = ( - BF_CX_VAL(rec, APP_USBD_SETUP_REQ_BF_REC) | - BF_CX_VAL(typ, APP_USBD_SETUP_REQ_BF_TYP) | - BF_CX_VAL(dir, APP_USBD_SETUP_REQ_BF_DIR) - ); - - ASSERT(bmRequestType < 256U); - return (uint8_t)bmRequestType; -} - - -ANON_UNIONS_DISABLE; -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_REQUEST_H__ */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef APP_USBD_REQUEST_H__ +#define APP_USBD_REQUEST_H__ + +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_drv_usbd.h" +#include "app_usbd_descriptor.h" +#include "app_util_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Compiler support for anonymous unions */ +ANON_UNIONS_ENABLE; + +#pragma pack(push, 1) + +/** + * @defgroup app_usbd_request USB standard requests + * @ingroup app_usbd + * + * @brief @tagAPI52840 Module with types definitions used for standard requests processing. + * @{ + */ + +/** + * @brief Recipient bit-field in request type. + * + * Bits 4...0 + */ +#define APP_USBD_SETUP_REQ_BF_REC BF_CX(5, 0) + +/** + * @brief Type bit-field in request type. + * + * Bits 6...5 + */ +#define APP_USBD_SETUP_REQ_BF_TYP BF_CX(2, 5) + +/** + * @brief Direction bit-field in request type. + * + * Bit 7 + */ +#define APP_USBD_SETUP_REQ_BF_DIR BF_CX(1, 7) + +/** + * @brief Recipient enumerator. + * + * @note It is part of @ref app_usbd_setup_reqtype_t variable type. + */ +typedef enum { + APP_USBD_SETUP_REQREC_DEVICE = 0x0, /**< The whole device is a request target */ + APP_USBD_SETUP_REQREC_INTERFACE = 0x1, /**< Selected interface is a request target */ + APP_USBD_SETUP_REQREC_ENDPOINT = 0x2, /**< Selected endpoint is a request target */ + APP_USBD_SETUP_REQREC_OTHER = 0x3 /**< Other element is a request target */ +} app_usbd_setup_reqrec_t; + +/** + * @brief Request type enumerator. + * + * @note It is part of @ref app_usbd_setup_reqtype_t variable type. + */ +typedef enum { + APP_USBD_SETUP_REQTYPE_STD = 0x0, /**< Standard request */ + APP_USBD_SETUP_REQTYPE_CLASS = 0x1, /**< Class specific request */ + APP_USBD_SETUP_REQTYPE_VENDOR = 0x2 /**< Vendor specific request */ +} app_usbd_setup_reqtype_t; + +/** + * @brief Direction of setup command. + * + * @note It is part of @ref app_usbd_setup_reqtype_t variable type. + */ +typedef enum { + APP_USBD_SETUP_REQDIR_OUT = 0x0, /**< Host to device */ + APP_USBD_SETUP_REQDIR_IN = 0x1, /**< Device to host */ +} app_usbd_setup_reqdir_t; + + +/** + * @brief Standard requests. + * + * Enumerator for standard requests values. + */ +typedef enum { + APP_USBD_SETUP_STDREQ_GET_STATUS = 0x00, /**< + * Targets: Device, Interface, Endpoint + * Expected SETUP frame format: + * - wValue: Zero + * - wIndex: Zero, (lb): Interface or Endpoint + * - wLength: 2 + * - Data:2 bytes of data, depending on targets + * - Device: + * - D15..D2: Reserved (Reset to zero) + * - D1: Remove Wakeup + * - D0: Self Powered + * - Interface: + * - D15..D0: Reserved (Reset to zero) + * - Endpoint: + * - D15..D1: Reserved (Reset to zero) + * - D0: Halt + */ + APP_USBD_SETUP_STDREQ_CLEAR_FEATURE = 0x01, /**< + * Targets: Device, Interface, Endpoint + * Expected SETUP frame format: + * - wValue: Feature selector (@ref app_usbd_setup_stdfeature_t) + * - wIndex: Zero, Interface or Endpoint + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_SET_FEATURE = 0x03, /**< + * Targets: Device, Interface, Endpoint + * Expected SETUP frame format: + * - wValue: Feature selector (@ref app_usbd_setup_stdfeature_t) + * - wIndex: Zero, Interface or Endpoint + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_SET_ADDRESS = 0x05, /**< + * @note This SETUP request is processed in hardware. + * Use it only to mark current USB state. + * + * Targets: Device + * Expected SETUP frame format: + * - wValue: New device address + * - wIndex: 0 + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR = 0x06, /**< + * Targets: Device + * - wValue: (hb): Descriptor Type and (lb): Descriptor Index + * - wIndex: Zero of Language ID + * - wLength: Descriptor Length + * - Data: Descriptor + */ + APP_USBD_SETUP_STDREQ_SET_DESCRIPTOR = 0x07, /**< + * Not supported - Stall when called. + */ + APP_USBD_SETUP_STDREQ_GET_CONFIGURATION = 0x08, /**< + * Target: Device + * Expected SETUP frame format: + * - wValue: 0 + * - wIndex: 0 + * - wLength: 1 + * - Data: Configuration value + */ + APP_USBD_SETUP_STDREQ_SET_CONFIGURATION = 0x09, /**< + * Target: Device + * Expected SETUP frame format: + * - wValue: (lb): Configuration value + * - wIndex: 0 + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_GET_INTERFACE = 0x0A, /**< + * Target: Interface + * Expected SETUP frame format: + * - wValue: 0 + * - wIndex: Interface + * - wLength: 1 + * - Data: Alternate setting + */ + APP_USBD_SETUP_STDREQ_SET_INTERFACE = 0x0B, /**< + * Target: Interface + * Expected SETUP frame format: + * - wValue: Alternate setting + * - wIndex: Interface + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_SYNCH_FRAME = 0x0C /**< + * Target: Endpoint + * Expected SETUP frame format: + * - wValue: 0 + * - wIndex: Endpoint + * - wLength: 2 + * - Data: Frame Number + * + * @note + * This request is used only in connection with isochronous endpoints. + * This is rarely used and probably we would not need to support it. + */ +} app_usbd_setup_stdrequest_t; + +/** + * @brief Standard feature selectors. + * + * Standard features that may be disabled or enabled by + * @ref APP_USBD_SETUP_STDREQ_CLEAR_FEATURE or @ref APP_USBD_SETUP_STDREQ_SET_FEATURE + */ +typedef enum { + APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP = 1, /**< + * Remote wakeup feature. + * Target: Device only + */ + APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT = 0, /**< + * Stall or clear the endpoint. + * Target: Endpoint different than default (0) + */ + APP_USBD_SETUP_STDFEATURE_TEST_MODE = 2 /**< + * Upstream port test mode. + * Power has to be cycled to exit test mode. + * This feature cannot be cleared. + * + * Target: Device only + * + * @note + * It should only be supported by HighSpeed capable devices. + * Not supported in this library. + */ +} app_usbd_setup_stdfeature_t; + + +/** + * @brief Universal way to access 16 bit values and its parts. + */ +typedef union { + uint16_t w; //!< 16 bit access + struct + { + uint8_t lb; //!< Low byte access + uint8_t hb; //!< High byte access + }; +} app_usbd_setup_w_t; + +/** + * @brief Internal redefinition of setup structure. + * + * Redefinition of the structure to simplify changes in the future + * if required - app_usbd API would present setup data using app_usbd_setup_t. + * + * The structure layout is always the same like @ref nrf_drv_usbd_setup_t + */ +typedef struct { + uint8_t bmRequestType; //!< Setup type bitfield + uint8_t bmRequest; //!< One of @ref app_usbd_setup_stdrequest_t values or class dependent one. + app_usbd_setup_w_t wValue; //!< byte 2, 3 + app_usbd_setup_w_t wIndex; //!< byte 4, 5 + app_usbd_setup_w_t wLength; //!< byte 6, 7 +} app_usbd_setup_t; + +#pragma pack(pop) + + +/** + * @brief Extract recipient from request type. + * + * @param[in] bmRequestType + * + * @return Extracted recipient field from request type value. + */ +static inline app_usbd_setup_reqrec_t app_usbd_setup_req_rec(uint8_t bmRequestType) +{ + return (app_usbd_setup_reqrec_t)BF_CX_GET(bmRequestType, APP_USBD_SETUP_REQ_BF_REC); +} + +/** + * @brief Extract type from request type. + * + * @param[in] bmRequestType + * + * @return Extracted type field from request type value. + */ +static inline app_usbd_setup_reqtype_t app_usbd_setup_req_typ(uint8_t bmRequestType) +{ + return (app_usbd_setup_reqtype_t)BF_CX_GET(bmRequestType, APP_USBD_SETUP_REQ_BF_TYP); +} + + +/** + * @brief Extract direction from request type. + * + * @param[in] bmRequestType + * + * @return Extracted direction field from request type value. + */ +static inline app_usbd_setup_reqdir_t app_usbd_setup_req_dir(uint8_t bmRequestType) +{ + return (app_usbd_setup_reqdir_t)BF_CX_GET(bmRequestType, APP_USBD_SETUP_REQ_BF_DIR); +} + +/** + * @brief Make request type value. + * + * @param[in] rec Recipient. + * @param[in] typ Request type. + * @param[in] dir Direction. + * + * @return Assembled request type value. + */ +static inline uint8_t app_usbd_setup_req_val(app_usbd_setup_reqrec_t rec, + app_usbd_setup_reqtype_t typ, + app_usbd_setup_reqdir_t dir) +{ + uint32_t bmRequestType = ( + BF_CX_VAL(rec, APP_USBD_SETUP_REQ_BF_REC) | + BF_CX_VAL(typ, APP_USBD_SETUP_REQ_BF_TYP) | + BF_CX_VAL(dir, APP_USBD_SETUP_REQ_BF_DIR) + ); + + ASSERT(bmRequestType < 256U); + return (uint8_t)bmRequestType; +} + + +ANON_UNIONS_DISABLE; +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_REQUEST_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_serial_num.c b/third_party/NordicSemiconductor/libraries/usb/app_usbd_serial_num.c index 548a2fab7..aff65035c 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_serial_num.c +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_serial_num.c @@ -1,84 +1,84 @@ -/** - * Copyright (c) 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "app_usbd_serial_num.h" - -#include -#include -#include -#include -#include "app_usbd.h" - -#define SERIAL_NUMBER_STRING_SIZE (12) - -/**@brief Serial number generated. - * - * Serial number generated by the @ref serial_number_string_create function. - */ -uint8_t g_extern_serial_number[SERIAL_NUMBER_STRING_SIZE + 1]; - - -/**@brief Function for creating the serial number string from a regular C string. - * - * @param[in] p_serial_number_string The serial number string. Must be terminated with \0. - */ -static void string_create(char * p_serial_number_string) -{ - - for (uint32_t i = 0; i < strlen(p_serial_number_string); i++) - { - g_extern_serial_number[i] = (uint8_t)p_serial_number_string[i]; - } -} - - -void app_usbd_serial_num_generate(void) -{ - char serial_number_string[SERIAL_NUMBER_STRING_SIZE + 1]; - const uint16_t serial_num_high_bytes = (uint16_t)NRF_FICR->DEVICEADDR[1] | 0xC000; // The masking makes the address match the Random Static BLE address. - const uint32_t serial_num_low_bytes = NRF_FICR->DEVICEADDR[0]; - - (void)snprintf(serial_number_string, - SERIAL_NUMBER_STRING_SIZE + 1, - "%04"PRIX16"%08"PRIX32, - serial_num_high_bytes, - serial_num_low_bytes); - - string_create(serial_number_string); -} +/** + * Copyright (c) 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "app_usbd_serial_num.h" + +#include +#include +#include +#include +#include "app_usbd.h" + +#define SERIAL_NUMBER_STRING_SIZE (12) + +/**@brief Serial number generated. + * + * Serial number generated by the @ref serial_number_string_create function. + */ +uint8_t g_extern_serial_number[SERIAL_NUMBER_STRING_SIZE + 1]; + + +/**@brief Function for creating the serial number string from a regular C string. + * + * @param[in] p_serial_number_string The serial number string. Must be terminated with \0. + */ +static void string_create(char * p_serial_number_string) +{ + + for (uint32_t i = 0; i < strlen(p_serial_number_string); i++) + { + g_extern_serial_number[i] = (uint8_t)p_serial_number_string[i]; + } +} + + +void app_usbd_serial_num_generate(void) +{ + char serial_number_string[SERIAL_NUMBER_STRING_SIZE + 1]; + const uint16_t serial_num_high_bytes = (uint16_t)NRF_FICR->DEVICEADDR[1] | 0xC000; // The masking makes the address match the Random Static BLE address. + const uint32_t serial_num_low_bytes = NRF_FICR->DEVICEADDR[0]; + + (void)snprintf(serial_number_string, + SERIAL_NUMBER_STRING_SIZE + 1, + "%04"PRIX16"%08"PRIX32, + serial_num_high_bytes, + serial_num_low_bytes); + + string_create(serial_number_string); +} diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_serial_num.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_serial_num.h index 6c0e91d40..11d4f886b 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_serial_num.h +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_serial_num.h @@ -1,75 +1,75 @@ -/** - * Copyright (c) 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef APP_USBD_SERIAL_NUM_H__ -#define APP_USBD_SERIAL_NUM_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup app_usbd_serial_num USBD serial number generator - * @ingroup app_usbd - * - * @brief @tagAPI52840 Generate a standard USB serial number that is unique for each device. - * @{ - */ - -/**@brief Function for generating a default serial number string based on FIRC->DEVICEADDR. - * - * After calling this function, the serial number is ready for the USB driver. - * - * The generated serial number shows up as a 12-hexidecimal-digit string with no delimiters - * (e.g 123456ABCDEF). The byte string is also printed on the PCA10059 dongle. It is also used as - * the default advertising address in the SoftDevice. - */ -void app_usbd_serial_num_generate(void); - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif // APP_USBD_SERIAL_NUM_H__ +/** + * Copyright (c) 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef APP_USBD_SERIAL_NUM_H__ +#define APP_USBD_SERIAL_NUM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup app_usbd_serial_num USBD serial number generator + * @ingroup app_usbd + * + * @brief @tagAPI52840 Generate a standard USB serial number that is unique for each device. + * @{ + */ + +/**@brief Function for generating a default serial number string based on FIRC->DEVICEADDR. + * + * After calling this function, the serial number is ready for the USB driver. + * + * The generated serial number shows up as a 12-hexidecimal-digit string with no delimiters + * (e.g 123456ABCDEF). The byte string is also printed on the PCA10059 dongle. It is also used as + * the default advertising address in the SoftDevice. + */ +void app_usbd_serial_num_generate(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // APP_USBD_SERIAL_NUM_H__ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.c b/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.c index 4fd78e425..c0c3fe73d 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.c +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.c @@ -1,295 +1,295 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_config.h" -#if APP_USBD_ENABLED -#include "app_usbd_string_desc.h" -#include "app_usbd_langid.h" -#include "app_usbd_core.h" -#include "nordic_common.h" -#include "utf.h" - -/** - * @defgroup app_usbd_string_desc - * @ingroup app_usbd - * - * USBD string descriptor management - * @{ - */ - -/** - * @brief Array with language identifiers. - * - * This array is used to search the proper string for the selected language. - */ -static uint16_t const m_langids[] = { APP_USBD_STRINGS_LANGIDS }; - -/** - * @brief Language ID descriptor. - * - * Language. - */ - - -/** - * @brief Mnemonics for the string positions in the array. - * - * The mnemonics for the indexes of the strings inside the string array. - */ -enum { - APP_USBD_STRING_ID_LANGIDS_ARRAY_POS = 0, /**< Supported language identifiers. */ - -#if (APP_USBD_STRING_ID_MANUFACTURER != 0) - APP_USBD_STRING_ID_MANUFACTURER_ARRAY_POS, /**< Manufacturer name. */ -#endif // (APP_USBD_STRING_ID_MANUFACTURER != 0) - -#if (APP_USBD_STRING_ID_PRODUCT != 0) - APP_USBD_STRING_ID_PRODUCT_ARRAY_POS, /**< Product name. */ -#endif // (APP_USBD_STRING_ID_PRODUCT != 0) - -#if (APP_USBD_STRING_ID_SERIAL != 0) - APP_USBD_STRING_ID_SERIAL_ARRAY_POS, /**< Serial number. */ -#endif // (APP_USBD_STRING_ID_SERIAL != 0) - -#if (APP_USBD_STRING_ID_CONFIGURATION != 0) - APP_USBD_STRING_ID_CONFIGURATION_ARRAY_POS, /**< Configuration string. */ -#endif // (APP_USBD_STRING_ID_CONFIGURATION != 0) - -#define X(mnemonic, str_idx, ...) CONCAT_2(mnemonic, _ARRAY_POS), - APP_USBD_STRINGS_USER -#undef X -}; - -/** - * @brief String index into internal array index conversion table. - * - * The array that transforms the USB string indexes into internal array position. - * @note Value 0 is used to mark non-existing string. - */ -static uint8_t const m_string_translation[APP_USBD_STRING_ID_CNT] = -{ - [APP_USBD_STRING_ID_LANGIDS] = APP_USBD_STRING_ID_LANGIDS_ARRAY_POS, - -#if (APP_USBD_STRING_ID_MANUFACTURER != 0) - [APP_USBD_STRING_ID_MANUFACTURER] = APP_USBD_STRING_ID_MANUFACTURER_ARRAY_POS, -#endif // (APP_USBD_STRING_ID_MANUFACTURER != 0) - -#if (APP_USBD_STRING_ID_PRODUCT != 0) - [APP_USBD_STRING_ID_PRODUCT] = APP_USBD_STRING_ID_PRODUCT_ARRAY_POS, -#endif // (APP_USBD_STRING_ID_PRODUCT != 0) - -#if (APP_USBD_STRING_ID_SERIAL != 0) - [APP_USBD_STRING_ID_SERIAL] = APP_USBD_STRING_ID_SERIAL_ARRAY_POS, -#endif // (APP_USBD_STRING_ID_SERIAL != 0) - -#if (APP_USBD_STRING_ID_CONFIGURATION != 0) - [APP_USBD_STRING_ID_CONFIGURATION] = APP_USBD_STRING_ID_CONFIGURATION_ARRAY_POS, -#endif // (APP_USBD_STRING_ID_CONFIGURATION != 0) - -#define X(mnemonic, str_idx, ...) [mnemonic] = CONCAT_2(mnemonic, _ARRAY_POS), - APP_USBD_STRINGS_USER -#undef X -}; - -#ifndef APP_USBD_STRINGS_MANUFACTURER_EXTERN -#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0 -#endif - -#if APP_USBD_STRINGS_MANUFACTURER_EXTERN -extern uint8_t APP_USBD_STRINGS_MANUFACTURER[]; -#endif - -#ifndef APP_USBD_STRINGS_PRODUCT_EXTERN -#define APP_USBD_STRINGS_PRODUCT_EXTERN 0 -#endif - -#if APP_USBD_STRINGS_PRODUCT_EXTERN -extern uint8_t APP_USBD_STRINGS_PRODUCT[]; -#endif - -#ifndef APP_USBD_STRING_SERIAL_EXTERN -#define APP_USBD_STRING_SERIAL_EXTERN 0 -#endif - -#if APP_USBD_STRING_SERIAL_EXTERN -extern uint8_t APP_USBD_STRING_SERIAL[]; -#endif - -#ifndef APP_USBD_STRING_CONFIGURATION_EXTERN -#define APP_USBD_STRING_CONFIGURATION_EXTERN 0 -#endif - -#if APP_USBD_STRING_CONFIGURATION_EXTERN -extern uint8_t APP_USBD_STRING_CONFIGURATION[]; -#endif - -/** - * @brief String descriptor table. - * */ -static uint8_t const * m_string_dsc[APP_USBD_STRING_ID_CNT][ARRAY_SIZE(m_langids)] = -{ - [APP_USBD_STRING_ID_LANGIDS_ARRAY_POS] = {APP_USBD_STRING_RAW16_DESC(APP_USBD_STRINGS_LANGIDS)}, - -#if (APP_USBD_STRING_ID_MANUFACTURER != 0) - [APP_USBD_STRING_ID_MANUFACTURER_ARRAY_POS] = { APP_USBD_STRINGS_MANUFACTURER }, -#endif // (APP_USBD_STRING_ID_MANUFACTURER != 0) - -#if (APP_USBD_STRING_ID_PRODUCT != 0) - [APP_USBD_STRING_ID_PRODUCT_ARRAY_POS] = { APP_USBD_STRINGS_PRODUCT }, -#endif // (APP_USBD_STRING_ID_PRODUCT != 0) - -#if (APP_USBD_STRING_ID_SERIAL != 0) - [APP_USBD_STRING_ID_SERIAL_ARRAY_POS] = { APP_USBD_STRING_SERIAL }, -#endif // (APP_USBD_STRING_ID_SERIAL != 0) - -#if (APP_USBD_STRING_ID_CONFIGURATION != 0) - [APP_USBD_STRING_ID_CONFIGURATION_ARRAY_POS] = { APP_USBD_STRINGS_CONFIGURATION }, -#endif // (APP_USBD_STRING_ID_CONFIGURATION != 0) - -#define X(mnemonic, str_idx, ...) [CONCAT_2(mnemonic, _ARRAY_POS)] = {__VA_ARGS__}, - APP_USBD_STRINGS_USER -#undef X -}; - -/** - * @brief Function for preparing UTF16 string descriptor. - * - * @param idx String descriptor ID. - * @param langid Language ID. - * - * @return Pointer to the string descriptor. - */ -static uint16_t * app_usbd_prepare_string(uint8_t idx, uint16_t langid) -{ - if (m_string_dsc[idx][langid][0] == 0x00) - { - return (uint16_t *) &(m_string_dsc[idx][langid][2]); - } - -#if ((APP_USBD_CONFIG_DESC_STRING_SIZE * 2) + 2) <= NRF_DRV_USBD_EPSIZE - uint16_t * string_buffer = app_usbd_core_setup_transfer_buff_get(NULL); -#else - static uint16_t string_buffer[APP_USBD_CONFIG_DESC_STRING_SIZE + 1]; - // + 1 element for string descriptor type and size -#endif - - uint8_t size = 0; - const uint8_t * p_pos = m_string_dsc[idx][langid]; - -#if APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED - size = utf8UTF16Count((char *) p_pos, 0); - ASSERT(size <= APP_USBD_CONFIG_DESC_STRING_SIZE); - - uint16_t * p_out = &(string_buffer[1]); - uint32_t rune; - - while (*p_pos != 0) - { - p_pos = (uint8_t *) utf8DecodeRune((char *) p_pos, 0, &rune); - p_out += utf16EncodeRune(rune, p_out); - } -#else - while(*p_pos != 0) - { - ASSERT(size < APP_USBD_CONFIG_DESC_STRING_SIZE); - ++size; - string_buffer[size] = *p_pos; - ++p_pos; - } -#endif - - // Descriptor size is length of the string times 2 bytes per character + 2 bytes for - // descriptor type and size. - string_buffer[0] = (0xff & (size * 2 + 2)) | ((uint16_t)APP_USBD_DESCRIPTOR_STRING) << 8; - - return string_buffer; -} - -uint16_t const * app_usbd_string_desc_get(uint8_t idx, uint16_t langid) -{ - /* LANGID string. */ - if (APP_USBD_STRING_ID_LANGIDS == idx) - { - return app_usbd_prepare_string(APP_USBD_STRING_ID_LANGIDS_ARRAY_POS, 0); - } - - /* Searching for the language. */ - uint8_t lang_idx = 0; - if (ARRAY_SIZE(m_langids) > 1) - { - while (m_langids[lang_idx] != langid) - { - ++lang_idx; - if (lang_idx >= ARRAY_SIZE(m_langids)) - { - return NULL; - } - } - } - - /* Get the string index in array. */ - if (idx >= ARRAY_SIZE(m_string_translation)) - { - return NULL; - } - - uint8_t str_pos = m_string_translation[idx]; - if (str_pos == 0) - { - return NULL; - } - - if ((ARRAY_SIZE(m_langids) > 1) && (lang_idx != 0)) - { - if (m_string_dsc[str_pos][lang_idx] == NULL) - { - lang_idx = 0; - } - } - - if (m_string_dsc[str_pos][lang_idx] == NULL) - { - return NULL; - } - - return app_usbd_prepare_string(str_pos, lang_idx); -} - -/** @} */ -#endif // APP_USBD_ENABLED +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_config.h" +#if APP_USBD_ENABLED +#include "app_usbd_string_desc.h" +#include "app_usbd_langid.h" +#include "app_usbd_core.h" +#include "nordic_common.h" +#include "utf.h" + +/** + * @defgroup app_usbd_string_desc + * @ingroup app_usbd + * + * USBD string descriptor management + * @{ + */ + +/** + * @brief Array with language identifiers. + * + * This array is used to search the proper string for the selected language. + */ +static uint16_t const m_langids[] = { APP_USBD_STRINGS_LANGIDS }; + +/** + * @brief Language ID descriptor. + * + * Language. + */ + + +/** + * @brief Mnemonics for the string positions in the array. + * + * The mnemonics for the indexes of the strings inside the string array. + */ +enum { + APP_USBD_STRING_ID_LANGIDS_ARRAY_POS = 0, /**< Supported language identifiers. */ + +#if (APP_USBD_STRING_ID_MANUFACTURER != 0) + APP_USBD_STRING_ID_MANUFACTURER_ARRAY_POS, /**< Manufacturer name. */ +#endif // (APP_USBD_STRING_ID_MANUFACTURER != 0) + +#if (APP_USBD_STRING_ID_PRODUCT != 0) + APP_USBD_STRING_ID_PRODUCT_ARRAY_POS, /**< Product name. */ +#endif // (APP_USBD_STRING_ID_PRODUCT != 0) + +#if (APP_USBD_STRING_ID_SERIAL != 0) + APP_USBD_STRING_ID_SERIAL_ARRAY_POS, /**< Serial number. */ +#endif // (APP_USBD_STRING_ID_SERIAL != 0) + +#if (APP_USBD_STRING_ID_CONFIGURATION != 0) + APP_USBD_STRING_ID_CONFIGURATION_ARRAY_POS, /**< Configuration string. */ +#endif // (APP_USBD_STRING_ID_CONFIGURATION != 0) + +#define X(mnemonic, str_idx, ...) CONCAT_2(mnemonic, _ARRAY_POS), + APP_USBD_STRINGS_USER +#undef X +}; + +/** + * @brief String index into internal array index conversion table. + * + * The array that transforms the USB string indexes into internal array position. + * @note Value 0 is used to mark non-existing string. + */ +static uint8_t const m_string_translation[APP_USBD_STRING_ID_CNT] = +{ + [APP_USBD_STRING_ID_LANGIDS] = APP_USBD_STRING_ID_LANGIDS_ARRAY_POS, + +#if (APP_USBD_STRING_ID_MANUFACTURER != 0) + [APP_USBD_STRING_ID_MANUFACTURER] = APP_USBD_STRING_ID_MANUFACTURER_ARRAY_POS, +#endif // (APP_USBD_STRING_ID_MANUFACTURER != 0) + +#if (APP_USBD_STRING_ID_PRODUCT != 0) + [APP_USBD_STRING_ID_PRODUCT] = APP_USBD_STRING_ID_PRODUCT_ARRAY_POS, +#endif // (APP_USBD_STRING_ID_PRODUCT != 0) + +#if (APP_USBD_STRING_ID_SERIAL != 0) + [APP_USBD_STRING_ID_SERIAL] = APP_USBD_STRING_ID_SERIAL_ARRAY_POS, +#endif // (APP_USBD_STRING_ID_SERIAL != 0) + +#if (APP_USBD_STRING_ID_CONFIGURATION != 0) + [APP_USBD_STRING_ID_CONFIGURATION] = APP_USBD_STRING_ID_CONFIGURATION_ARRAY_POS, +#endif // (APP_USBD_STRING_ID_CONFIGURATION != 0) + +#define X(mnemonic, str_idx, ...) [mnemonic] = CONCAT_2(mnemonic, _ARRAY_POS), + APP_USBD_STRINGS_USER +#undef X +}; + +#ifndef APP_USBD_STRINGS_MANUFACTURER_EXTERN +#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0 +#endif + +#if APP_USBD_STRINGS_MANUFACTURER_EXTERN +extern uint8_t APP_USBD_STRINGS_MANUFACTURER[]; +#endif + +#ifndef APP_USBD_STRINGS_PRODUCT_EXTERN +#define APP_USBD_STRINGS_PRODUCT_EXTERN 0 +#endif + +#if APP_USBD_STRINGS_PRODUCT_EXTERN +extern uint8_t APP_USBD_STRINGS_PRODUCT[]; +#endif + +#ifndef APP_USBD_STRING_SERIAL_EXTERN +#define APP_USBD_STRING_SERIAL_EXTERN 0 +#endif + +#if APP_USBD_STRING_SERIAL_EXTERN +extern uint8_t APP_USBD_STRING_SERIAL[]; +#endif + +#ifndef APP_USBD_STRING_CONFIGURATION_EXTERN +#define APP_USBD_STRING_CONFIGURATION_EXTERN 0 +#endif + +#if APP_USBD_STRING_CONFIGURATION_EXTERN +extern uint8_t APP_USBD_STRING_CONFIGURATION[]; +#endif + +/** + * @brief String descriptor table. + * */ +static uint8_t const * m_string_dsc[APP_USBD_STRING_ID_CNT][ARRAY_SIZE(m_langids)] = +{ + [APP_USBD_STRING_ID_LANGIDS_ARRAY_POS] = {APP_USBD_STRING_RAW16_DESC(APP_USBD_STRINGS_LANGIDS)}, + +#if (APP_USBD_STRING_ID_MANUFACTURER != 0) + [APP_USBD_STRING_ID_MANUFACTURER_ARRAY_POS] = { APP_USBD_STRINGS_MANUFACTURER }, +#endif // (APP_USBD_STRING_ID_MANUFACTURER != 0) + +#if (APP_USBD_STRING_ID_PRODUCT != 0) + [APP_USBD_STRING_ID_PRODUCT_ARRAY_POS] = { APP_USBD_STRINGS_PRODUCT }, +#endif // (APP_USBD_STRING_ID_PRODUCT != 0) + +#if (APP_USBD_STRING_ID_SERIAL != 0) + [APP_USBD_STRING_ID_SERIAL_ARRAY_POS] = { APP_USBD_STRING_SERIAL }, +#endif // (APP_USBD_STRING_ID_SERIAL != 0) + +#if (APP_USBD_STRING_ID_CONFIGURATION != 0) + [APP_USBD_STRING_ID_CONFIGURATION_ARRAY_POS] = { APP_USBD_STRINGS_CONFIGURATION }, +#endif // (APP_USBD_STRING_ID_CONFIGURATION != 0) + +#define X(mnemonic, str_idx, ...) [CONCAT_2(mnemonic, _ARRAY_POS)] = {__VA_ARGS__}, + APP_USBD_STRINGS_USER +#undef X +}; + +/** + * @brief Function for preparing UTF16 string descriptor. + * + * @param idx String descriptor ID. + * @param langid Language ID. + * + * @return Pointer to the string descriptor. + */ +static uint16_t * app_usbd_prepare_string(uint8_t idx, uint16_t langid) +{ + if (m_string_dsc[idx][langid][0] == 0x00) + { + return (uint16_t *) &(m_string_dsc[idx][langid][2]); + } + +#if ((APP_USBD_CONFIG_DESC_STRING_SIZE * 2) + 2) <= NRF_DRV_USBD_EPSIZE + uint16_t * string_buffer = app_usbd_core_setup_transfer_buff_get(NULL); +#else + static uint16_t string_buffer[APP_USBD_CONFIG_DESC_STRING_SIZE + 1]; + // + 1 element for string descriptor type and size +#endif + + uint8_t size = 0; + const uint8_t * p_pos = m_string_dsc[idx][langid]; + +#if APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED + size = utf8UTF16Count((char *) p_pos, 0); + ASSERT(size <= APP_USBD_CONFIG_DESC_STRING_SIZE); + + uint16_t * p_out = &(string_buffer[1]); + uint32_t rune; + + while (*p_pos != 0) + { + p_pos = (uint8_t *) utf8DecodeRune((char *) p_pos, 0, &rune); + p_out += utf16EncodeRune(rune, p_out); + } +#else + while(*p_pos != 0) + { + ASSERT(size < APP_USBD_CONFIG_DESC_STRING_SIZE); + ++size; + string_buffer[size] = *p_pos; + ++p_pos; + } +#endif + + // Descriptor size is length of the string times 2 bytes per character + 2 bytes for + // descriptor type and size. + string_buffer[0] = (0xff & (size * 2 + 2)) | ((uint16_t)APP_USBD_DESCRIPTOR_STRING) << 8; + + return string_buffer; +} + +uint16_t const * app_usbd_string_desc_get(uint8_t idx, uint16_t langid) +{ + /* LANGID string. */ + if (APP_USBD_STRING_ID_LANGIDS == idx) + { + return app_usbd_prepare_string(APP_USBD_STRING_ID_LANGIDS_ARRAY_POS, 0); + } + + /* Searching for the language. */ + uint8_t lang_idx = 0; + if (ARRAY_SIZE(m_langids) > 1) + { + while (m_langids[lang_idx] != langid) + { + ++lang_idx; + if (lang_idx >= ARRAY_SIZE(m_langids)) + { + return NULL; + } + } + } + + /* Get the string index in array. */ + if (idx >= ARRAY_SIZE(m_string_translation)) + { + return NULL; + } + + uint8_t str_pos = m_string_translation[idx]; + if (str_pos == 0) + { + return NULL; + } + + if ((ARRAY_SIZE(m_langids) > 1) && (lang_idx != 0)) + { + if (m_string_dsc[str_pos][lang_idx] == NULL) + { + lang_idx = 0; + } + } + + if (m_string_dsc[str_pos][lang_idx] == NULL) + { + return NULL; + } + + return app_usbd_prepare_string(str_pos, lang_idx); +} + +/** @} */ +#endif // APP_USBD_ENABLED diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.h index 665cc0d35..e0b2fe450 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.h +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.h @@ -1,179 +1,179 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef APP_USBD_STRING_DESC_H__ -#define APP_USBD_STRING_DESC_H__ - -#include -#include "sdk_common.h" -#include "app_usbd.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup app_usbd_string_desc USBD string descriptors - * @ingroup app_usbd - * - * @brief @tagAPI52840 USBD string descriptor management. - * @{ - */ - -/** - * @brief USB Language identifier initialization. - * - * @param[in] lang Language identifier. - */ -#define APP_USBD_LANG(lang) \ - ((app_usbd_langid_t) lang) - -/** - * @brief USB Language identifier with sublanguage initialization. - * - * @param[in] lang Language identifier. - * @param[in] sublang Sublanguage identifier. - */ -#define APP_USBD_LANG_AND_SUBLANG(lang, sublang) \ - ((app_usbd_langid_t) lang | (app_usbd_langid_t) sublang) - -/** - * @brief USB string initialization. - * - * Macro that creates initialization values for the USB string. - * The string must be declared as a NULL-terminated string. - * - * @param[in] str NULL-terminated string. - * - * @return String descriptor initialization data. - */ -#define APP_USBD_STRING_DESC(str) (const uint8_t *)(const char[]){str} - -/** - * @brief USB raw 8-bit string initialization. - * - * Macro that creates header for raw values passed into descriptor. - * Values must be of the uint8_t type and separated by commas. - * - * @param[in] ... comma-separated values. - * - * @return String descriptor initialization data. - */ -#define APP_USBD_STRING_RAW8_DESC(...) (const uint8_t[]){ \ - 0x00, 0x00, /* NULL character at start to differentiate from normal string */ \ - (0xff & (sizeof((uint8_t[]){__VA_ARGS__}) + 2)), \ - (APP_USBD_DESCRIPTOR_STRING), \ - __VA_ARGS__ } - -/** - * @brief USB raw 16-bit string initialization. - * - * Macro that creates header for raw values passed into descriptor. - * Values must be of the uint16_t type and separated by commas. - * - * @param[in] ... comma-separated values. - * - * @return String descriptor initialization data. - */ -#define APP_USBD_STRING_RAW16_DESC(...) (const uint8_t *) ((const uint16_t[]){ \ - 0x00, /* NULL character at start to differentiate from normal string */ \ - (0xff & (sizeof((uint16_t[]){__VA_ARGS__}) + 2)) | \ - ((uint16_t)APP_USBD_DESCRIPTOR_STRING) << 8, \ - __VA_ARGS__ }) - -/** - * @brief USB string descriptors IDs - */ -typedef enum { - APP_USBD_STRING_ID_LANGIDS = 0, /**< Supported language identifiers */ - - /// Placeholders used only for alignement of user strings. Do not use or modify them. - -#if (APP_USBD_STRING_ID_MANUFACTURER != 0) - APP_USBD_STRING_ID_MANUFACTURER_PLACEHOLDER = APP_USBD_STRING_ID_MANUFACTURER, -#endif // (APP_USBD_STRING_ID_MANUFACTURER != 0) - -#if (APP_USBD_STRING_ID_PRODUCT != 0) - APP_USBD_STRING_ID_PRODUCT_PLACEHOLDER = APP_USBD_STRING_ID_PRODUCT, -#endif // (APP_USBD_STRING_ID_PRODUCT != 0) - -#if (APP_USBD_STRING_ID_SERIAL != 0) - APP_USBD_STRING_ID_SERIAL_PLACEHOLDER = APP_USBD_STRING_ID_SERIAL, -#endif // (APP_USBD_STRING_ID_SERIAL != 0) - -#if (APP_USBD_STRING_ID_CONFIGURATION != 0) - APP_USBD_STRING_ID_CONFIGURATION_PLACEHOLDER = APP_USBD_STRING_ID_CONFIGURATION, -#endif // (APP_USBD_STRING_ID_CONFIGURATION != 0) - -#define X(mnemonic, str_idx, ...) mnemonic str_idx, - APP_USBD_STRINGS_USER -#undef X - - APP_USBD_STRING_ID_CNT /**< Total number of identifiers. */ -} app_usbd_string_desc_idx_t; - -/** - * @brief Get string descriptor. - * - * @param[in] idx String descriptor index. - * @param[in] langid Selected language for the string. - * @return String descriptor, or NULL if it does not exist. - * */ -uint16_t const * app_usbd_string_desc_get(uint8_t idx, uint16_t langid); - -/** - * @brief Get string length. - * - * Function for getting string length from descriptor (descriptor returned by @ref app_usbd_string_desc_get). - * - * @param[in] p_str String descriptor pointer. - * @return Total descriptor length in bytes. - */ -static inline size_t app_usbd_string_desc_length(uint16_t const * p_str) -{ - return ((const app_usbd_descriptor_string_t *)p_str)->bLength; -} - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_STRING_DESC_H__ */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef APP_USBD_STRING_DESC_H__ +#define APP_USBD_STRING_DESC_H__ + +#include +#include "sdk_common.h" +#include "app_usbd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup app_usbd_string_desc USBD string descriptors + * @ingroup app_usbd + * + * @brief @tagAPI52840 USBD string descriptor management. + * @{ + */ + +/** + * @brief USB Language identifier initialization. + * + * @param[in] lang Language identifier. + */ +#define APP_USBD_LANG(lang) \ + ((app_usbd_langid_t) lang) + +/** + * @brief USB Language identifier with sublanguage initialization. + * + * @param[in] lang Language identifier. + * @param[in] sublang Sublanguage identifier. + */ +#define APP_USBD_LANG_AND_SUBLANG(lang, sublang) \ + ((app_usbd_langid_t) lang | (app_usbd_langid_t) sublang) + +/** + * @brief USB string initialization. + * + * Macro that creates initialization values for the USB string. + * The string must be declared as a NULL-terminated string. + * + * @param[in] str NULL-terminated string. + * + * @return String descriptor initialization data. + */ +#define APP_USBD_STRING_DESC(str) (const uint8_t *)(const char[]){str} + +/** + * @brief USB raw 8-bit string initialization. + * + * Macro that creates header for raw values passed into descriptor. + * Values must be of the uint8_t type and separated by commas. + * + * @param[in] ... comma-separated values. + * + * @return String descriptor initialization data. + */ +#define APP_USBD_STRING_RAW8_DESC(...) (const uint8_t[]){ \ + 0x00, 0x00, /* NULL character at start to differentiate from normal string */ \ + (0xff & (sizeof((uint8_t[]){__VA_ARGS__}) + 2)), \ + (APP_USBD_DESCRIPTOR_STRING), \ + __VA_ARGS__ } + +/** + * @brief USB raw 16-bit string initialization. + * + * Macro that creates header for raw values passed into descriptor. + * Values must be of the uint16_t type and separated by commas. + * + * @param[in] ... comma-separated values. + * + * @return String descriptor initialization data. + */ +#define APP_USBD_STRING_RAW16_DESC(...) (const uint8_t *) ((const uint16_t[]){ \ + 0x00, /* NULL character at start to differentiate from normal string */ \ + (0xff & (sizeof((uint16_t[]){__VA_ARGS__}) + 2)) | \ + ((uint16_t)APP_USBD_DESCRIPTOR_STRING) << 8, \ + __VA_ARGS__ }) + +/** + * @brief USB string descriptors IDs + */ +typedef enum { + APP_USBD_STRING_ID_LANGIDS = 0, /**< Supported language identifiers */ + + /// Placeholders used only for alignement of user strings. Do not use or modify them. + +#if (APP_USBD_STRING_ID_MANUFACTURER != 0) + APP_USBD_STRING_ID_MANUFACTURER_PLACEHOLDER = APP_USBD_STRING_ID_MANUFACTURER, +#endif // (APP_USBD_STRING_ID_MANUFACTURER != 0) + +#if (APP_USBD_STRING_ID_PRODUCT != 0) + APP_USBD_STRING_ID_PRODUCT_PLACEHOLDER = APP_USBD_STRING_ID_PRODUCT, +#endif // (APP_USBD_STRING_ID_PRODUCT != 0) + +#if (APP_USBD_STRING_ID_SERIAL != 0) + APP_USBD_STRING_ID_SERIAL_PLACEHOLDER = APP_USBD_STRING_ID_SERIAL, +#endif // (APP_USBD_STRING_ID_SERIAL != 0) + +#if (APP_USBD_STRING_ID_CONFIGURATION != 0) + APP_USBD_STRING_ID_CONFIGURATION_PLACEHOLDER = APP_USBD_STRING_ID_CONFIGURATION, +#endif // (APP_USBD_STRING_ID_CONFIGURATION != 0) + +#define X(mnemonic, str_idx, ...) mnemonic str_idx, + APP_USBD_STRINGS_USER +#undef X + + APP_USBD_STRING_ID_CNT /**< Total number of identifiers. */ +} app_usbd_string_desc_idx_t; + +/** + * @brief Get string descriptor. + * + * @param[in] idx String descriptor index. + * @param[in] langid Selected language for the string. + * @return String descriptor, or NULL if it does not exist. + * */ +uint16_t const * app_usbd_string_desc_get(uint8_t idx, uint16_t langid); + +/** + * @brief Get string length. + * + * Function for getting string length from descriptor (descriptor returned by @ref app_usbd_string_desc_get). + * + * @param[in] p_str String descriptor pointer. + * @return Total descriptor length in bytes. + */ +static inline size_t app_usbd_string_desc_length(uint16_t const * p_str) +{ + return ((const app_usbd_descriptor_string_t *)p_str)->bLength; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_STRING_DESC_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_types.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_types.h index 494cb5f19..44ea273a4 100644 --- a/third_party/NordicSemiconductor/libraries/usb/app_usbd_types.h +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_types.h @@ -1,278 +1,278 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef APP_USBD_TYPES_H__ -#define APP_USBD_TYPES_H__ - -#include - -#include "sdk_errors.h" -#include "nrf_drv_usbd.h" -#include "app_usbd_request.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup app_usbd_types USB Device high level library variable types definition - * @ingroup app_usbd - * - * @brief @tagAPI52840 All types used by @ref app_usbd are defined here. - * This helps to avoid cross referencing into types in different files. - * @{ - */ - -/** - * @brief Change given value to 2 digits in BCD notation. - * - * @param[in] val The decimal value to be converted in the range from 0 to 99. - * @return Calculated BCD value. - */ -#define APP_USBD_BCD_2_MAKE(val) ( \ - ((((val) % 100) / 10) * 0x10) + \ - ((((val) % 10) / 1) * 0x1) \ - ) - -/** - * @brief Change given decimal version values to 4 digits in BCD notation. - * - * USB specification uses 4 digits BCD version notation in many descriptors. - * This macro changes 2 values to 4 BCD digits (one 16 bit value) - * that describes version in USB standard. - * - * @param[in] major Major version. - * @param[in] minor Minor version. - * - * @return Calculated 16 bit value with BCD representation of the version. - */ -#define APP_USBD_BCD_VER_MAKE(major, minor) \ - ((APP_USBD_BCD_2_MAKE(major) << 8) | APP_USBD_BCD_2_MAKE(minor)) - -/** - * @brief Combine endpoint address and its interval. - * - * @param[in] address Endpoint address - * @param[in] interval Endpoint interval - * @return Combined address and interval. - */ -#define APP_USBD_EP_WITH_INTERVAL(address, interval) \ - ((1UL << 16) | ((interval) << 8) | (address)) - -#define APP_USBD_EXTRACT_INTERVAL_VALUE(combined) \ - (((combined) & 0xFF00) >> 8) - -#define APP_USBD_EXTRACT_INTERVAL_FLAG(combined) \ - (((combined) >> 16) & 0x01) - -/** - * @brief Events codes. - * - * Redefined application event codes. - */ -typedef enum -{ - APP_USBD_EVT_DRV_SOF = NRF_DRV_USBD_EVT_SOF, /**< See documentation for @ref NRF_DRV_USBD_EVT_SOF */ - APP_USBD_EVT_DRV_RESET = NRF_DRV_USBD_EVT_RESET, /**< See documentation for @ref NRF_DRV_USBD_EVT_RESET */ - APP_USBD_EVT_DRV_SUSPEND = NRF_DRV_USBD_EVT_SUSPEND, /**< See documentation for @ref NRF_DRV_USBD_EVT_SUSPEND */ - APP_USBD_EVT_DRV_RESUME = NRF_DRV_USBD_EVT_RESUME, /**< See documentation for @ref NRF_DRV_USBD_EVT_RESUME */ - APP_USBD_EVT_DRV_WUREQ = NRF_DRV_USBD_EVT_WUREQ, /**< See documentation for @ref NRF_DRV_USBD_EVT_WUREQ */ - APP_USBD_EVT_DRV_SETUP = NRF_DRV_USBD_EVT_SETUP, /**< This event type has special structure. See @ref app_usbd_setup_evt_t */ - APP_USBD_EVT_DRV_EPTRANSFER = NRF_DRV_USBD_EVT_EPTRANSFER, /**< See documentation for @ref NRF_DRV_USBD_EVT_EPTRANSFER */ - - APP_USBD_EVT_FIRST_POWER, /**< First power event code - for internal static assert checking */ - - APP_USBD_EVT_POWER_DETECTED, /**< See documentation for @ref NRF_DRV_POWER_USB_EVT_DETECTED */ - APP_USBD_EVT_POWER_REMOVED, /**< See documentation for @ref NRF_DRV_POWER_USB_EVT_REMOVED */ - APP_USBD_EVT_POWER_READY, /**< See documentation for @ref NRF_DRV_POWER_USB_EVT_READY */ - - - APP_USBD_EVT_FIRST_APP, /**< First application event code - for internal static assert checking */ - - APP_USBD_EVT_INST_APPEND = APP_USBD_EVT_FIRST_APP, /**< The instance was attached to the library, any configuration action can be done now */ - APP_USBD_EVT_INST_REMOVE, /**< - * The instance is going to be removed, this event is called just before removing the instance. - * This removing cannot be stopped. - */ - APP_USBD_EVT_STARTED, /**< USBD library has just been started and functional - event passed to all instances, before USBD interrupts have been enabled */ - APP_USBD_EVT_STOPPED, /**< USBD library has just been stopped and is not functional - event passed to all instances, after USBD interrupts have been disabled*/ - - APP_USBD_EVT_STATE_CHANGED, /**< - * Informs all the classes that base state has been changed. - * This event is processed before setup stage that caused the state change finishes (before acknowledging it). - */ - - APP_USBD_EVT_FIRST_INTERNAL = 0x80, /**< First internal event, used by the APP library internally. */ - - APP_USBD_EVT_HFCLK_READY = APP_USBD_EVT_FIRST_INTERNAL, /**< High frequency clock started */ - APP_USBD_EVT_START_REQ, /**< Start requested */ - APP_USBD_EVT_STOP_REQ, /**< Stop requested */ - APP_USBD_EVT_SUSPEND_REQ, /**< Suspend request - HFCLK would be released and USBD peripheral clock would be disconnected */ - APP_USBD_EVT_WAKEUP_REQ, /**< Wakeup request - start the whole wakeup generation. */ - APP_USBD_EVT_SETUP_SETADDRESS, /**< - * Setup request to set address, separated from - * regular EVT_SETUP because this request is - * fully handled by hardware and for the software - * it is only a notification about what happened - */ - -} app_usbd_event_type_t; - - - -/** - * @brief Specific application event structure. - * - * All the data required by the events that comes from the application level. - */ -typedef struct -{ - app_usbd_event_type_t type; //!< Event type -} app_usbd_evt_t; - -/** - * @brief Specific application event structure with setup structure included. - * - * This event structure would be used when @ref APP_USBD_EVT_DRV_SETUP - * is passed to instance event handler. - */ -typedef struct -{ - app_usbd_event_type_t type; //!< Event type - app_usbd_setup_t setup; //!< Setup structure -} app_usbd_setup_evt_t; - - -/** - * @brief Complex event variable type. - * - * A variable that can store any kind of event. - */ -typedef union -{ - app_usbd_event_type_t type; //!< Event type - nrf_drv_usbd_evt_t drv_evt; //!< Events that comes directly from the driver. - /**< Use this event structure only for event - * type < @ref APP_USBD_EVT_FIRST_APP - */ - app_usbd_setup_evt_t setup_evt; //!< Event structure with SETUP structure included. - /**< This structure is used in connection with - * @ref APP_USBD_EVT_DRV_SETUP - */ - app_usbd_evt_t app_evt; //!< Events that comes from the application driver. - /**< Use this event structure only for event - * type >= @ref APP_USBD_EVT_FIRST_APP - */ -} app_usbd_complex_evt_t; - - -/** - * @brief Internal event variable type. - * - * The variable type used for internal event processing. - * This kind of event is the one that goes into the event queue. - * - * @note There is no setup event structure. - * This structure would be created when setup event is processed. - * The reason for that is the fact that setup event structure has high memory printout. - */ -typedef union -{ - app_usbd_event_type_t type; //!< Event type - nrf_drv_usbd_evt_t drv_evt; //!< Events that comes directly from the driver. - /**< Use this event structure only for event - * type < @ref APP_USBD_EVT_FIRST_APP - */ - app_usbd_evt_t app_evt; //!< Events that comes from the application driver. - /**< Use this event structure only for event - * type >= @ref APP_USBD_EVT_FIRST_APP - */ -} app_usbd_internal_evt_t; - - -#ifdef DOXYGEN -/** - * @brief Base instance of a USBD class. - * - * Any USBD class instance have to begin with this instance. - * This may then be followed by any implementation dependent data. - * - * For an instance it should be possible to put whole structure into FLASH. - * - * @note This type is early defined as incomplete type. - * This is required for function declaration that takes the pointer - * to this structure but in second hand - it is also placed inside - * the instance structure. - * @note The structure is defined in @file app_usbd_class_base.h. - */ -typedef struct {} app_usbd_class_inst_t; -#else -typedef struct app_usbd_class_inst_s app_usbd_class_inst_t; -#endif -/** - * @brief Endpoint callback function. - * - * The function used by every class instance. - * @param[in,out] p_inst Instance of the class. - * @param[in] p_event Event to process. - * - * @note If given event is not supported by class, return @ref NRF_ERROR_NOT_SUPPORTED - */ -typedef ret_code_t (*app_usbd_ep_event_handler_t)( - app_usbd_class_inst_t const * const p_inst, - app_usbd_complex_evt_t const * const p_event - ); - -/** - * @brief SOF interrupt callback function. - * - * @param[in] framecnt Number of current SOF frame. - * - * @sa app_usbd_class_sof_register - */ -typedef void (*app_usbd_sof_interrupt_handler_t)(uint16_t framecnt); - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_TYPES_H__ */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef APP_USBD_TYPES_H__ +#define APP_USBD_TYPES_H__ + +#include + +#include "sdk_errors.h" +#include "nrf_drv_usbd.h" +#include "app_usbd_request.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup app_usbd_types USB Device high level library variable types definition + * @ingroup app_usbd + * + * @brief @tagAPI52840 All types used by @ref app_usbd are defined here. + * This helps to avoid cross referencing into types in different files. + * @{ + */ + +/** + * @brief Change given value to 2 digits in BCD notation. + * + * @param[in] val The decimal value to be converted in the range from 0 to 99. + * @return Calculated BCD value. + */ +#define APP_USBD_BCD_2_MAKE(val) ( \ + ((((val) % 100) / 10) * 0x10) + \ + ((((val) % 10) / 1) * 0x1) \ + ) + +/** + * @brief Change given decimal version values to 4 digits in BCD notation. + * + * USB specification uses 4 digits BCD version notation in many descriptors. + * This macro changes 2 values to 4 BCD digits (one 16 bit value) + * that describes version in USB standard. + * + * @param[in] major Major version. + * @param[in] minor Minor version. + * + * @return Calculated 16 bit value with BCD representation of the version. + */ +#define APP_USBD_BCD_VER_MAKE(major, minor) \ + ((APP_USBD_BCD_2_MAKE(major) << 8) | APP_USBD_BCD_2_MAKE(minor)) + +/** + * @brief Combine endpoint address and its interval. + * + * @param[in] address Endpoint address + * @param[in] interval Endpoint interval + * @return Combined address and interval. + */ +#define APP_USBD_EP_WITH_INTERVAL(address, interval) \ + ((1UL << 16) | ((interval) << 8) | (address)) + +#define APP_USBD_EXTRACT_INTERVAL_VALUE(combined) \ + (((combined) & 0xFF00) >> 8) + +#define APP_USBD_EXTRACT_INTERVAL_FLAG(combined) \ + (((combined) >> 16) & 0x01) + +/** + * @brief Events codes. + * + * Redefined application event codes. + */ +typedef enum +{ + APP_USBD_EVT_DRV_SOF = NRF_DRV_USBD_EVT_SOF, /**< See documentation for @ref NRF_DRV_USBD_EVT_SOF */ + APP_USBD_EVT_DRV_RESET = NRF_DRV_USBD_EVT_RESET, /**< See documentation for @ref NRF_DRV_USBD_EVT_RESET */ + APP_USBD_EVT_DRV_SUSPEND = NRF_DRV_USBD_EVT_SUSPEND, /**< See documentation for @ref NRF_DRV_USBD_EVT_SUSPEND */ + APP_USBD_EVT_DRV_RESUME = NRF_DRV_USBD_EVT_RESUME, /**< See documentation for @ref NRF_DRV_USBD_EVT_RESUME */ + APP_USBD_EVT_DRV_WUREQ = NRF_DRV_USBD_EVT_WUREQ, /**< See documentation for @ref NRF_DRV_USBD_EVT_WUREQ */ + APP_USBD_EVT_DRV_SETUP = NRF_DRV_USBD_EVT_SETUP, /**< This event type has special structure. See @ref app_usbd_setup_evt_t */ + APP_USBD_EVT_DRV_EPTRANSFER = NRF_DRV_USBD_EVT_EPTRANSFER, /**< See documentation for @ref NRF_DRV_USBD_EVT_EPTRANSFER */ + + APP_USBD_EVT_FIRST_POWER, /**< First power event code - for internal static assert checking */ + + APP_USBD_EVT_POWER_DETECTED, /**< See documentation for @ref NRF_DRV_POWER_USB_EVT_DETECTED */ + APP_USBD_EVT_POWER_REMOVED, /**< See documentation for @ref NRF_DRV_POWER_USB_EVT_REMOVED */ + APP_USBD_EVT_POWER_READY, /**< See documentation for @ref NRF_DRV_POWER_USB_EVT_READY */ + + + APP_USBD_EVT_FIRST_APP, /**< First application event code - for internal static assert checking */ + + APP_USBD_EVT_INST_APPEND = APP_USBD_EVT_FIRST_APP, /**< The instance was attached to the library, any configuration action can be done now */ + APP_USBD_EVT_INST_REMOVE, /**< + * The instance is going to be removed, this event is called just before removing the instance. + * This removing cannot be stopped. + */ + APP_USBD_EVT_STARTED, /**< USBD library has just been started and functional - event passed to all instances, before USBD interrupts have been enabled */ + APP_USBD_EVT_STOPPED, /**< USBD library has just been stopped and is not functional - event passed to all instances, after USBD interrupts have been disabled*/ + + APP_USBD_EVT_STATE_CHANGED, /**< + * Informs all the classes that base state has been changed. + * This event is processed before setup stage that caused the state change finishes (before acknowledging it). + */ + + APP_USBD_EVT_FIRST_INTERNAL = 0x80, /**< First internal event, used by the APP library internally. */ + + APP_USBD_EVT_HFCLK_READY = APP_USBD_EVT_FIRST_INTERNAL, /**< High frequency clock started */ + APP_USBD_EVT_START_REQ, /**< Start requested */ + APP_USBD_EVT_STOP_REQ, /**< Stop requested */ + APP_USBD_EVT_SUSPEND_REQ, /**< Suspend request - HFCLK would be released and USBD peripheral clock would be disconnected */ + APP_USBD_EVT_WAKEUP_REQ, /**< Wakeup request - start the whole wakeup generation. */ + APP_USBD_EVT_SETUP_SETADDRESS, /**< + * Setup request to set address, separated from + * regular EVT_SETUP because this request is + * fully handled by hardware and for the software + * it is only a notification about what happened + */ + +} app_usbd_event_type_t; + + + +/** + * @brief Specific application event structure. + * + * All the data required by the events that comes from the application level. + */ +typedef struct +{ + app_usbd_event_type_t type; //!< Event type +} app_usbd_evt_t; + +/** + * @brief Specific application event structure with setup structure included. + * + * This event structure would be used when @ref APP_USBD_EVT_DRV_SETUP + * is passed to instance event handler. + */ +typedef struct +{ + app_usbd_event_type_t type; //!< Event type + app_usbd_setup_t setup; //!< Setup structure +} app_usbd_setup_evt_t; + + +/** + * @brief Complex event variable type. + * + * A variable that can store any kind of event. + */ +typedef union +{ + app_usbd_event_type_t type; //!< Event type + nrf_drv_usbd_evt_t drv_evt; //!< Events that comes directly from the driver. + /**< Use this event structure only for event + * type < @ref APP_USBD_EVT_FIRST_APP + */ + app_usbd_setup_evt_t setup_evt; //!< Event structure with SETUP structure included. + /**< This structure is used in connection with + * @ref APP_USBD_EVT_DRV_SETUP + */ + app_usbd_evt_t app_evt; //!< Events that comes from the application driver. + /**< Use this event structure only for event + * type >= @ref APP_USBD_EVT_FIRST_APP + */ +} app_usbd_complex_evt_t; + + +/** + * @brief Internal event variable type. + * + * The variable type used for internal event processing. + * This kind of event is the one that goes into the event queue. + * + * @note There is no setup event structure. + * This structure would be created when setup event is processed. + * The reason for that is the fact that setup event structure has high memory printout. + */ +typedef union +{ + app_usbd_event_type_t type; //!< Event type + nrf_drv_usbd_evt_t drv_evt; //!< Events that comes directly from the driver. + /**< Use this event structure only for event + * type < @ref APP_USBD_EVT_FIRST_APP + */ + app_usbd_evt_t app_evt; //!< Events that comes from the application driver. + /**< Use this event structure only for event + * type >= @ref APP_USBD_EVT_FIRST_APP + */ +} app_usbd_internal_evt_t; + + +#ifdef DOXYGEN +/** + * @brief Base instance of a USBD class. + * + * Any USBD class instance have to begin with this instance. + * This may then be followed by any implementation dependent data. + * + * For an instance it should be possible to put whole structure into FLASH. + * + * @note This type is early defined as incomplete type. + * This is required for function declaration that takes the pointer + * to this structure but in second hand - it is also placed inside + * the instance structure. + * @note The structure is defined in @file app_usbd_class_base.h. + */ +typedef struct {} app_usbd_class_inst_t; +#else +typedef struct app_usbd_class_inst_s app_usbd_class_inst_t; +#endif +/** + * @brief Endpoint callback function. + * + * The function used by every class instance. + * @param[in,out] p_inst Instance of the class. + * @param[in] p_event Event to process. + * + * @note If given event is not supported by class, return @ref NRF_ERROR_NOT_SUPPORTED + */ +typedef ret_code_t (*app_usbd_ep_event_handler_t)( + app_usbd_class_inst_t const * const p_inst, + app_usbd_complex_evt_t const * const p_event + ); + +/** + * @brief SOF interrupt callback function. + * + * @param[in] framecnt Number of current SOF frame. + * + * @sa app_usbd_class_sof_register + */ +typedef void (*app_usbd_sof_interrupt_handler_t)(uint16_t framecnt); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_TYPES_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.c b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.c index a151e60b0..87d901bf5 100644 --- a/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.c +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.c @@ -1,1199 +1,1199 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(APP_USBD_CDC_ACM) - -#include "app_usbd_cdc_acm.h" -#include - -/** - * @defgroup app_usbd_cdc_acm_internal CDC ACM internals - * @{ - * @ingroup app_usbd_cdc - * @internal - */ - - -#define NRF_LOG_MODULE_NAME cdc_acm - -#if APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED -#define NRF_LOG_LEVEL APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL -#define NRF_LOG_INFO_COLOR APP_USBD_CDC_ACM_CONFIG_INFO_COLOR -#define NRF_LOG_DEBUG_COLOR APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR -#else //APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED -#define NRF_LOG_LEVEL 0 -#endif //APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED -#include "nrf_log.h" -NRF_LOG_MODULE_REGISTER(); - -#define APP_USBD_CDC_ACM_COMM_IFACE_IDX 0 /**< CDC ACM class comm interface index. */ -#define APP_USBD_CDC_ACM_DATA_IFACE_IDX 1 /**< CDC ACM class data interface index. */ - -#define APP_USBD_CDC_ACM_COMM_EPIN_IDX 0 /**< CDC ACM comm class endpoint IN index. */ -#define APP_USBD_CDC_ACM_DATA_EPIN_IDX 0 /**< CDC ACM data class endpoint IN index. */ -#define APP_USBD_CDC_ACM_DATA_EPOUT_IDX 1 /**< CDC ACM data class endpoint OUT index. */ - -/** - * @brief Auxiliary function to access cdc_acm class instance data. - * - * @param[in] p_inst Class instance data. - * - * @return CDC ACM class instance. - */ -static inline app_usbd_cdc_acm_t const * cdc_acm_get(app_usbd_class_inst_t const * p_inst) -{ - ASSERT(p_inst != NULL); - return (app_usbd_cdc_acm_t const *)p_inst; -} - -/** - * @brief Auxiliary function to access cdc_acm class context data. - * - * @param[in] p_cdc_acm CDC ACM class instance data. - * - * @return CDC ACM class instance context. - */ -static inline app_usbd_cdc_acm_ctx_t * cdc_acm_ctx_get(app_usbd_cdc_acm_t const * p_cdc_acm) -{ - ASSERT(p_cdc_acm != NULL); - ASSERT(p_cdc_acm->specific.p_data != NULL); - return &p_cdc_acm->specific.p_data->ctx; -} - -/** - * @brief User event handler. - * - * @param[in] p_inst Class instance. - * @param[in] event user Event type. - */ -static inline void user_event_handler(app_usbd_class_inst_t const * p_inst, - app_usbd_cdc_acm_user_event_t event) -{ - app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); - if (p_cdc_acm->specific.inst.user_ev_handler != NULL) - { - p_cdc_acm->specific.inst.user_ev_handler(p_inst, event); - } -} - -/** - * @brief Auxiliary function to access CDC ACM COMM IN endpoint address. - * - * @param[in] p_inst Class instance data. - * - * @return IN endpoint address. - */ -static inline nrf_drv_usbd_ep_t comm_ep_in_addr_get(app_usbd_class_inst_t const * p_inst) -{ - app_usbd_class_iface_conf_t const * class_iface; - class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_COMM_IFACE_IDX); - - app_usbd_class_ep_conf_t const * ep_cfg; - ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_COMM_EPIN_IDX); - - return app_usbd_class_ep_address_get(ep_cfg); -} - -/** - * @brief Auxiliary function to access CDC ACM DATA IN endpoint address. - * - * @param[in] p_inst Class instance data. - * - * @return IN endpoint address. - */ -static inline nrf_drv_usbd_ep_t data_ep_in_addr_get(app_usbd_class_inst_t const * p_inst) -{ - app_usbd_class_iface_conf_t const * class_iface; - class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_DATA_IFACE_IDX); - - app_usbd_class_ep_conf_t const * ep_cfg; - ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_DATA_EPIN_IDX); - - return app_usbd_class_ep_address_get(ep_cfg); -} - -/** - * @brief Auxiliary function to access CDC ACM DATA OUT endpoint address. - * - * @param[in] p_inst Class instance data. - * - * @return OUT endpoint address. - */ -static inline nrf_drv_usbd_ep_t data_ep_out_addr_get(app_usbd_class_inst_t const * p_inst) -{ - app_usbd_class_iface_conf_t const * class_iface; - class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_DATA_IFACE_IDX); - - app_usbd_class_ep_conf_t const * ep_cfg; - ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_DATA_EPOUT_IDX); - - return app_usbd_class_ep_address_get(ep_cfg); -} - -/** - * @brief Internal SETUP standard IN request handler. - * - * @param[in] p_inst Generic class instance. - * @param[in] p_setup_ev Setup event. - * - * @return Standard error code. - */ -static ret_code_t setup_req_std_in(app_usbd_class_inst_t const * p_inst, - app_usbd_setup_evt_t const * p_setup_ev) -{ - /* Only Get Descriptor standard IN request is supported by CDC class */ - if ((app_usbd_setup_req_rec(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQREC_INTERFACE) - && - (p_setup_ev->setup.bmRequest == APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR)) - { - size_t dsc_len = 0; - size_t max_size; - - uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size); - - /* Try to find descriptor in class internals*/ - ret_code_t ret = app_usbd_class_descriptor_find( - p_inst, - p_setup_ev->setup.wValue.hb, - p_setup_ev->setup.wValue.lb, - p_trans_buff, - &dsc_len); - - if (ret != NRF_ERROR_NOT_FOUND) - { - ASSERT(dsc_len < NRF_DRV_USBD_EPSIZE); - return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_trans_buff, dsc_len); - } - } - - return NRF_ERROR_NOT_SUPPORTED; -} - -/** - * @brief Internal SETUP standard OUT request handler. - * - * @param[in] p_inst Generic class instance. - * @param[in] p_setup_ev Setup event. - * - * @return Standard error code. - */ -static ret_code_t setup_req_std_out(app_usbd_class_inst_t const * p_inst, - app_usbd_setup_evt_t const * p_setup_ev) -{ - - switch (p_setup_ev->setup.bmRequest) - { - default: - break; - } - - return NRF_ERROR_NOT_SUPPORTED; -} - -/** - * @brief Internal SETUP class IN request handler. - * - * @param[in] p_inst Generic class instance. - * @param[in] p_setup_ev Setup event. - * - * @return Standard error code. - */ -static ret_code_t setup_req_class_in(app_usbd_class_inst_t const * p_inst, - app_usbd_setup_evt_t const * p_setup_ev) -{ - app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - switch (p_setup_ev->setup.bmRequest) - { - case APP_USBD_CDC_REQ_GET_LINE_CODING: - { - if (p_setup_ev->setup.wLength.w != sizeof(app_usbd_cdc_line_coding_t)) - { - return NRF_ERROR_NOT_SUPPORTED; - } - - return app_usbd_core_setup_rsp(&p_setup_ev->setup, - &p_cdc_acm_ctx->line_coding, - sizeof(app_usbd_cdc_line_coding_t)); - } - default: - break; - } - - return NRF_ERROR_NOT_SUPPORTED; -} - -/** - * @brief Class specific OUT request data callback. - * - * @param status Endpoint status. - * @param p_context Context of transfer (set by @ref app_usbd_core_setup_data_handler_set). - * - * @return Standard error code. - */ -static ret_code_t cdc_acm_req_out_data_cb(nrf_drv_usbd_ep_status_t status, void * p_context) -{ - if (status != NRF_USBD_EP_OK) - { - return NRF_ERROR_INTERNAL; - } - - app_usbd_cdc_acm_t const * p_cdc_acm = p_context; - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - switch (p_cdc_acm_ctx->request.type) - { - case APP_USBD_CDC_REQ_SET_LINE_CODING: - { - memcpy(&p_cdc_acm_ctx->line_coding, - &p_cdc_acm_ctx->request.payload.line_coding, - sizeof(app_usbd_cdc_line_coding_t)); - - NRF_LOG_INFO("REQ_SET_LINE_CODING: baudrate: %"PRIu32", databits: %u, " - "format: %u, parity: %u", - uint32_decode(p_cdc_acm_ctx->line_coding.dwDTERate), - p_cdc_acm_ctx->line_coding.bDataBits, - p_cdc_acm_ctx->line_coding.bCharFormat, - p_cdc_acm_ctx->line_coding.bParityType); - break; - } - default: - return NRF_ERROR_NOT_SUPPORTED; - } - - return NRF_SUCCESS; -} - - -/** - * @brief Class specific request data stage setup. - * - * @param[in] p_inst Generic class instance. - * @param[in] p_setup_ev Setup event. - * - * @return Standard error code. - */ -static ret_code_t cdc_acm_req_out_datastage(app_usbd_class_inst_t const * p_inst, - app_usbd_setup_evt_t const * p_setup_ev) -{ - app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - p_cdc_acm_ctx->request.type = p_setup_ev->setup.bmRequest; - p_cdc_acm_ctx->request.len = p_setup_ev->setup.wLength.w; - - /*Request setup data*/ - NRF_DRV_USBD_TRANSFER_OUT(transfer, - &p_cdc_acm_ctx->request.payload, - p_cdc_acm_ctx->request.len); - ret_code_t ret; - CRITICAL_REGION_ENTER(); - ret = app_usbd_ep_transfer(NRF_DRV_USBD_EPOUT0, &transfer); - if (ret == NRF_SUCCESS) - { - const app_usbd_core_setup_data_handler_desc_t desc = { - .handler = cdc_acm_req_out_data_cb, - .p_context = (void*)p_cdc_acm - }; - - ret = app_usbd_core_setup_data_handler_set(NRF_DRV_USBD_EPOUT0, &desc); - } - CRITICAL_REGION_EXIT(); - - return ret; -} - -/** - * @brief Reset port to default state. - * - * @param p_inst Generic class instance. - */ -static void cdc_acm_reset_port(app_usbd_class_inst_t const * p_inst) -{ - app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - p_cdc_acm_ctx->line_state = 0; - - // Set rx transfers configuration to default state. - p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; - p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; - p_cdc_acm_ctx->bytes_left = 0; - p_cdc_acm_ctx->bytes_read = 0; - p_cdc_acm_ctx->last_read = 0; - p_cdc_acm_ctx->cur_read = 0; - p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf; -} - -/** - * @brief Internal SETUP class OUT request handler. - * - * @param[in] p_inst Generic class instance. - * @param[in] p_setup_ev Setup event. - * - * @return Standard error code. - */ -static ret_code_t setup_req_class_out(app_usbd_class_inst_t const * p_inst, - app_usbd_setup_evt_t const * p_setup_ev) -{ - app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - switch (p_setup_ev->setup.bmRequest) - { - case APP_USBD_CDC_REQ_SET_LINE_CODING: - { - if (p_setup_ev->setup.wLength.w != sizeof(app_usbd_cdc_line_coding_t)) - { - return NRF_ERROR_NOT_SUPPORTED; - } - - return cdc_acm_req_out_datastage(p_inst, p_setup_ev); - } - case APP_USBD_CDC_REQ_SET_CONTROL_LINE_STATE: - { - if (p_setup_ev->setup.wLength.w != 0) - { - return NRF_ERROR_NOT_SUPPORTED; - } - - NRF_LOG_INFO("REQ_SET_CONTROL_LINE_STATE: 0x%x", p_setup_ev->setup.wValue.w); - - bool old_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? - true : false; - p_cdc_acm_ctx->line_state = p_setup_ev->setup.wValue.w; - - bool new_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? - true : false; - - if (old_dtr == new_dtr) - { - return NRF_SUCCESS; - } - - const app_usbd_cdc_acm_user_event_t ev = new_dtr ? - APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN : APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE; - - user_event_handler(p_inst, ev); - - if (!new_dtr) - { - /*Abort DATA endpoints on port close */ - nrf_drv_usbd_ep_t ep; - ep = data_ep_in_addr_get(p_inst); - nrf_drv_usbd_ep_abort(ep); - ep = data_ep_out_addr_get(p_inst); - nrf_drv_usbd_ep_abort(ep); - - // Set rx transfers configuration to default state. - p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; - p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; - p_cdc_acm_ctx->bytes_left = 0; - p_cdc_acm_ctx->bytes_read = 0; - p_cdc_acm_ctx->last_read = 0; - p_cdc_acm_ctx->cur_read = 0; - p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf; - } - - return NRF_SUCCESS; - } - default: - break; - } - - return NRF_ERROR_NOT_SUPPORTED; -} - -/** - * @brief Control endpoint handler. - * - * @param[in] p_inst Generic class instance. - * @param[in] p_setup_ev Setup event. - * - * @return Standard error code. - */ -static ret_code_t setup_event_handler(app_usbd_class_inst_t const * p_inst, - app_usbd_setup_evt_t const * p_setup_ev) -{ - ASSERT(p_inst != NULL); - ASSERT(p_setup_ev != NULL); - - if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN) - { - switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) - { - case APP_USBD_SETUP_REQTYPE_STD: - return setup_req_std_in(p_inst, p_setup_ev); - case APP_USBD_SETUP_REQTYPE_CLASS: - return setup_req_class_in(p_inst, p_setup_ev); - default: - break; - } - } - else /*APP_USBD_SETUP_REQDIR_OUT*/ - { - switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) - { - case APP_USBD_SETUP_REQTYPE_STD: - return setup_req_std_out(p_inst, p_setup_ev); - case APP_USBD_SETUP_REQTYPE_CLASS: - return setup_req_class_out(p_inst, p_setup_ev); - default: - break; - } - } - - return NRF_ERROR_NOT_SUPPORTED; -} - - -/** - * @brief CDC ACM consumer. - * - * @note See @ref nrf_drv_usbd_consumer_t - */ -static bool cdc_acm_consumer(nrf_drv_usbd_ep_transfer_t * p_next, - void * p_context, - size_t ep_size, - size_t data_size) -{ - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = (app_usbd_cdc_acm_ctx_t *) p_context; - p_next->size = data_size; - - if (data_size <= p_cdc_acm_ctx->rx_transfer[0].read_left) - { - p_next->p_data.rx = p_cdc_acm_ctx->rx_transfer[0].p_buf; - - p_cdc_acm_ctx->rx_transfer[0].p_buf += data_size; - p_cdc_acm_ctx->bytes_read += data_size; - p_cdc_acm_ctx->rx_transfer[0].read_left -= data_size; - NRF_LOG_DEBUG("Received %d bytes. Space left in user buffer: %d bytes.", - data_size, - p_cdc_acm_ctx->rx_transfer[0].read_left); - return (p_cdc_acm_ctx->rx_transfer[0].read_left) != 0; - } - else - { - p_next->p_data.rx = p_cdc_acm_ctx->internal_rx_buf; - - p_cdc_acm_ctx->cur_read = data_size; - NRF_LOG_DEBUG("Received %d bytes. Stored in internal buffer.", data_size); - return false; - } -} - -/** - * @brief CDC ACM single transfer consumer. - * - * This function finalizes transfer after any received block. - * - * @note See @ref nrf_drv_usbd_consumer_t - */ -static bool cdc_acm_single_shoot_consumer(nrf_drv_usbd_ep_transfer_t * p_next, - void * p_context, - size_t ep_size, - size_t data_size) -{ - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = (app_usbd_cdc_acm_ctx_t *) p_context; - p_next->size = data_size; - - if (data_size <= p_cdc_acm_ctx->rx_transfer[0].read_left) - { - p_next->p_data.rx = p_cdc_acm_ctx->rx_transfer[0].p_buf; - - p_cdc_acm_ctx->bytes_read = data_size; - p_cdc_acm_ctx->rx_transfer[0].read_left = data_size; - NRF_LOG_DEBUG("Received %d bytes. Space left in user buffer: %d bytes.", - data_size, - p_cdc_acm_ctx->rx_transfer[0].read_left); - } - else - { - p_next->p_data.rx = p_cdc_acm_ctx->internal_rx_buf; - p_cdc_acm_ctx->cur_read = data_size; - NRF_LOG_DEBUG("Received %d bytes. Stored in internal buffer.", data_size); - } - - return false; -} - -/** - * @brief Manage switching between user buffers and copying data from internal buffer. - * - * @param p_inst Generic USB class instance. - * - * @return Standard error code. - */ -static ret_code_t cdc_acm_rx_block_finished(app_usbd_class_inst_t const * p_inst) -{ - app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(p_inst); - - nrf_drv_usbd_handler_desc_t handler_desc = { - .handler.consumer = cdc_acm_consumer, - .p_context = p_cdc_acm_ctx - }; - - if (p_cdc_acm_ctx->rx_transfer[0].read_left == 0) // Buffer completely filled by consumer - { - p_cdc_acm_ctx->last_read = p_cdc_acm_ctx->bytes_read; - p_cdc_acm_ctx->bytes_read = 0; - p_cdc_acm_ctx->bytes_left = 0; - - if (p_cdc_acm_ctx->rx_transfer[1].p_buf != NULL) - { - p_cdc_acm_ctx->rx_transfer[0] = p_cdc_acm_ctx->rx_transfer[1]; - p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; - return app_usbd_ep_handled_transfer(ep, &handler_desc); - } - else - { - p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; - return NRF_SUCCESS; - } - } - - size_t bytes_read = p_cdc_acm_ctx->cur_read; - size_t bytes_to_cpy = bytes_read; - - if (bytes_read > p_cdc_acm_ctx->rx_transfer[0].read_left) - { - bytes_to_cpy = p_cdc_acm_ctx->rx_transfer[0].read_left; - } - memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf, - p_cdc_acm_ctx->internal_rx_buf, - bytes_to_cpy); - - // First buffer is full - p_cdc_acm_ctx->last_read = p_cdc_acm_ctx->bytes_read + bytes_to_cpy; - p_cdc_acm_ctx->bytes_read = 0; - p_cdc_acm_ctx->bytes_left = bytes_read - bytes_to_cpy; - p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf + bytes_to_cpy; - - if (p_cdc_acm_ctx->rx_transfer[1].p_buf != NULL) - { - // If there is second transfer, copy it to first - p_cdc_acm_ctx->rx_transfer[0] = p_cdc_acm_ctx->rx_transfer[1]; - p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; - - while (p_cdc_acm_ctx->bytes_left > 0) - { - - if (p_cdc_acm_ctx->bytes_left >= p_cdc_acm_ctx->rx_transfer[0].read_left) - { - // If there are enough bytes left in internal buffer to completely fill next transfer, - // we call user event handler to obtain next buffer and continue double buffering. - memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf, - p_cdc_acm_ctx->p_copy_pos, - p_cdc_acm_ctx->rx_transfer[0].read_left); - - p_cdc_acm_ctx->bytes_left -= p_cdc_acm_ctx->rx_transfer[0].read_left; - p_cdc_acm_ctx->p_copy_pos += p_cdc_acm_ctx->rx_transfer[0].read_left; - p_cdc_acm_ctx->last_read = p_cdc_acm_ctx->rx_transfer[0].read_left; - user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_RX_DONE); - - if (p_cdc_acm_ctx->rx_transfer[1].p_buf != NULL) - { - p_cdc_acm_ctx->rx_transfer[0] = p_cdc_acm_ctx->rx_transfer[1]; - p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; - } - else - { - // If user does not specify a second buffer, all data transfers are done - // and data left in internal buffer is lost. - p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; - break; - } - } - else - { - memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf, - p_cdc_acm_ctx->p_copy_pos, - p_cdc_acm_ctx->bytes_left); - p_cdc_acm_ctx->bytes_read = p_cdc_acm_ctx->bytes_left; - - p_cdc_acm_ctx->rx_transfer[0].read_left -= p_cdc_acm_ctx->bytes_left; - p_cdc_acm_ctx->rx_transfer[0].p_buf += p_cdc_acm_ctx->bytes_left; - break; - } - } - - - } - else - { - p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; - } - - if (p_cdc_acm_ctx->rx_transfer[0].p_buf != NULL) - { - return app_usbd_ep_handled_transfer(ep, &handler_desc); - } - return NRF_SUCCESS; -} - -/** - * @brief Class specific endpoint transfer handler. - * - * @param[in] p_inst Generic class instance. - * @param[in] p_setup_ev Setup event. - * - * @return Standard error code. - */ -static ret_code_t cdc_acm_endpoint_ev(app_usbd_class_inst_t const * p_inst, - app_usbd_complex_evt_t const * p_event) -{ - if (comm_ep_in_addr_get(p_inst) == p_event->drv_evt.data.eptransfer.ep) - { - NRF_LOG_INFO("EPIN_COMM: notify"); - return NRF_SUCCESS; - } - ret_code_t ret; - if (NRF_USBD_EPIN_CHECK(p_event->drv_evt.data.eptransfer.ep)) - { - switch (p_event->drv_evt.data.eptransfer.status) - { - case NRF_USBD_EP_OK: - NRF_LOG_INFO("EPIN_DATA: %02x done", p_event->drv_evt.data.eptransfer.ep); - user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_TX_DONE); - return NRF_SUCCESS; - case NRF_USBD_EP_ABORTED: - return NRF_SUCCESS; - default: - return NRF_ERROR_INTERNAL; - } - } - - if (NRF_USBD_EPOUT_CHECK(p_event->drv_evt.data.eptransfer.ep)) - { - switch (p_event->drv_evt.data.eptransfer.status) - { - case NRF_USBD_EP_OK: - ret = cdc_acm_rx_block_finished(p_inst); - NRF_LOG_INFO("EPOUT_DATA: %02x done", p_event->drv_evt.data.eptransfer.ep); - user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_RX_DONE); - return ret; - case NRF_USBD_EP_WAITING: - case NRF_USBD_EP_ABORTED: - return NRF_SUCCESS; - default: - return NRF_ERROR_INTERNAL; - } - } - - return NRF_ERROR_NOT_SUPPORTED; -} - - -/** - * @brief @ref app_usbd_class_methods_t::event_handler - */ -static ret_code_t cdc_acm_event_handler(app_usbd_class_inst_t const * p_inst, - app_usbd_complex_evt_t const * p_event) -{ - ASSERT(p_inst != NULL); - ASSERT(p_event != NULL); - - ret_code_t ret = NRF_SUCCESS; - switch (p_event->app_evt.type) - { - case APP_USBD_EVT_DRV_SOF: - break; - case APP_USBD_EVT_DRV_RESET: - cdc_acm_reset_port(p_inst); - break; - case APP_USBD_EVT_DRV_SETUP: - ret = setup_event_handler(p_inst, (app_usbd_setup_evt_t const *)p_event); - break; - case APP_USBD_EVT_DRV_EPTRANSFER: - ret = cdc_acm_endpoint_ev(p_inst, p_event); - break; - case APP_USBD_EVT_DRV_SUSPEND: - break; - case APP_USBD_EVT_DRV_RESUME: - break; - case APP_USBD_EVT_INST_APPEND: - break; - case APP_USBD_EVT_INST_REMOVE: - break; - case APP_USBD_EVT_STARTED: - break; - case APP_USBD_EVT_STOPPED: - break; - case APP_USBD_EVT_POWER_REMOVED: - cdc_acm_reset_port(p_inst); - break; - default: - ret = NRF_ERROR_NOT_SUPPORTED; - break; - } - - return ret; -} - - -static bool cdc_acm_feed_descriptors(app_usbd_class_descriptor_ctx_t * p_ctx, - app_usbd_class_inst_t const * p_inst, - uint8_t * p_buff, - size_t max_size) -{ - static uint8_t ifaces = 0; - ifaces = app_usbd_class_iface_count_get(p_inst); - app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); - - APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size); - - /* INTERFACE ASSOCIATION DESCRIPTOR */ - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x08); // bLength - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE_ASSOCIATION); // bDescriptorType = Interface Association - APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.comm_interface); // bFirstInterface - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x02); // bInterfaceCount - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_COMM_CLASS); // bFunctionClass - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SUBCLASS_ACM); // bFunctionSubClass - APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.protocol); // bFunctionProtocol - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iFunction - - static uint8_t i = 0; - - for (i = 0; i < ifaces; i++) - { - /* INTERFACE DESCRIPTOR */ - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE); // bDescriptorType = Interface - - static app_usbd_class_iface_conf_t const * p_cur_iface = NULL; - p_cur_iface = app_usbd_class_iface_get(p_inst, i); - - APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_number_get(p_cur_iface)); // bInterfaceNumber - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bAlternateSetting - APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_ep_count_get(p_cur_iface)); // bNumEndpoints - - if (p_cdc_acm->specific.inst.comm_interface == app_usbd_class_iface_number_get(p_cur_iface)) - { - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_COMM_CLASS); // bInterfaceClass = CDC COMM - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SUBCLASS_ACM); // bInterfaceSubclass - APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.protocol); // bInterfaceProtocol - } - else if (p_cdc_acm->specific.inst.data_interface == - app_usbd_class_iface_number_get(p_cur_iface)) - { - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_DATA_CLASS); // bInterfaceClass = CDC DATA - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterfaceSubclass - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterfaceProtocol - } - else - { - ASSERT(0); - } - - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iInterface - - if (p_cdc_acm->specific.inst.comm_interface == app_usbd_class_iface_number_get(p_cur_iface)) - { - /* HEADER DESCRIPTOR */ - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x05); // bLength - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_HEADER); // bDescriptorSubtype = Header Functional Descriptor - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x10); // bcdCDC LSB - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x01); // bcdCDC MSB - - /* CALL MANAGEMENT DESCRIPTOR */ - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x05); // bLength - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_CALL_MGMT); // bDescriptorSubtype = Call Management Functional Descriptor - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x03); // bmCapabilities - APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.data_interface); // bDataInterface - - /* ABSTRACT CONTROL MANAGEMENT DESCRIPTOR */ - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x04); // bLength - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_ACM); // bDescriptorSubtype = Abstract Control Management Functional Descriptor - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x02); // bmCapabilities - - /* UNION DESCRIPTOR */ - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x05); - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_UNION); // bDescriptorSubtype = Union Functional Descriptor - APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.comm_interface); // bControlInterface - APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.data_interface); // bSubordinateInterface - } - else if (p_cdc_acm->specific.inst.data_interface == - app_usbd_class_iface_number_get(p_cur_iface)) - { - ; - } - else - { - ASSERT(0); - } - - /* ENDPOINT DESCRIPTORS */ - static uint8_t endpoints = 0; - endpoints = app_usbd_class_iface_ep_count_get(p_cur_iface); - - static uint8_t j = 0; - - for (j = 0; j < endpoints; j++) - { - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x07); // bLength - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_ENDPOINT); // bDescriptorType = Endpoint - - static app_usbd_class_ep_conf_t const * p_cur_ep = NULL; - p_cur_ep = app_usbd_class_iface_ep_get(p_cur_iface, j); - APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_ep_address_get(p_cur_ep)); // bEndpointAddress - - if (p_cdc_acm->specific.inst.comm_interface == - app_usbd_class_iface_number_get(p_cur_iface)) - { - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_INTERRUPT); // bmAttributes - } - else if (p_cdc_acm->specific.inst.data_interface == - app_usbd_class_iface_number_get(p_cur_iface)) - { - APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK); // bmAttributes - } - else - { - ASSERT(0); - } - - APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize LSB - APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize MSB - - if (p_cdc_acm->specific.inst.comm_interface == - app_usbd_class_iface_number_get(p_cur_iface)) - { - APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.p_ep_interval[0]); // bInterval - } - else if (p_cdc_acm->specific.inst.data_interface == - app_usbd_class_iface_number_get(p_cur_iface)) - { - APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterval - } - else - { - ASSERT(0); - } - - } - - } - - APP_USBD_CLASS_DESCRIPTOR_END(); -} - -/** - * @brief Public cdc_acm class interface. - * - */ -const app_usbd_class_methods_t app_usbd_cdc_acm_class_methods = { - .event_handler = cdc_acm_event_handler, - .feed_descriptors = cdc_acm_feed_descriptors, -}; - -/** @} */ - -ret_code_t app_usbd_cdc_acm_write(app_usbd_cdc_acm_t const * p_cdc_acm, - const void * p_buf, - size_t length) -{ - app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm); - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - bool dtr_state = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? - true : false; - if (!dtr_state) - { - /*Port is not opened*/ - return NRF_ERROR_INVALID_STATE; - } - - nrf_drv_usbd_ep_t ep = data_ep_in_addr_get(p_inst); - - if (APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE && ((length % NRF_DRV_USBD_EPSIZE) == 0)) - { - NRF_DRV_USBD_TRANSFER_IN_ZLP(transfer, p_buf, length); - return app_usbd_ep_transfer(ep, &transfer); - } - else - { - NRF_DRV_USBD_TRANSFER_IN(transfer, p_buf, length); - return app_usbd_ep_transfer(ep, &transfer); - } -} - -size_t app_usbd_cdc_acm_rx_size(app_usbd_cdc_acm_t const * p_cdc_acm) -{ - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - return p_cdc_acm_ctx->last_read; -} - -size_t app_usbd_cdc_acm_bytes_stored(app_usbd_cdc_acm_t const * p_cdc_acm) -{ - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - return p_cdc_acm_ctx->bytes_left; -} - -ret_code_t app_usbd_cdc_acm_read(app_usbd_cdc_acm_t const * p_cdc_acm, - void * p_buf, - size_t length) -{ - ASSERT(p_buf != NULL); - ret_code_t ret; - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - if (0U == (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR)) - { - /*Port is not opened*/ - return NRF_ERROR_INVALID_STATE; - } - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) - CRITICAL_REGION_ENTER(); -#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) - - if (p_cdc_acm_ctx->rx_transfer[0].p_buf == NULL) - { - if (p_cdc_acm_ctx->bytes_left >= length) - { - memcpy(p_buf, p_cdc_acm_ctx->p_copy_pos, length); - p_cdc_acm_ctx->bytes_left -= length; - p_cdc_acm_ctx->p_copy_pos += length; - p_cdc_acm_ctx->last_read = length; - ret = NRF_SUCCESS; - } - else - { - p_cdc_acm_ctx->rx_transfer[0].p_buf = p_buf; - p_cdc_acm_ctx->rx_transfer[0].read_left = length; - nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(app_usbd_cdc_acm_class_inst_get(p_cdc_acm)); - nrf_drv_usbd_handler_desc_t const handler_desc = { - .handler.consumer = cdc_acm_consumer, - .p_context = p_cdc_acm_ctx - }; - - if (p_cdc_acm_ctx->bytes_left > 0) - { - memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf, - p_cdc_acm_ctx->p_copy_pos, - p_cdc_acm_ctx->bytes_left); - p_cdc_acm_ctx->rx_transfer[0].read_left -= p_cdc_acm_ctx->bytes_left; - p_cdc_acm_ctx->rx_transfer[0].p_buf += p_cdc_acm_ctx->bytes_left; - p_cdc_acm_ctx->bytes_read = p_cdc_acm_ctx->bytes_left; - p_cdc_acm_ctx->bytes_left = 0; - - } - ret = app_usbd_ep_handled_transfer(ep, &handler_desc); - if (ret == NRF_SUCCESS) - { - ret = NRF_ERROR_IO_PENDING; - } - } - } - else if (p_cdc_acm_ctx->rx_transfer[1].p_buf == NULL) - { - p_cdc_acm_ctx->rx_transfer[1].p_buf = p_buf; - p_cdc_acm_ctx->rx_transfer[1].read_left = length; - ret = NRF_ERROR_IO_PENDING; - } - else - { - ret = NRF_ERROR_BUSY; - } -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) - CRITICAL_REGION_EXIT(); -#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) - - return ret; -} - -ret_code_t app_usbd_cdc_acm_read_any(app_usbd_cdc_acm_t const * p_cdc_acm, - void * p_buf, - size_t length) -{ - ASSERT(p_buf != NULL); - ret_code_t ret; - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - if (0U == (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR)) - { - /*Port is not opened*/ - return NRF_ERROR_INVALID_STATE; - } - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) - CRITICAL_REGION_ENTER(); -#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) - if (p_cdc_acm_ctx->bytes_left > 0) - { - size_t to_copy = MIN(length, p_cdc_acm_ctx->bytes_left); - memcpy(p_buf, p_cdc_acm_ctx->p_copy_pos, to_copy); - p_cdc_acm_ctx->bytes_left -= to_copy; - p_cdc_acm_ctx->p_copy_pos += to_copy; - p_cdc_acm_ctx->last_read = to_copy; - ret = NRF_SUCCESS; - } - else - { - if (p_cdc_acm_ctx->rx_transfer[0].p_buf == NULL) - { - p_cdc_acm_ctx->rx_transfer[0].p_buf = p_buf; - p_cdc_acm_ctx->rx_transfer[0].read_left = length; - nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(app_usbd_cdc_acm_class_inst_get(p_cdc_acm)); - nrf_drv_usbd_handler_desc_t const handler_desc = { - .handler.consumer = cdc_acm_single_shoot_consumer, - .p_context = p_cdc_acm_ctx - }; - - ret = app_usbd_ep_handled_transfer(ep, &handler_desc); - if (ret == NRF_SUCCESS) - { - ret = NRF_ERROR_IO_PENDING; - } - } - else - { - ret = NRF_ERROR_BUSY; - } - } - -#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) - CRITICAL_REGION_EXIT(); -#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) - - return ret; -} - -static ret_code_t cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm) -{ - app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm); - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - nrf_drv_usbd_ep_t ep = comm_ep_in_addr_get(p_inst); - - NRF_DRV_USBD_TRANSFER_OUT(transfer, - &p_cdc_acm_ctx->request.payload, - sizeof(app_usbd_cdc_acm_notify_t)); - return app_usbd_ep_transfer(ep, &transfer); -} - -ret_code_t app_usbd_cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm, - app_usbd_cdc_acm_serial_state_t serial_state, - bool value) -{ - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - ret_code_t ret; - CRITICAL_REGION_ENTER(); - ret = NRF_SUCCESS; - switch (serial_state) - { - case APP_USBD_CDC_ACM_SERIAL_STATE_DCD: - case APP_USBD_CDC_ACM_SERIAL_STATE_DSR: - case APP_USBD_CDC_ACM_SERIAL_STATE_BREAK: - case APP_USBD_CDC_ACM_SERIAL_STATE_RING: - case APP_USBD_CDC_ACM_SERIAL_STATE_FRAMING: - case APP_USBD_CDC_ACM_SERIAL_STATE_PARITY: - case APP_USBD_CDC_ACM_SERIAL_STATE_OVERRUN: - - if (value) - { - p_cdc_acm_ctx->serial_state |= serial_state; - } - else - { - p_cdc_acm_ctx->serial_state &= ~serial_state; - } - - break; - default: - ret = NRF_ERROR_NOT_SUPPORTED; - break; - } - - if (ret == NRF_SUCCESS) - { - app_usbd_cdc_acm_notify_t * notify = &p_cdc_acm_ctx->request.payload.notify; - notify->cdc_notify.bmRequestType = app_usbd_setup_req_val(APP_USBD_SETUP_REQREC_INTERFACE, - APP_USBD_SETUP_REQTYPE_CLASS, - APP_USBD_SETUP_REQDIR_IN); - notify->cdc_notify.bmRequest = APP_USBD_CDC_NOTIF_SERIAL_STATE; - notify->cdc_notify.wValue = 0; - notify->cdc_notify.wIndex = 0; - notify->cdc_notify.wLength = sizeof(notify->serial_state); - - notify->serial_state = p_cdc_acm_ctx->serial_state; - - ret = cdc_acm_serial_state_notify(p_cdc_acm); - } - CRITICAL_REGION_EXIT(); - - return ret; -} - -ret_code_t app_usbd_cdc_acm_line_state_get(app_usbd_cdc_acm_t const * p_cdc_acm, - app_usbd_cdc_acm_line_state_t line_state, - uint32_t * value) -{ - app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); - - ret_code_t ret; - CRITICAL_REGION_ENTER(); - ret = NRF_SUCCESS; - switch (line_state) - { - case APP_USBD_CDC_ACM_LINE_STATE_DTR: - case APP_USBD_CDC_ACM_LINE_STATE_RTS: - *value = (p_cdc_acm_ctx->line_state & line_state) != 0; - break; - default: - ret = NRF_ERROR_NOT_SUPPORTED; - break; - } - CRITICAL_REGION_EXIT(); - - return ret; -} - -#endif //NRF_MODULE_ENABLED(APP_USBD_CDC_ACM) +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_USBD_CDC_ACM) + +#include "app_usbd_cdc_acm.h" +#include + +/** + * @defgroup app_usbd_cdc_acm_internal CDC ACM internals + * @{ + * @ingroup app_usbd_cdc + * @internal + */ + + +#define NRF_LOG_MODULE_NAME cdc_acm + +#if APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR APP_USBD_CDC_ACM_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR +#else //APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define APP_USBD_CDC_ACM_COMM_IFACE_IDX 0 /**< CDC ACM class comm interface index. */ +#define APP_USBD_CDC_ACM_DATA_IFACE_IDX 1 /**< CDC ACM class data interface index. */ + +#define APP_USBD_CDC_ACM_COMM_EPIN_IDX 0 /**< CDC ACM comm class endpoint IN index. */ +#define APP_USBD_CDC_ACM_DATA_EPIN_IDX 0 /**< CDC ACM data class endpoint IN index. */ +#define APP_USBD_CDC_ACM_DATA_EPOUT_IDX 1 /**< CDC ACM data class endpoint OUT index. */ + +/** + * @brief Auxiliary function to access cdc_acm class instance data. + * + * @param[in] p_inst Class instance data. + * + * @return CDC ACM class instance. + */ +static inline app_usbd_cdc_acm_t const * cdc_acm_get(app_usbd_class_inst_t const * p_inst) +{ + ASSERT(p_inst != NULL); + return (app_usbd_cdc_acm_t const *)p_inst; +} + +/** + * @brief Auxiliary function to access cdc_acm class context data. + * + * @param[in] p_cdc_acm CDC ACM class instance data. + * + * @return CDC ACM class instance context. + */ +static inline app_usbd_cdc_acm_ctx_t * cdc_acm_ctx_get(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + ASSERT(p_cdc_acm != NULL); + ASSERT(p_cdc_acm->specific.p_data != NULL); + return &p_cdc_acm->specific.p_data->ctx; +} + +/** + * @brief User event handler. + * + * @param[in] p_inst Class instance. + * @param[in] event user Event type. + */ +static inline void user_event_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_cdc_acm_user_event_t event) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + if (p_cdc_acm->specific.inst.user_ev_handler != NULL) + { + p_cdc_acm->specific.inst.user_ev_handler(p_inst, event); + } +} + +/** + * @brief Auxiliary function to access CDC ACM COMM IN endpoint address. + * + * @param[in] p_inst Class instance data. + * + * @return IN endpoint address. + */ +static inline nrf_drv_usbd_ep_t comm_ep_in_addr_get(app_usbd_class_inst_t const * p_inst) +{ + app_usbd_class_iface_conf_t const * class_iface; + class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_COMM_IFACE_IDX); + + app_usbd_class_ep_conf_t const * ep_cfg; + ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_COMM_EPIN_IDX); + + return app_usbd_class_ep_address_get(ep_cfg); +} + +/** + * @brief Auxiliary function to access CDC ACM DATA IN endpoint address. + * + * @param[in] p_inst Class instance data. + * + * @return IN endpoint address. + */ +static inline nrf_drv_usbd_ep_t data_ep_in_addr_get(app_usbd_class_inst_t const * p_inst) +{ + app_usbd_class_iface_conf_t const * class_iface; + class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_DATA_IFACE_IDX); + + app_usbd_class_ep_conf_t const * ep_cfg; + ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_DATA_EPIN_IDX); + + return app_usbd_class_ep_address_get(ep_cfg); +} + +/** + * @brief Auxiliary function to access CDC ACM DATA OUT endpoint address. + * + * @param[in] p_inst Class instance data. + * + * @return OUT endpoint address. + */ +static inline nrf_drv_usbd_ep_t data_ep_out_addr_get(app_usbd_class_inst_t const * p_inst) +{ + app_usbd_class_iface_conf_t const * class_iface; + class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_DATA_IFACE_IDX); + + app_usbd_class_ep_conf_t const * ep_cfg; + ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_DATA_EPOUT_IDX); + + return app_usbd_class_ep_address_get(ep_cfg); +} + +/** + * @brief Internal SETUP standard IN request handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_req_std_in(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + /* Only Get Descriptor standard IN request is supported by CDC class */ + if ((app_usbd_setup_req_rec(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQREC_INTERFACE) + && + (p_setup_ev->setup.bmRequest == APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR)) + { + size_t dsc_len = 0; + size_t max_size; + + uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size); + + /* Try to find descriptor in class internals*/ + ret_code_t ret = app_usbd_class_descriptor_find( + p_inst, + p_setup_ev->setup.wValue.hb, + p_setup_ev->setup.wValue.lb, + p_trans_buff, + &dsc_len); + + if (ret != NRF_ERROR_NOT_FOUND) + { + ASSERT(dsc_len < NRF_DRV_USBD_EPSIZE); + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_trans_buff, dsc_len); + } + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Internal SETUP standard OUT request handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_req_std_out(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + + switch (p_setup_ev->setup.bmRequest) + { + default: + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Internal SETUP class IN request handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_req_class_in(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_CDC_REQ_GET_LINE_CODING: + { + if (p_setup_ev->setup.wLength.w != sizeof(app_usbd_cdc_line_coding_t)) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + return app_usbd_core_setup_rsp(&p_setup_ev->setup, + &p_cdc_acm_ctx->line_coding, + sizeof(app_usbd_cdc_line_coding_t)); + } + default: + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Class specific OUT request data callback. + * + * @param status Endpoint status. + * @param p_context Context of transfer (set by @ref app_usbd_core_setup_data_handler_set). + * + * @return Standard error code. + */ +static ret_code_t cdc_acm_req_out_data_cb(nrf_drv_usbd_ep_status_t status, void * p_context) +{ + if (status != NRF_USBD_EP_OK) + { + return NRF_ERROR_INTERNAL; + } + + app_usbd_cdc_acm_t const * p_cdc_acm = p_context; + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + switch (p_cdc_acm_ctx->request.type) + { + case APP_USBD_CDC_REQ_SET_LINE_CODING: + { + memcpy(&p_cdc_acm_ctx->line_coding, + &p_cdc_acm_ctx->request.payload.line_coding, + sizeof(app_usbd_cdc_line_coding_t)); + + NRF_LOG_INFO("REQ_SET_LINE_CODING: baudrate: %"PRIu32", databits: %u, " + "format: %u, parity: %u", + uint32_decode(p_cdc_acm_ctx->line_coding.dwDTERate), + p_cdc_acm_ctx->line_coding.bDataBits, + p_cdc_acm_ctx->line_coding.bCharFormat, + p_cdc_acm_ctx->line_coding.bParityType); + break; + } + default: + return NRF_ERROR_NOT_SUPPORTED; + } + + return NRF_SUCCESS; +} + + +/** + * @brief Class specific request data stage setup. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t cdc_acm_req_out_datastage(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + p_cdc_acm_ctx->request.type = p_setup_ev->setup.bmRequest; + p_cdc_acm_ctx->request.len = p_setup_ev->setup.wLength.w; + + /*Request setup data*/ + NRF_DRV_USBD_TRANSFER_OUT(transfer, + &p_cdc_acm_ctx->request.payload, + p_cdc_acm_ctx->request.len); + ret_code_t ret; + CRITICAL_REGION_ENTER(); + ret = app_usbd_ep_transfer(NRF_DRV_USBD_EPOUT0, &transfer); + if (ret == NRF_SUCCESS) + { + const app_usbd_core_setup_data_handler_desc_t desc = { + .handler = cdc_acm_req_out_data_cb, + .p_context = (void*)p_cdc_acm + }; + + ret = app_usbd_core_setup_data_handler_set(NRF_DRV_USBD_EPOUT0, &desc); + } + CRITICAL_REGION_EXIT(); + + return ret; +} + +/** + * @brief Reset port to default state. + * + * @param p_inst Generic class instance. + */ +static void cdc_acm_reset_port(app_usbd_class_inst_t const * p_inst) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + p_cdc_acm_ctx->line_state = 0; + + // Set rx transfers configuration to default state. + p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; + p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; + p_cdc_acm_ctx->bytes_left = 0; + p_cdc_acm_ctx->bytes_read = 0; + p_cdc_acm_ctx->last_read = 0; + p_cdc_acm_ctx->cur_read = 0; + p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf; +} + +/** + * @brief Internal SETUP class OUT request handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_req_class_out(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_CDC_REQ_SET_LINE_CODING: + { + if (p_setup_ev->setup.wLength.w != sizeof(app_usbd_cdc_line_coding_t)) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + return cdc_acm_req_out_datastage(p_inst, p_setup_ev); + } + case APP_USBD_CDC_REQ_SET_CONTROL_LINE_STATE: + { + if (p_setup_ev->setup.wLength.w != 0) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + NRF_LOG_INFO("REQ_SET_CONTROL_LINE_STATE: 0x%x", p_setup_ev->setup.wValue.w); + + bool old_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? + true : false; + p_cdc_acm_ctx->line_state = p_setup_ev->setup.wValue.w; + + bool new_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? + true : false; + + if (old_dtr == new_dtr) + { + return NRF_SUCCESS; + } + + const app_usbd_cdc_acm_user_event_t ev = new_dtr ? + APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN : APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE; + + user_event_handler(p_inst, ev); + + if (!new_dtr) + { + /*Abort DATA endpoints on port close */ + nrf_drv_usbd_ep_t ep; + ep = data_ep_in_addr_get(p_inst); + nrf_drv_usbd_ep_abort(ep); + ep = data_ep_out_addr_get(p_inst); + nrf_drv_usbd_ep_abort(ep); + + // Set rx transfers configuration to default state. + p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; + p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; + p_cdc_acm_ctx->bytes_left = 0; + p_cdc_acm_ctx->bytes_read = 0; + p_cdc_acm_ctx->last_read = 0; + p_cdc_acm_ctx->cur_read = 0; + p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf; + } + + return NRF_SUCCESS; + } + default: + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Control endpoint handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_event_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + ASSERT(p_inst != NULL); + ASSERT(p_setup_ev != NULL); + + if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN) + { + switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) + { + case APP_USBD_SETUP_REQTYPE_STD: + return setup_req_std_in(p_inst, p_setup_ev); + case APP_USBD_SETUP_REQTYPE_CLASS: + return setup_req_class_in(p_inst, p_setup_ev); + default: + break; + } + } + else /*APP_USBD_SETUP_REQDIR_OUT*/ + { + switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) + { + case APP_USBD_SETUP_REQTYPE_STD: + return setup_req_std_out(p_inst, p_setup_ev); + case APP_USBD_SETUP_REQTYPE_CLASS: + return setup_req_class_out(p_inst, p_setup_ev); + default: + break; + } + } + + return NRF_ERROR_NOT_SUPPORTED; +} + + +/** + * @brief CDC ACM consumer. + * + * @note See @ref nrf_drv_usbd_consumer_t + */ +static bool cdc_acm_consumer(nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size, + size_t data_size) +{ + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = (app_usbd_cdc_acm_ctx_t *) p_context; + p_next->size = data_size; + + if (data_size <= p_cdc_acm_ctx->rx_transfer[0].read_left) + { + p_next->p_data.rx = p_cdc_acm_ctx->rx_transfer[0].p_buf; + + p_cdc_acm_ctx->rx_transfer[0].p_buf += data_size; + p_cdc_acm_ctx->bytes_read += data_size; + p_cdc_acm_ctx->rx_transfer[0].read_left -= data_size; + NRF_LOG_DEBUG("Received %d bytes. Space left in user buffer: %d bytes.", + data_size, + p_cdc_acm_ctx->rx_transfer[0].read_left); + return (p_cdc_acm_ctx->rx_transfer[0].read_left) != 0; + } + else + { + p_next->p_data.rx = p_cdc_acm_ctx->internal_rx_buf; + + p_cdc_acm_ctx->cur_read = data_size; + NRF_LOG_DEBUG("Received %d bytes. Stored in internal buffer.", data_size); + return false; + } +} + +/** + * @brief CDC ACM single transfer consumer. + * + * This function finalizes transfer after any received block. + * + * @note See @ref nrf_drv_usbd_consumer_t + */ +static bool cdc_acm_single_shoot_consumer(nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size, + size_t data_size) +{ + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = (app_usbd_cdc_acm_ctx_t *) p_context; + p_next->size = data_size; + + if (data_size <= p_cdc_acm_ctx->rx_transfer[0].read_left) + { + p_next->p_data.rx = p_cdc_acm_ctx->rx_transfer[0].p_buf; + + p_cdc_acm_ctx->bytes_read = data_size; + p_cdc_acm_ctx->rx_transfer[0].read_left = data_size; + NRF_LOG_DEBUG("Received %d bytes. Space left in user buffer: %d bytes.", + data_size, + p_cdc_acm_ctx->rx_transfer[0].read_left); + } + else + { + p_next->p_data.rx = p_cdc_acm_ctx->internal_rx_buf; + p_cdc_acm_ctx->cur_read = data_size; + NRF_LOG_DEBUG("Received %d bytes. Stored in internal buffer.", data_size); + } + + return false; +} + +/** + * @brief Manage switching between user buffers and copying data from internal buffer. + * + * @param p_inst Generic USB class instance. + * + * @return Standard error code. + */ +static ret_code_t cdc_acm_rx_block_finished(app_usbd_class_inst_t const * p_inst) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(p_inst); + + nrf_drv_usbd_handler_desc_t handler_desc = { + .handler.consumer = cdc_acm_consumer, + .p_context = p_cdc_acm_ctx + }; + + if (p_cdc_acm_ctx->rx_transfer[0].read_left == 0) // Buffer completely filled by consumer + { + p_cdc_acm_ctx->last_read = p_cdc_acm_ctx->bytes_read; + p_cdc_acm_ctx->bytes_read = 0; + p_cdc_acm_ctx->bytes_left = 0; + + if (p_cdc_acm_ctx->rx_transfer[1].p_buf != NULL) + { + p_cdc_acm_ctx->rx_transfer[0] = p_cdc_acm_ctx->rx_transfer[1]; + p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; + return app_usbd_ep_handled_transfer(ep, &handler_desc); + } + else + { + p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; + return NRF_SUCCESS; + } + } + + size_t bytes_read = p_cdc_acm_ctx->cur_read; + size_t bytes_to_cpy = bytes_read; + + if (bytes_read > p_cdc_acm_ctx->rx_transfer[0].read_left) + { + bytes_to_cpy = p_cdc_acm_ctx->rx_transfer[0].read_left; + } + memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf, + p_cdc_acm_ctx->internal_rx_buf, + bytes_to_cpy); + + // First buffer is full + p_cdc_acm_ctx->last_read = p_cdc_acm_ctx->bytes_read + bytes_to_cpy; + p_cdc_acm_ctx->bytes_read = 0; + p_cdc_acm_ctx->bytes_left = bytes_read - bytes_to_cpy; + p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf + bytes_to_cpy; + + if (p_cdc_acm_ctx->rx_transfer[1].p_buf != NULL) + { + // If there is second transfer, copy it to first + p_cdc_acm_ctx->rx_transfer[0] = p_cdc_acm_ctx->rx_transfer[1]; + p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; + + while (p_cdc_acm_ctx->bytes_left > 0) + { + + if (p_cdc_acm_ctx->bytes_left >= p_cdc_acm_ctx->rx_transfer[0].read_left) + { + // If there are enough bytes left in internal buffer to completely fill next transfer, + // we call user event handler to obtain next buffer and continue double buffering. + memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf, + p_cdc_acm_ctx->p_copy_pos, + p_cdc_acm_ctx->rx_transfer[0].read_left); + + p_cdc_acm_ctx->bytes_left -= p_cdc_acm_ctx->rx_transfer[0].read_left; + p_cdc_acm_ctx->p_copy_pos += p_cdc_acm_ctx->rx_transfer[0].read_left; + p_cdc_acm_ctx->last_read = p_cdc_acm_ctx->rx_transfer[0].read_left; + user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_RX_DONE); + + if (p_cdc_acm_ctx->rx_transfer[1].p_buf != NULL) + { + p_cdc_acm_ctx->rx_transfer[0] = p_cdc_acm_ctx->rx_transfer[1]; + p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL; + } + else + { + // If user does not specify a second buffer, all data transfers are done + // and data left in internal buffer is lost. + p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; + break; + } + } + else + { + memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf, + p_cdc_acm_ctx->p_copy_pos, + p_cdc_acm_ctx->bytes_left); + p_cdc_acm_ctx->bytes_read = p_cdc_acm_ctx->bytes_left; + + p_cdc_acm_ctx->rx_transfer[0].read_left -= p_cdc_acm_ctx->bytes_left; + p_cdc_acm_ctx->rx_transfer[0].p_buf += p_cdc_acm_ctx->bytes_left; + break; + } + } + + + } + else + { + p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL; + } + + if (p_cdc_acm_ctx->rx_transfer[0].p_buf != NULL) + { + return app_usbd_ep_handled_transfer(ep, &handler_desc); + } + return NRF_SUCCESS; +} + +/** + * @brief Class specific endpoint transfer handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t cdc_acm_endpoint_ev(app_usbd_class_inst_t const * p_inst, + app_usbd_complex_evt_t const * p_event) +{ + if (comm_ep_in_addr_get(p_inst) == p_event->drv_evt.data.eptransfer.ep) + { + NRF_LOG_INFO("EPIN_COMM: notify"); + return NRF_SUCCESS; + } + ret_code_t ret; + if (NRF_USBD_EPIN_CHECK(p_event->drv_evt.data.eptransfer.ep)) + { + switch (p_event->drv_evt.data.eptransfer.status) + { + case NRF_USBD_EP_OK: + NRF_LOG_INFO("EPIN_DATA: %02x done", p_event->drv_evt.data.eptransfer.ep); + user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_TX_DONE); + return NRF_SUCCESS; + case NRF_USBD_EP_ABORTED: + return NRF_SUCCESS; + default: + return NRF_ERROR_INTERNAL; + } + } + + if (NRF_USBD_EPOUT_CHECK(p_event->drv_evt.data.eptransfer.ep)) + { + switch (p_event->drv_evt.data.eptransfer.status) + { + case NRF_USBD_EP_OK: + ret = cdc_acm_rx_block_finished(p_inst); + NRF_LOG_INFO("EPOUT_DATA: %02x done", p_event->drv_evt.data.eptransfer.ep); + user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_RX_DONE); + return ret; + case NRF_USBD_EP_WAITING: + case NRF_USBD_EP_ABORTED: + return NRF_SUCCESS; + default: + return NRF_ERROR_INTERNAL; + } + } + + return NRF_ERROR_NOT_SUPPORTED; +} + + +/** + * @brief @ref app_usbd_class_methods_t::event_handler + */ +static ret_code_t cdc_acm_event_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_complex_evt_t const * p_event) +{ + ASSERT(p_inst != NULL); + ASSERT(p_event != NULL); + + ret_code_t ret = NRF_SUCCESS; + switch (p_event->app_evt.type) + { + case APP_USBD_EVT_DRV_SOF: + break; + case APP_USBD_EVT_DRV_RESET: + cdc_acm_reset_port(p_inst); + break; + case APP_USBD_EVT_DRV_SETUP: + ret = setup_event_handler(p_inst, (app_usbd_setup_evt_t const *)p_event); + break; + case APP_USBD_EVT_DRV_EPTRANSFER: + ret = cdc_acm_endpoint_ev(p_inst, p_event); + break; + case APP_USBD_EVT_DRV_SUSPEND: + break; + case APP_USBD_EVT_DRV_RESUME: + break; + case APP_USBD_EVT_INST_APPEND: + break; + case APP_USBD_EVT_INST_REMOVE: + break; + case APP_USBD_EVT_STARTED: + break; + case APP_USBD_EVT_STOPPED: + break; + case APP_USBD_EVT_POWER_REMOVED: + cdc_acm_reset_port(p_inst); + break; + default: + ret = NRF_ERROR_NOT_SUPPORTED; + break; + } + + return ret; +} + + +static bool cdc_acm_feed_descriptors(app_usbd_class_descriptor_ctx_t * p_ctx, + app_usbd_class_inst_t const * p_inst, + uint8_t * p_buff, + size_t max_size) +{ + static uint8_t ifaces = 0; + ifaces = app_usbd_class_iface_count_get(p_inst); + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + + APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size); + + /* INTERFACE ASSOCIATION DESCRIPTOR */ + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x08); // bLength + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE_ASSOCIATION); // bDescriptorType = Interface Association + APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.comm_interface); // bFirstInterface + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x02); // bInterfaceCount + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_COMM_CLASS); // bFunctionClass + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SUBCLASS_ACM); // bFunctionSubClass + APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.protocol); // bFunctionProtocol + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iFunction + + static uint8_t i = 0; + + for (i = 0; i < ifaces; i++) + { + /* INTERFACE DESCRIPTOR */ + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE); // bDescriptorType = Interface + + static app_usbd_class_iface_conf_t const * p_cur_iface = NULL; + p_cur_iface = app_usbd_class_iface_get(p_inst, i); + + APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_number_get(p_cur_iface)); // bInterfaceNumber + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bAlternateSetting + APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_ep_count_get(p_cur_iface)); // bNumEndpoints + + if (p_cdc_acm->specific.inst.comm_interface == app_usbd_class_iface_number_get(p_cur_iface)) + { + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_COMM_CLASS); // bInterfaceClass = CDC COMM + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SUBCLASS_ACM); // bInterfaceSubclass + APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.protocol); // bInterfaceProtocol + } + else if (p_cdc_acm->specific.inst.data_interface == + app_usbd_class_iface_number_get(p_cur_iface)) + { + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_DATA_CLASS); // bInterfaceClass = CDC DATA + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterfaceSubclass + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterfaceProtocol + } + else + { + ASSERT(0); + } + + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iInterface + + if (p_cdc_acm->specific.inst.comm_interface == app_usbd_class_iface_number_get(p_cur_iface)) + { + /* HEADER DESCRIPTOR */ + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x05); // bLength + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_HEADER); // bDescriptorSubtype = Header Functional Descriptor + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x10); // bcdCDC LSB + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x01); // bcdCDC MSB + + /* CALL MANAGEMENT DESCRIPTOR */ + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x05); // bLength + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_CALL_MGMT); // bDescriptorSubtype = Call Management Functional Descriptor + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x03); // bmCapabilities + APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.data_interface); // bDataInterface + + /* ABSTRACT CONTROL MANAGEMENT DESCRIPTOR */ + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x04); // bLength + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_ACM); // bDescriptorSubtype = Abstract Control Management Functional Descriptor + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x02); // bmCapabilities + + /* UNION DESCRIPTOR */ + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x05); + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_UNION); // bDescriptorSubtype = Union Functional Descriptor + APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.comm_interface); // bControlInterface + APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.data_interface); // bSubordinateInterface + } + else if (p_cdc_acm->specific.inst.data_interface == + app_usbd_class_iface_number_get(p_cur_iface)) + { + ; + } + else + { + ASSERT(0); + } + + /* ENDPOINT DESCRIPTORS */ + static uint8_t endpoints = 0; + endpoints = app_usbd_class_iface_ep_count_get(p_cur_iface); + + static uint8_t j = 0; + + for (j = 0; j < endpoints; j++) + { + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x07); // bLength + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_ENDPOINT); // bDescriptorType = Endpoint + + static app_usbd_class_ep_conf_t const * p_cur_ep = NULL; + p_cur_ep = app_usbd_class_iface_ep_get(p_cur_iface, j); + APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_ep_address_get(p_cur_ep)); // bEndpointAddress + + if (p_cdc_acm->specific.inst.comm_interface == + app_usbd_class_iface_number_get(p_cur_iface)) + { + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_INTERRUPT); // bmAttributes + } + else if (p_cdc_acm->specific.inst.data_interface == + app_usbd_class_iface_number_get(p_cur_iface)) + { + APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK); // bmAttributes + } + else + { + ASSERT(0); + } + + APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize LSB + APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize MSB + + if (p_cdc_acm->specific.inst.comm_interface == + app_usbd_class_iface_number_get(p_cur_iface)) + { + APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.p_ep_interval[0]); // bInterval + } + else if (p_cdc_acm->specific.inst.data_interface == + app_usbd_class_iface_number_get(p_cur_iface)) + { + APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterval + } + else + { + ASSERT(0); + } + + } + + } + + APP_USBD_CLASS_DESCRIPTOR_END(); +} + +/** + * @brief Public cdc_acm class interface. + * + */ +const app_usbd_class_methods_t app_usbd_cdc_acm_class_methods = { + .event_handler = cdc_acm_event_handler, + .feed_descriptors = cdc_acm_feed_descriptors, +}; + +/** @} */ + +ret_code_t app_usbd_cdc_acm_write(app_usbd_cdc_acm_t const * p_cdc_acm, + const void * p_buf, + size_t length) +{ + app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + bool dtr_state = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? + true : false; + if (!dtr_state) + { + /*Port is not opened*/ + return NRF_ERROR_INVALID_STATE; + } + + nrf_drv_usbd_ep_t ep = data_ep_in_addr_get(p_inst); + + if (APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE && ((length % NRF_DRV_USBD_EPSIZE) == 0)) + { + NRF_DRV_USBD_TRANSFER_IN_ZLP(transfer, p_buf, length); + return app_usbd_ep_transfer(ep, &transfer); + } + else + { + NRF_DRV_USBD_TRANSFER_IN(transfer, p_buf, length); + return app_usbd_ep_transfer(ep, &transfer); + } +} + +size_t app_usbd_cdc_acm_rx_size(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + return p_cdc_acm_ctx->last_read; +} + +size_t app_usbd_cdc_acm_bytes_stored(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + return p_cdc_acm_ctx->bytes_left; +} + +ret_code_t app_usbd_cdc_acm_read(app_usbd_cdc_acm_t const * p_cdc_acm, + void * p_buf, + size_t length) +{ + ASSERT(p_buf != NULL); + ret_code_t ret; + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + if (0U == (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR)) + { + /*Port is not opened*/ + return NRF_ERROR_INVALID_STATE; + } + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) + CRITICAL_REGION_ENTER(); +#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) + + if (p_cdc_acm_ctx->rx_transfer[0].p_buf == NULL) + { + if (p_cdc_acm_ctx->bytes_left >= length) + { + memcpy(p_buf, p_cdc_acm_ctx->p_copy_pos, length); + p_cdc_acm_ctx->bytes_left -= length; + p_cdc_acm_ctx->p_copy_pos += length; + p_cdc_acm_ctx->last_read = length; + ret = NRF_SUCCESS; + } + else + { + p_cdc_acm_ctx->rx_transfer[0].p_buf = p_buf; + p_cdc_acm_ctx->rx_transfer[0].read_left = length; + nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(app_usbd_cdc_acm_class_inst_get(p_cdc_acm)); + nrf_drv_usbd_handler_desc_t const handler_desc = { + .handler.consumer = cdc_acm_consumer, + .p_context = p_cdc_acm_ctx + }; + + if (p_cdc_acm_ctx->bytes_left > 0) + { + memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf, + p_cdc_acm_ctx->p_copy_pos, + p_cdc_acm_ctx->bytes_left); + p_cdc_acm_ctx->rx_transfer[0].read_left -= p_cdc_acm_ctx->bytes_left; + p_cdc_acm_ctx->rx_transfer[0].p_buf += p_cdc_acm_ctx->bytes_left; + p_cdc_acm_ctx->bytes_read = p_cdc_acm_ctx->bytes_left; + p_cdc_acm_ctx->bytes_left = 0; + + } + ret = app_usbd_ep_handled_transfer(ep, &handler_desc); + if (ret == NRF_SUCCESS) + { + ret = NRF_ERROR_IO_PENDING; + } + } + } + else if (p_cdc_acm_ctx->rx_transfer[1].p_buf == NULL) + { + p_cdc_acm_ctx->rx_transfer[1].p_buf = p_buf; + p_cdc_acm_ctx->rx_transfer[1].read_left = length; + ret = NRF_ERROR_IO_PENDING; + } + else + { + ret = NRF_ERROR_BUSY; + } +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) + CRITICAL_REGION_EXIT(); +#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) + + return ret; +} + +ret_code_t app_usbd_cdc_acm_read_any(app_usbd_cdc_acm_t const * p_cdc_acm, + void * p_buf, + size_t length) +{ + ASSERT(p_buf != NULL); + ret_code_t ret; + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + if (0U == (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR)) + { + /*Port is not opened*/ + return NRF_ERROR_INVALID_STATE; + } + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) + CRITICAL_REGION_ENTER(); +#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) + if (p_cdc_acm_ctx->bytes_left > 0) + { + size_t to_copy = MIN(length, p_cdc_acm_ctx->bytes_left); + memcpy(p_buf, p_cdc_acm_ctx->p_copy_pos, to_copy); + p_cdc_acm_ctx->bytes_left -= to_copy; + p_cdc_acm_ctx->p_copy_pos += to_copy; + p_cdc_acm_ctx->last_read = to_copy; + ret = NRF_SUCCESS; + } + else + { + if (p_cdc_acm_ctx->rx_transfer[0].p_buf == NULL) + { + p_cdc_acm_ctx->rx_transfer[0].p_buf = p_buf; + p_cdc_acm_ctx->rx_transfer[0].read_left = length; + nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(app_usbd_cdc_acm_class_inst_get(p_cdc_acm)); + nrf_drv_usbd_handler_desc_t const handler_desc = { + .handler.consumer = cdc_acm_single_shoot_consumer, + .p_context = p_cdc_acm_ctx + }; + + ret = app_usbd_ep_handled_transfer(ep, &handler_desc); + if (ret == NRF_SUCCESS) + { + ret = NRF_ERROR_IO_PENDING; + } + } + else + { + ret = NRF_ERROR_BUSY; + } + } + +#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) + CRITICAL_REGION_EXIT(); +#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0) + + return ret; +} + +static ret_code_t cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + nrf_drv_usbd_ep_t ep = comm_ep_in_addr_get(p_inst); + + NRF_DRV_USBD_TRANSFER_OUT(transfer, + &p_cdc_acm_ctx->request.payload, + sizeof(app_usbd_cdc_acm_notify_t)); + return app_usbd_ep_transfer(ep, &transfer); +} + +ret_code_t app_usbd_cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm, + app_usbd_cdc_acm_serial_state_t serial_state, + bool value) +{ + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + ret_code_t ret; + CRITICAL_REGION_ENTER(); + ret = NRF_SUCCESS; + switch (serial_state) + { + case APP_USBD_CDC_ACM_SERIAL_STATE_DCD: + case APP_USBD_CDC_ACM_SERIAL_STATE_DSR: + case APP_USBD_CDC_ACM_SERIAL_STATE_BREAK: + case APP_USBD_CDC_ACM_SERIAL_STATE_RING: + case APP_USBD_CDC_ACM_SERIAL_STATE_FRAMING: + case APP_USBD_CDC_ACM_SERIAL_STATE_PARITY: + case APP_USBD_CDC_ACM_SERIAL_STATE_OVERRUN: + + if (value) + { + p_cdc_acm_ctx->serial_state |= serial_state; + } + else + { + p_cdc_acm_ctx->serial_state &= ~serial_state; + } + + break; + default: + ret = NRF_ERROR_NOT_SUPPORTED; + break; + } + + if (ret == NRF_SUCCESS) + { + app_usbd_cdc_acm_notify_t * notify = &p_cdc_acm_ctx->request.payload.notify; + notify->cdc_notify.bmRequestType = app_usbd_setup_req_val(APP_USBD_SETUP_REQREC_INTERFACE, + APP_USBD_SETUP_REQTYPE_CLASS, + APP_USBD_SETUP_REQDIR_IN); + notify->cdc_notify.bmRequest = APP_USBD_CDC_NOTIF_SERIAL_STATE; + notify->cdc_notify.wValue = 0; + notify->cdc_notify.wIndex = 0; + notify->cdc_notify.wLength = sizeof(notify->serial_state); + + notify->serial_state = p_cdc_acm_ctx->serial_state; + + ret = cdc_acm_serial_state_notify(p_cdc_acm); + } + CRITICAL_REGION_EXIT(); + + return ret; +} + +ret_code_t app_usbd_cdc_acm_line_state_get(app_usbd_cdc_acm_t const * p_cdc_acm, + app_usbd_cdc_acm_line_state_t line_state, + uint32_t * value) +{ + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + ret_code_t ret; + CRITICAL_REGION_ENTER(); + ret = NRF_SUCCESS; + switch (line_state) + { + case APP_USBD_CDC_ACM_LINE_STATE_DTR: + case APP_USBD_CDC_ACM_LINE_STATE_RTS: + *value = (p_cdc_acm_ctx->line_state & line_state) != 0; + break; + default: + ret = NRF_ERROR_NOT_SUPPORTED; + break; + } + CRITICAL_REGION_EXIT(); + + return ret; +} + +#endif //NRF_MODULE_ENABLED(APP_USBD_CDC_ACM) diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.h b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.h index f6c00d0b4..4c8ccbeec 100644 --- a/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.h +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.h @@ -1,362 +1,362 @@ -/** - * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef APP_USBD_CDC_ACM_H__ -#define APP_USBD_CDC_ACM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "nrf_drv_usbd.h" -#include "app_usbd_class_base.h" -#include "app_usbd.h" -#include "app_usbd_core.h" -#include "app_usbd_descriptor.h" - -#include "app_usbd_cdc_desc.h" -#include "app_usbd_cdc_types.h" -#include "app_usbd_cdc_acm_internal.h" - -/** - * @defgroup app_usbd_cdc_acm USB CDC ACM class - * @ingroup app_usbd - * - * @brief @tagAPI52840 Module with types, definitions and API used by CDC ACM class. - * - * @details References: - * - "Universal Serial Bus Class Definitions for Communications Devices" - * Revision 1.2, November 3, 2010 - * - "Universal Serial Bus Communications Class Subclass Specification for PSTN Devices" - * Revision 1.2, February 9, 2007 - * - * @{ - */ - -#ifdef DOXYGEN -/** - * @brief CDC ACM class instance type. - * - * @ref APP_USBD_CLASS_TYPEDEF - */ -typedef struct { } app_usbd_cdc_acm_t; -#else -/*lint -save -e10 -e26 -e123 -e505 */ -APP_USBD_CLASS_TYPEDEF(app_usbd_cdc_acm, \ - APP_USBD_CDC_ACM_CONFIG(0, 0, 0, 0, 0), \ - APP_USBD_CDC_ACM_INSTANCE_SPECIFIC_DEC, \ - APP_USBD_CDC_ACM_DATA_SPECIFIC_DEC \ -); -/*lint -restore*/ -#endif - - -/*lint -save -e407 */ - -/** - * @brief Events passed to user event handler. - * - * @note Example prototype of user event handler: - * - * @code - void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, - app_usbd_cdc_acm_user_event_t event); - * @endcode - */ -typedef enum app_usbd_cdc_acm_user_event_e { - APP_USBD_CDC_ACM_USER_EVT_RX_DONE, /**< User event RX_DONE. */ - APP_USBD_CDC_ACM_USER_EVT_TX_DONE, /**< User event TX_DONE. */ - - APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN, /**< User event PORT_OPEN. */ - APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE, /**< User event PORT_CLOSE. */ -} app_usbd_cdc_acm_user_event_t; - -/*lint -restore*/ - -/** - * @brief Default CDC ACM descriptors. - * - * @param comm_interface COMM interface number. - * @param comm_epin COMM interface IN endpoint. - * @param data_interface DATA interface number. - * @param data_epin DATA interface IN endpoint. - * @param data_epout DATA interface OUT endpoint. - */ -#define APP_USBD_CDC_ACM_DEFAULT_DESC(comm_interface, \ - comm_epin, \ - data_interface, \ - data_epin, \ - data_epout) \ - APP_USBD_CDC_IAD_DSC(comm_interface, \ - APP_USBD_CDC_SUBCLASS_ACM, \ - APP_USBD_CDC_COMM_PROTOCOL_AT_V250) \ - APP_USBD_CDC_COMM_INTERFACE_DSC(comm_interface, \ - APP_USBD_CDC_SUBCLASS_ACM, \ - APP_USBD_CDC_COMM_PROTOCOL_AT_V250) \ - APP_USBD_CDC_HEADER_DSC(0x0110) \ - APP_USBD_CDC_CALL_MGMT_DSC(0x03, data_interface) \ - APP_USBD_CDC_ACM_DSC(0x02) \ - APP_USBD_CDC_UNION_DSC(comm_interface, data_interface) \ - APP_USBD_CDC_COM_EP_DSC(comm_epin, NRF_DRV_USBD_EPSIZE) \ - APP_USBD_CDC_DATA_INTERFACE_DSC(data_interface, 0, 0) \ - APP_USBD_CDC_DATA_EP_DSC(data_epin, data_epout, NRF_DRV_USBD_EPSIZE) - -/** - * @brief Global definition of app_usbd_cdc_acm_t class instance. - * - * @param instance_name Name of global instance. - * @param user_ev_handler User event handler (optional). - * @param comm_ifc Interface number of cdc_acm control. - * @param data_ifc Interface number of cdc_acm DATA. - * @param comm_ein COMM subclass IN endpoint. - * @param data_ein DATA subclass IN endpoint. - * @param data_eout DATA subclass OUT endpoint. - * @param cdc_protocol CDC protocol @ref app_usbd_cdc_comm_protocol_t - * - * @note This macro is just simplified version of @ref APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL. - * - */ -#define APP_USBD_CDC_ACM_GLOBAL_DEF(instance_name, \ - user_ev_handler, \ - comm_ifc, \ - data_ifc, \ - comm_ein, \ - data_ein, \ - data_eout, \ - cdc_protocol) \ - APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL(instance_name, \ - user_ev_handler, \ - comm_ifc, \ - data_ifc, \ - comm_ein, \ - data_ein, \ - data_eout, \ - cdc_protocol) \ - -/** - * @brief Helper function to get class instance from CDC ACM class. - * - * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). - * - * @return Base class instance. - */ -static inline app_usbd_class_inst_t const * -app_usbd_cdc_acm_class_inst_get(app_usbd_cdc_acm_t const * p_cdc_acm) -{ - return &p_cdc_acm->base; -} - -/** - * @brief Helper function to get cdc_acm specific request from cdc_acm class. - * - * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). - * - * @return CDC ACM class specific request. - */ -static inline app_usbd_cdc_acm_req_t * -app_usbd_cdc_acm_class_request_get(app_usbd_cdc_acm_t const * p_cdc_acm) -{ - return &p_cdc_acm->specific.p_data->ctx.request; -} - -/** - * @brief Helper function to get cdc_acm from base class instance. - * - * @param[in] p_inst Base class instance. - * - * @return CDC ACM class handle. - */ -static inline app_usbd_cdc_acm_t const * -app_usbd_cdc_acm_class_get(app_usbd_class_inst_t const * p_inst) -{ - return (app_usbd_cdc_acm_t const *)p_inst; -} - - -/** - * @brief Writes data to CDC ACM serial port. - * - * This is asynchronous call. User should wait for @ref APP_USBD_CDC_ACM_USER_EVT_TX_DONE event - * to be sure that all data has been sent and input buffer could be accessed again. - * - * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). - * @param[in] p_buf Input buffer. - * @param[in] length Input buffer length. - * - * @return Standard error code. - */ -ret_code_t app_usbd_cdc_acm_write(app_usbd_cdc_acm_t const * p_cdc_acm, - const void * p_buf, - size_t length); - -/** - * @brief Returns the amount of data that was read. - * - * This function should be used on @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event to get - * information how many bytes have been transfered into user buffer. - * - * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). - * - * @return Amount of data transfered. - */ -size_t app_usbd_cdc_acm_rx_size(app_usbd_cdc_acm_t const * p_cdc_acm); - -/** - * @brief Returns the amount of data that was stored into internal buffer - * - * This function should be used on @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event to get - * information how many bytes are waiting in internal buffer. - * - * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). - * - * @return Amount of data waiting. - */ -size_t app_usbd_cdc_acm_bytes_stored(app_usbd_cdc_acm_t const * p_cdc_acm); - -/** - * @brief Reads data from CDC ACM serial port. - * - * This function uses internal buffer and double buffering for continuous transmission. - * - * If there is enough data in internal buffer to fill user buffer, NRF_SUCCESS is - * returned and data is immediately available in the user buffer. - * - * If not, up to two user buffers can be scheduled, function returns NRF_ERROR_IO_PENDING - * when first buffer is filled and @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event is generated. - * - * @sa app_usbd_cdc_acm_read_any - * @sa app_usbd_cdc_acm_rx_size - * - * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). - * @param[out] p_buf Output buffer. - * @param[in] length Number of bytes to read. - * - * @retval NRF_SUCCESS Data is stored into user buffer. - * @retval NRF_ERROR_IO_PENDING Awaiting transmission, when data is stored into user buffer, - * @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event will be raised. - * @retval NRF_ERROR_BUSY There are already 2 buffers queued for transfers. - * @retval other Standard error code. - */ -ret_code_t app_usbd_cdc_acm_read(app_usbd_cdc_acm_t const * p_cdc_acm, - void * p_buf, - size_t length); - -/** - * @brief Read any data from CDC ACM port up to given buffer size - * - * This function is very similar to the @ref app_usbd_cdc_acm_read but it returns - * data as quick as any data is available, even if the given buffer was not totally full. - * - * @note This function cannot use double buffering. - * @note To check the number of bytes really read use @ref app_usbd_cdc_acm_rx_size - * function. - * - * @sa app_usbd_cdc_acm_read - * @sa app_usbd_cdc_acm_rx_size - * - * @param p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). - * @param[out] p_buf Output buffer. - * @param[in] length Maximum number of bytes to read. - * - * @retval NRF_SUCCESS Data is stored into user buffer. - * @retval NRF_ERROR_IO_PENDING Awaiting transmission, when data is stored into user buffer, - * @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event will be raised. - * @retval NRF_ERROR_BUSY There is already buffer set for a transfer. - * @retval other Standard error code. - */ -ret_code_t app_usbd_cdc_acm_read_any(app_usbd_cdc_acm_t const * p_cdc_acm, - void * p_buf, - size_t length); - -/** - * @brief Serial state notifications. - * */ -typedef enum { - APP_USBD_CDC_ACM_SERIAL_STATE_DCD = (1u << 0), /**< Notification bit DCD. */ - APP_USBD_CDC_ACM_SERIAL_STATE_DSR = (1u << 1), /**< Notification bit DSR. */ - APP_USBD_CDC_ACM_SERIAL_STATE_BREAK = (1u << 2), /**< Notification bit BREAK. */ - APP_USBD_CDC_ACM_SERIAL_STATE_RING = (1u << 3), /**< Notification bit RING. */ - APP_USBD_CDC_ACM_SERIAL_STATE_FRAMING = (1u << 4), /**< Notification bit FRAMING.*/ - APP_USBD_CDC_ACM_SERIAL_STATE_PARITY = (1u << 5), /**< Notification bit PARITY. */ - APP_USBD_CDC_ACM_SERIAL_STATE_OVERRUN = (1u << 6), /**< Notification bit OVERRUN.*/ -} app_usbd_cdc_acm_serial_state_t; - -/** - * @brief Serial line state. - */ -typedef enum { - APP_USBD_CDC_ACM_LINE_STATE_DTR = (1u << 0), /**< Line state bit DTR.*/ - APP_USBD_CDC_ACM_LINE_STATE_RTS = (1u << 1), /**< Line state bit RTS.*/ -} app_usbd_cdc_acm_line_state_t; - -/** - * @brief Serial state notification via IN interrupt endpoint. - * - * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). - * @param[in] serial_state Serial state notification type. - * @param[in] value Serial state value. - * - * @return Standard error code. - */ -ret_code_t app_usbd_cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm, - app_usbd_cdc_acm_serial_state_t serial_state, - bool value); - -/** - * @brief Control line value get. - * - * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). - * @param[in] line_state Line control value type. - * @param[out] value Line control value. - * - * @return Standard error code. - */ -ret_code_t app_usbd_cdc_acm_line_state_get(app_usbd_cdc_acm_t const * p_cdc_acm, - app_usbd_cdc_acm_line_state_t line_state, - uint32_t * value); - -/** @} */ -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_CDC_ACM_H__ */ +/** + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef APP_USBD_CDC_ACM_H__ +#define APP_USBD_CDC_ACM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "nrf_drv_usbd.h" +#include "app_usbd_class_base.h" +#include "app_usbd.h" +#include "app_usbd_core.h" +#include "app_usbd_descriptor.h" + +#include "app_usbd_cdc_desc.h" +#include "app_usbd_cdc_types.h" +#include "app_usbd_cdc_acm_internal.h" + +/** + * @defgroup app_usbd_cdc_acm USB CDC ACM class + * @ingroup app_usbd + * + * @brief @tagAPI52840 Module with types, definitions and API used by CDC ACM class. + * + * @details References: + * - "Universal Serial Bus Class Definitions for Communications Devices" + * Revision 1.2, November 3, 2010 + * - "Universal Serial Bus Communications Class Subclass Specification for PSTN Devices" + * Revision 1.2, February 9, 2007 + * + * @{ + */ + +#ifdef DOXYGEN +/** + * @brief CDC ACM class instance type. + * + * @ref APP_USBD_CLASS_TYPEDEF + */ +typedef struct { } app_usbd_cdc_acm_t; +#else +/*lint -save -e10 -e26 -e123 -e505 */ +APP_USBD_CLASS_TYPEDEF(app_usbd_cdc_acm, \ + APP_USBD_CDC_ACM_CONFIG(0, 0, 0, 0, 0), \ + APP_USBD_CDC_ACM_INSTANCE_SPECIFIC_DEC, \ + APP_USBD_CDC_ACM_DATA_SPECIFIC_DEC \ +); +/*lint -restore*/ +#endif + + +/*lint -save -e407 */ + +/** + * @brief Events passed to user event handler. + * + * @note Example prototype of user event handler: + * + * @code + void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_cdc_acm_user_event_t event); + * @endcode + */ +typedef enum app_usbd_cdc_acm_user_event_e { + APP_USBD_CDC_ACM_USER_EVT_RX_DONE, /**< User event RX_DONE. */ + APP_USBD_CDC_ACM_USER_EVT_TX_DONE, /**< User event TX_DONE. */ + + APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN, /**< User event PORT_OPEN. */ + APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE, /**< User event PORT_CLOSE. */ +} app_usbd_cdc_acm_user_event_t; + +/*lint -restore*/ + +/** + * @brief Default CDC ACM descriptors. + * + * @param comm_interface COMM interface number. + * @param comm_epin COMM interface IN endpoint. + * @param data_interface DATA interface number. + * @param data_epin DATA interface IN endpoint. + * @param data_epout DATA interface OUT endpoint. + */ +#define APP_USBD_CDC_ACM_DEFAULT_DESC(comm_interface, \ + comm_epin, \ + data_interface, \ + data_epin, \ + data_epout) \ + APP_USBD_CDC_IAD_DSC(comm_interface, \ + APP_USBD_CDC_SUBCLASS_ACM, \ + APP_USBD_CDC_COMM_PROTOCOL_AT_V250) \ + APP_USBD_CDC_COMM_INTERFACE_DSC(comm_interface, \ + APP_USBD_CDC_SUBCLASS_ACM, \ + APP_USBD_CDC_COMM_PROTOCOL_AT_V250) \ + APP_USBD_CDC_HEADER_DSC(0x0110) \ + APP_USBD_CDC_CALL_MGMT_DSC(0x03, data_interface) \ + APP_USBD_CDC_ACM_DSC(0x02) \ + APP_USBD_CDC_UNION_DSC(comm_interface, data_interface) \ + APP_USBD_CDC_COM_EP_DSC(comm_epin, NRF_DRV_USBD_EPSIZE) \ + APP_USBD_CDC_DATA_INTERFACE_DSC(data_interface, 0, 0) \ + APP_USBD_CDC_DATA_EP_DSC(data_epin, data_epout, NRF_DRV_USBD_EPSIZE) + +/** + * @brief Global definition of app_usbd_cdc_acm_t class instance. + * + * @param instance_name Name of global instance. + * @param user_ev_handler User event handler (optional). + * @param comm_ifc Interface number of cdc_acm control. + * @param data_ifc Interface number of cdc_acm DATA. + * @param comm_ein COMM subclass IN endpoint. + * @param data_ein DATA subclass IN endpoint. + * @param data_eout DATA subclass OUT endpoint. + * @param cdc_protocol CDC protocol @ref app_usbd_cdc_comm_protocol_t + * + * @note This macro is just simplified version of @ref APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL. + * + */ +#define APP_USBD_CDC_ACM_GLOBAL_DEF(instance_name, \ + user_ev_handler, \ + comm_ifc, \ + data_ifc, \ + comm_ein, \ + data_ein, \ + data_eout, \ + cdc_protocol) \ + APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL(instance_name, \ + user_ev_handler, \ + comm_ifc, \ + data_ifc, \ + comm_ein, \ + data_ein, \ + data_eout, \ + cdc_protocol) \ + +/** + * @brief Helper function to get class instance from CDC ACM class. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * + * @return Base class instance. + */ +static inline app_usbd_class_inst_t const * +app_usbd_cdc_acm_class_inst_get(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + return &p_cdc_acm->base; +} + +/** + * @brief Helper function to get cdc_acm specific request from cdc_acm class. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * + * @return CDC ACM class specific request. + */ +static inline app_usbd_cdc_acm_req_t * +app_usbd_cdc_acm_class_request_get(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + return &p_cdc_acm->specific.p_data->ctx.request; +} + +/** + * @brief Helper function to get cdc_acm from base class instance. + * + * @param[in] p_inst Base class instance. + * + * @return CDC ACM class handle. + */ +static inline app_usbd_cdc_acm_t const * +app_usbd_cdc_acm_class_get(app_usbd_class_inst_t const * p_inst) +{ + return (app_usbd_cdc_acm_t const *)p_inst; +} + + +/** + * @brief Writes data to CDC ACM serial port. + * + * This is asynchronous call. User should wait for @ref APP_USBD_CDC_ACM_USER_EVT_TX_DONE event + * to be sure that all data has been sent and input buffer could be accessed again. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * @param[in] p_buf Input buffer. + * @param[in] length Input buffer length. + * + * @return Standard error code. + */ +ret_code_t app_usbd_cdc_acm_write(app_usbd_cdc_acm_t const * p_cdc_acm, + const void * p_buf, + size_t length); + +/** + * @brief Returns the amount of data that was read. + * + * This function should be used on @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event to get + * information how many bytes have been transfered into user buffer. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * + * @return Amount of data transfered. + */ +size_t app_usbd_cdc_acm_rx_size(app_usbd_cdc_acm_t const * p_cdc_acm); + +/** + * @brief Returns the amount of data that was stored into internal buffer + * + * This function should be used on @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event to get + * information how many bytes are waiting in internal buffer. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * + * @return Amount of data waiting. + */ +size_t app_usbd_cdc_acm_bytes_stored(app_usbd_cdc_acm_t const * p_cdc_acm); + +/** + * @brief Reads data from CDC ACM serial port. + * + * This function uses internal buffer and double buffering for continuous transmission. + * + * If there is enough data in internal buffer to fill user buffer, NRF_SUCCESS is + * returned and data is immediately available in the user buffer. + * + * If not, up to two user buffers can be scheduled, function returns NRF_ERROR_IO_PENDING + * when first buffer is filled and @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event is generated. + * + * @sa app_usbd_cdc_acm_read_any + * @sa app_usbd_cdc_acm_rx_size + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * @param[out] p_buf Output buffer. + * @param[in] length Number of bytes to read. + * + * @retval NRF_SUCCESS Data is stored into user buffer. + * @retval NRF_ERROR_IO_PENDING Awaiting transmission, when data is stored into user buffer, + * @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event will be raised. + * @retval NRF_ERROR_BUSY There are already 2 buffers queued for transfers. + * @retval other Standard error code. + */ +ret_code_t app_usbd_cdc_acm_read(app_usbd_cdc_acm_t const * p_cdc_acm, + void * p_buf, + size_t length); + +/** + * @brief Read any data from CDC ACM port up to given buffer size + * + * This function is very similar to the @ref app_usbd_cdc_acm_read but it returns + * data as quick as any data is available, even if the given buffer was not totally full. + * + * @note This function cannot use double buffering. + * @note To check the number of bytes really read use @ref app_usbd_cdc_acm_rx_size + * function. + * + * @sa app_usbd_cdc_acm_read + * @sa app_usbd_cdc_acm_rx_size + * + * @param p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * @param[out] p_buf Output buffer. + * @param[in] length Maximum number of bytes to read. + * + * @retval NRF_SUCCESS Data is stored into user buffer. + * @retval NRF_ERROR_IO_PENDING Awaiting transmission, when data is stored into user buffer, + * @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event will be raised. + * @retval NRF_ERROR_BUSY There is already buffer set for a transfer. + * @retval other Standard error code. + */ +ret_code_t app_usbd_cdc_acm_read_any(app_usbd_cdc_acm_t const * p_cdc_acm, + void * p_buf, + size_t length); + +/** + * @brief Serial state notifications. + * */ +typedef enum { + APP_USBD_CDC_ACM_SERIAL_STATE_DCD = (1u << 0), /**< Notification bit DCD. */ + APP_USBD_CDC_ACM_SERIAL_STATE_DSR = (1u << 1), /**< Notification bit DSR. */ + APP_USBD_CDC_ACM_SERIAL_STATE_BREAK = (1u << 2), /**< Notification bit BREAK. */ + APP_USBD_CDC_ACM_SERIAL_STATE_RING = (1u << 3), /**< Notification bit RING. */ + APP_USBD_CDC_ACM_SERIAL_STATE_FRAMING = (1u << 4), /**< Notification bit FRAMING.*/ + APP_USBD_CDC_ACM_SERIAL_STATE_PARITY = (1u << 5), /**< Notification bit PARITY. */ + APP_USBD_CDC_ACM_SERIAL_STATE_OVERRUN = (1u << 6), /**< Notification bit OVERRUN.*/ +} app_usbd_cdc_acm_serial_state_t; + +/** + * @brief Serial line state. + */ +typedef enum { + APP_USBD_CDC_ACM_LINE_STATE_DTR = (1u << 0), /**< Line state bit DTR.*/ + APP_USBD_CDC_ACM_LINE_STATE_RTS = (1u << 1), /**< Line state bit RTS.*/ +} app_usbd_cdc_acm_line_state_t; + +/** + * @brief Serial state notification via IN interrupt endpoint. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * @param[in] serial_state Serial state notification type. + * @param[in] value Serial state value. + * + * @return Standard error code. + */ +ret_code_t app_usbd_cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm, + app_usbd_cdc_acm_serial_state_t serial_state, + bool value); + +/** + * @brief Control line value get. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * @param[in] line_state Line control value type. + * @param[out] value Line control value. + * + * @return Standard error code. + */ +ret_code_t app_usbd_cdc_acm_line_state_get(app_usbd_cdc_acm_t const * p_cdc_acm, + app_usbd_cdc_acm_line_state_t line_state, + uint32_t * value); + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CDC_ACM_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm_internal.h b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm_internal.h index 1d2d13c00..58251c9df 100644 --- a/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm_internal.h +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm_internal.h @@ -1,287 +1,287 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef APP_USBD_CDC_ACM_INTERNAL_H__ -#define APP_USBD_CDC_ACM_INTERNAL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - - -#include "app_util.h" - -/** - * @defgroup app_usbd_cdc_acm_internal USB CDC ACM internals - * @ingroup app_usbd_cdc_acm - * @brief @tagAPI52840 Internals of the USB ACM class implementation. - * @{ - */ - -/** - * @brief Forward declaration of type defined by @ref APP_USBD_CLASS_TYPEDEF in cdc_acm class. - * - */ -APP_USBD_CLASS_FORWARD(app_usbd_cdc_acm); - -/*lint -save -e165*/ -/** - * @brief Forward declaration of @ref app_usbd_cdc_acm_user_event_e. - * - */ -enum app_usbd_cdc_acm_user_event_e; - -/*lint -restore*/ - -/** - * @brief User event handler. - * - * @param[in] p_inst Class instance. - * @param[in] event User event. - * - */ -typedef void (*app_usbd_cdc_acm_user_ev_handler_t)(app_usbd_class_inst_t const * p_inst, - enum app_usbd_cdc_acm_user_event_e event); - -/** - * @brief CDC ACM class part of class instance data. - */ -typedef struct { - uint8_t comm_interface; //!< Interface number of cdc_acm control. - uint8_t comm_epin; //!< COMM subclass IN endpoint. - uint8_t data_interface; //!< Interface number of cdc_acm DATA. - uint8_t data_epout; //!< DATA subclass OUT endpoint. - uint8_t data_epin; //!< DATA subclass IN endpoint. - - app_usbd_cdc_comm_protocol_t protocol; //!< User specified CDC protocol. - - app_usbd_cdc_acm_user_ev_handler_t user_ev_handler; //!< User event handler. - - uint8_t * p_ep_interval; //!< Endpoint intervals. -} app_usbd_cdc_acm_inst_t; - - -/** - * @brief CDC ACM serial state class notify. - */ -typedef struct { - app_usbd_cdc_notify_t cdc_notify; //!< CDC notify. - uint16_t serial_state; //!< Serial port state. -} app_usbd_cdc_acm_notify_t; - -/** - * @brief CDC ACM class specific request handled via control endpoint. - */ -typedef struct { - uint8_t type; //!< Request type. - uint8_t len; //!< Request length. - - union { - app_usbd_cdc_line_coding_t line_coding; //!< CDC ACM current line coding. - app_usbd_cdc_acm_notify_t notify; //!< CDC ACM class notify. - } payload; -} app_usbd_cdc_acm_req_t; - -/** - * @brief CDC ACM rx transfer buffer. - */ -typedef struct { - uint8_t * p_buf; //!< User buffer pointer. - size_t read_left; //!< Bytes left to read into buffer. -} cdc_rx_buffer_t; - -/** - * @brief CDC ACM class context. - */ -typedef struct { - app_usbd_cdc_acm_req_t request; //!< CDC ACM class request. - app_usbd_cdc_line_coding_t line_coding; //!< CDC ACM current line coding. - - uint16_t line_state; //!< CDC ACM line state bitmap, DTE side. - uint16_t serial_state; //!< CDC ACM serial state bitmap, DCE side. - - cdc_rx_buffer_t rx_transfer[2]; //!< User receive transfers. - - uint8_t internal_rx_buf[NRF_DRV_USBD_EPSIZE]; //!< Internal receive buffer. - uint8_t * p_copy_pos; //!< Current copy position from internal buffer. - - size_t bytes_left; //!< Bytes left in internal buffer to copy. - size_t bytes_read; //!< Bytes currently written to user buffer. - size_t last_read; //!< Bytes read in last transfer. - size_t cur_read; //!< Bytes currently read to internal buffer. -} app_usbd_cdc_acm_ctx_t; - -/** - * @brief Default interval value for comm endpoint IN - * - */ -#define APP_USBD_CDC_ACM_DEFAULT_INTERVAL 0x10 - -/** - * @brief CDC ACM class configuration macro. - * - * Used by @ref APP_USBD_CDC_ACM_GLOBAL_DEF - * - * @param iface_comm Interface number of cdc_acm control. - * @param epin_comm COMM subclass IN endpoint. - * @param iface_data Interface number of cdc_acm DATA. - * @param epin_data DATA subclass IN endpoint. - * @param epout_data DATA subclass OUT endpoint. - * - */ -#define APP_USBD_CDC_ACM_CONFIG(iface_comm, epin_comm, iface_data, epin_data, epout_data) \ - ((iface_comm, epin_comm), \ - (iface_data, epin_data, epout_data)) - - -/** - * @brief Specific class constant data for cdc_acm class. - * - * @ref app_usbd_cdc_acm_inst_t - */ -#define APP_USBD_CDC_ACM_INSTANCE_SPECIFIC_DEC app_usbd_cdc_acm_inst_t inst; - - -/** - * @brief Configures cdc_acm class instance. - * - * @param user_event_handler User event handler. - * @param comm_ifc Interface number of cdc_acm control. - * @param comm_ein COMM subclass IN endpoint. - * @param data_ifc Interface number of cdc_acm DATA. - * @param data_ein DATA subclass IN endpoint. - * @param data_eout DATA subclass OUT endpoint. - * @param cdc_protocol CDC protocol. - * @param ep_list List of endpoints and intervals - */ -#define APP_USBD_CDC_ACM_INST_CONFIG(user_event_handler, \ - comm_ifc, \ - comm_ein, \ - data_ifc, \ - data_ein, \ - data_eout, \ - cdc_protocol, \ - ep_list) \ - .inst = { \ - .user_ev_handler = user_event_handler, \ - .comm_interface = comm_ifc, \ - .comm_epin = comm_ifc, \ - .data_interface = data_ifc, \ - .data_epin = data_ein, \ - .data_epout = data_eout, \ - .protocol = cdc_protocol, \ - .p_ep_interval = ep_list \ - } - -/** - * @brief Specific class data for cdc_acm class. - * - * @ref app_usbd_cdc_acm_ctx_t - */ -#define APP_USBD_CDC_ACM_DATA_SPECIFIC_DEC app_usbd_cdc_acm_ctx_t ctx; - - -/** - * @brief CDC ACM class descriptors config macro. - * - * @param interface_number Interface number. - * @param ... Extracted endpoint list. - */ -#define APP_USBD_CDC_ACM_DSC_CONFIG(interface_number, ...) { \ - APP_USBD_CDC_ACM_INTERFACE_DSC(interface_number, \ - 0, \ - 0, \ - APP_USBD_CDC_ACM_SUBCLASS_CDC_ACMCONTROL) \ -} - -/** - * @brief Public cdc_acm class interface. - * - */ -extern const app_usbd_class_methods_t app_usbd_cdc_acm_class_methods; - -/** - * @brief Global definition of @ref app_usbd_cdc_acm_t class. - * - * @param instance_name Name of global instance. - * @param user_ev_handler User event handler. - * @param comm_ifc Interface number of cdc_acm control. - * @param data_ifc Interface number of cdc_acm DATA. - * @param comm_ein COMM subclass IN endpoint. - * @param data_ein DATA subclass IN endpoint. - * @param data_eout DATA subclass OUT endpoint. - * @param cdc_protocol CDC protocol @ref app_usbd_cdc_comm_protocol_t - */ -/*lint -save -emacro(26 64 123 505 572 651, APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL)*/ -#define APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL(instance_name, \ - user_ev_handler, \ - comm_ifc, \ - data_ifc, \ - comm_ein, \ - data_ein, \ - data_eout, \ - cdc_protocol) \ - static uint8_t CONCAT_2(instance_name, _ep) = { \ - (APP_USBD_EXTRACT_INTERVAL_FLAG(comm_ein) ? APP_USBD_EXTRACT_INTERVAL_VALUE(comm_ein) \ - : APP_USBD_CDC_ACM_DEFAULT_INTERVAL)}; \ - APP_USBD_CLASS_INST_GLOBAL_DEF( \ - instance_name, \ - app_usbd_cdc_acm, \ - &app_usbd_cdc_acm_class_methods, \ - APP_USBD_CDC_ACM_CONFIG(comm_ifc, comm_ein, data_ifc, data_ein, data_eout), \ - (APP_USBD_CDC_ACM_INST_CONFIG(user_ev_handler, \ - comm_ifc, \ - comm_ein, \ - data_ifc, \ - data_ein, \ - data_eout, \ - cdc_protocol, \ - &CONCAT_2(instance_name, _ep))) \ - ) -/*lint -restore*/ - -/** @} */ - - - -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_CDC_ACM_INTERNAL_H__ */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef APP_USBD_CDC_ACM_INTERNAL_H__ +#define APP_USBD_CDC_ACM_INTERNAL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "app_util.h" + +/** + * @defgroup app_usbd_cdc_acm_internal USB CDC ACM internals + * @ingroup app_usbd_cdc_acm + * @brief @tagAPI52840 Internals of the USB ACM class implementation. + * @{ + */ + +/** + * @brief Forward declaration of type defined by @ref APP_USBD_CLASS_TYPEDEF in cdc_acm class. + * + */ +APP_USBD_CLASS_FORWARD(app_usbd_cdc_acm); + +/*lint -save -e165*/ +/** + * @brief Forward declaration of @ref app_usbd_cdc_acm_user_event_e. + * + */ +enum app_usbd_cdc_acm_user_event_e; + +/*lint -restore*/ + +/** + * @brief User event handler. + * + * @param[in] p_inst Class instance. + * @param[in] event User event. + * + */ +typedef void (*app_usbd_cdc_acm_user_ev_handler_t)(app_usbd_class_inst_t const * p_inst, + enum app_usbd_cdc_acm_user_event_e event); + +/** + * @brief CDC ACM class part of class instance data. + */ +typedef struct { + uint8_t comm_interface; //!< Interface number of cdc_acm control. + uint8_t comm_epin; //!< COMM subclass IN endpoint. + uint8_t data_interface; //!< Interface number of cdc_acm DATA. + uint8_t data_epout; //!< DATA subclass OUT endpoint. + uint8_t data_epin; //!< DATA subclass IN endpoint. + + app_usbd_cdc_comm_protocol_t protocol; //!< User specified CDC protocol. + + app_usbd_cdc_acm_user_ev_handler_t user_ev_handler; //!< User event handler. + + uint8_t * p_ep_interval; //!< Endpoint intervals. +} app_usbd_cdc_acm_inst_t; + + +/** + * @brief CDC ACM serial state class notify. + */ +typedef struct { + app_usbd_cdc_notify_t cdc_notify; //!< CDC notify. + uint16_t serial_state; //!< Serial port state. +} app_usbd_cdc_acm_notify_t; + +/** + * @brief CDC ACM class specific request handled via control endpoint. + */ +typedef struct { + uint8_t type; //!< Request type. + uint8_t len; //!< Request length. + + union { + app_usbd_cdc_line_coding_t line_coding; //!< CDC ACM current line coding. + app_usbd_cdc_acm_notify_t notify; //!< CDC ACM class notify. + } payload; +} app_usbd_cdc_acm_req_t; + +/** + * @brief CDC ACM rx transfer buffer. + */ +typedef struct { + uint8_t * p_buf; //!< User buffer pointer. + size_t read_left; //!< Bytes left to read into buffer. +} cdc_rx_buffer_t; + +/** + * @brief CDC ACM class context. + */ +typedef struct { + app_usbd_cdc_acm_req_t request; //!< CDC ACM class request. + app_usbd_cdc_line_coding_t line_coding; //!< CDC ACM current line coding. + + uint16_t line_state; //!< CDC ACM line state bitmap, DTE side. + uint16_t serial_state; //!< CDC ACM serial state bitmap, DCE side. + + cdc_rx_buffer_t rx_transfer[2]; //!< User receive transfers. + + uint8_t internal_rx_buf[NRF_DRV_USBD_EPSIZE]; //!< Internal receive buffer. + uint8_t * p_copy_pos; //!< Current copy position from internal buffer. + + size_t bytes_left; //!< Bytes left in internal buffer to copy. + size_t bytes_read; //!< Bytes currently written to user buffer. + size_t last_read; //!< Bytes read in last transfer. + size_t cur_read; //!< Bytes currently read to internal buffer. +} app_usbd_cdc_acm_ctx_t; + +/** + * @brief Default interval value for comm endpoint IN + * + */ +#define APP_USBD_CDC_ACM_DEFAULT_INTERVAL 0x10 + +/** + * @brief CDC ACM class configuration macro. + * + * Used by @ref APP_USBD_CDC_ACM_GLOBAL_DEF + * + * @param iface_comm Interface number of cdc_acm control. + * @param epin_comm COMM subclass IN endpoint. + * @param iface_data Interface number of cdc_acm DATA. + * @param epin_data DATA subclass IN endpoint. + * @param epout_data DATA subclass OUT endpoint. + * + */ +#define APP_USBD_CDC_ACM_CONFIG(iface_comm, epin_comm, iface_data, epin_data, epout_data) \ + ((iface_comm, epin_comm), \ + (iface_data, epin_data, epout_data)) + + +/** + * @brief Specific class constant data for cdc_acm class. + * + * @ref app_usbd_cdc_acm_inst_t + */ +#define APP_USBD_CDC_ACM_INSTANCE_SPECIFIC_DEC app_usbd_cdc_acm_inst_t inst; + + +/** + * @brief Configures cdc_acm class instance. + * + * @param user_event_handler User event handler. + * @param comm_ifc Interface number of cdc_acm control. + * @param comm_ein COMM subclass IN endpoint. + * @param data_ifc Interface number of cdc_acm DATA. + * @param data_ein DATA subclass IN endpoint. + * @param data_eout DATA subclass OUT endpoint. + * @param cdc_protocol CDC protocol. + * @param ep_list List of endpoints and intervals + */ +#define APP_USBD_CDC_ACM_INST_CONFIG(user_event_handler, \ + comm_ifc, \ + comm_ein, \ + data_ifc, \ + data_ein, \ + data_eout, \ + cdc_protocol, \ + ep_list) \ + .inst = { \ + .user_ev_handler = user_event_handler, \ + .comm_interface = comm_ifc, \ + .comm_epin = comm_ifc, \ + .data_interface = data_ifc, \ + .data_epin = data_ein, \ + .data_epout = data_eout, \ + .protocol = cdc_protocol, \ + .p_ep_interval = ep_list \ + } + +/** + * @brief Specific class data for cdc_acm class. + * + * @ref app_usbd_cdc_acm_ctx_t + */ +#define APP_USBD_CDC_ACM_DATA_SPECIFIC_DEC app_usbd_cdc_acm_ctx_t ctx; + + +/** + * @brief CDC ACM class descriptors config macro. + * + * @param interface_number Interface number. + * @param ... Extracted endpoint list. + */ +#define APP_USBD_CDC_ACM_DSC_CONFIG(interface_number, ...) { \ + APP_USBD_CDC_ACM_INTERFACE_DSC(interface_number, \ + 0, \ + 0, \ + APP_USBD_CDC_ACM_SUBCLASS_CDC_ACMCONTROL) \ +} + +/** + * @brief Public cdc_acm class interface. + * + */ +extern const app_usbd_class_methods_t app_usbd_cdc_acm_class_methods; + +/** + * @brief Global definition of @ref app_usbd_cdc_acm_t class. + * + * @param instance_name Name of global instance. + * @param user_ev_handler User event handler. + * @param comm_ifc Interface number of cdc_acm control. + * @param data_ifc Interface number of cdc_acm DATA. + * @param comm_ein COMM subclass IN endpoint. + * @param data_ein DATA subclass IN endpoint. + * @param data_eout DATA subclass OUT endpoint. + * @param cdc_protocol CDC protocol @ref app_usbd_cdc_comm_protocol_t + */ +/*lint -save -emacro(26 64 123 505 572 651, APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL)*/ +#define APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL(instance_name, \ + user_ev_handler, \ + comm_ifc, \ + data_ifc, \ + comm_ein, \ + data_ein, \ + data_eout, \ + cdc_protocol) \ + static uint8_t CONCAT_2(instance_name, _ep) = { \ + (APP_USBD_EXTRACT_INTERVAL_FLAG(comm_ein) ? APP_USBD_EXTRACT_INTERVAL_VALUE(comm_ein) \ + : APP_USBD_CDC_ACM_DEFAULT_INTERVAL)}; \ + APP_USBD_CLASS_INST_GLOBAL_DEF( \ + instance_name, \ + app_usbd_cdc_acm, \ + &app_usbd_cdc_acm_class_methods, \ + APP_USBD_CDC_ACM_CONFIG(comm_ifc, comm_ein, data_ifc, data_ein, data_eout), \ + (APP_USBD_CDC_ACM_INST_CONFIG(user_ev_handler, \ + comm_ifc, \ + comm_ein, \ + data_ifc, \ + data_ein, \ + data_eout, \ + cdc_protocol, \ + &CONCAT_2(instance_name, _ep))) \ + ) +/*lint -restore*/ + +/** @} */ + + + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CDC_ACM_INTERNAL_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_desc.h b/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_desc.h index 4e0131c36..72ad224ff 100644 --- a/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_desc.h +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_desc.h @@ -1,208 +1,208 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef APP_USBD_CDC_DESC_H__ -#define APP_USBD_CDC_DESC_H__ - -#include -#include - -#include "app_usbd_descriptor.h" -#include "app_usbd_cdc_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup app_usbd_cdc_desc CDC class descriptors - * @brief @tagAPI52840 Descriptors used in the USB CDC class implementation. - * @ingroup app_usbd_cdc_acm - * - * A group of macros used to initialize CDC descriptors - * @{ - */ - -/** - * @brief Initializer of IAD descriptor for CDC class. - * - * @param interface_number Interface number. - * @param subclass Subclass, @ref app_usbd_cdc_subclass_t. - * @param protocol Protocol, @ref app_usbd_cdc_comm_protocol_t. - */ -#define APP_USBD_CDC_IAD_DSC(interface_number, subclass, protocol) \ - /*.bLength = */ sizeof(app_usbd_descriptor_iad_t), \ - /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_INTERFACE_ASSOCIATION, \ - /*.bFirstInterface = */ interface_number, \ - /*.bInterfaceCount = */ 2, \ - /*.bFunctionClass = */ APP_USBD_CDC_COMM_CLASS, \ - /*.bFunctionSubClass = */ subclass, \ - /*.bFunctionProtocol = */ protocol, \ - /*.iFunction = */ 0, \ - -/** - * @brief Initializer of interface descriptor for CDC COMM class. - * - * @param interface_number Interface number. - * @param subclass Subclass, @ref app_usbd_cdc_subclass_t. - * @param protocol Protocol, @ref app_usbd_cdc_comm_protocol_t. - */ -#define APP_USBD_CDC_COMM_INTERFACE_DSC(interface_number, subclass, protocol) \ - /*.bLength = */ sizeof(app_usbd_descriptor_iface_t), \ - /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_INTERFACE, \ - /*.bInterfaceNumber = */ interface_number, \ - /*.bAlternateSetting = */ 0x00, \ - /*.bNumEndpoints = */ 1, \ - /*.bInterfaceClass = */ APP_USBD_CDC_COMM_CLASS, \ - /*.bInterfaceSubClass = */ subclass, \ - /*.bInterfaceProtocol = */ protocol, \ - /*.iInterface = 0, */ 0x00, \ - - -/** - * @brief Initializer of interface descriptor for CDC DATA class. - * - * @param interface_number Interface number. - * @param subclass Subclass, @ref app_usbd_cdc_subclass_t. - * @param protocol Protocol, @ref app_usbd_cdc_data_protocol_t. - */ -#define APP_USBD_CDC_DATA_INTERFACE_DSC(interface_number, subclass, protocol) \ - /*.bLength = */ sizeof(app_usbd_descriptor_iface_t), \ - /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_INTERFACE, \ - /*.bInterfaceNumber = */ interface_number, \ - /*.bAlternateSetting = */ 0x00, \ - /*.bNumEndpoints = */ 2, \ - /*.bInterfaceClass = */ APP_USBD_CDC_DATA_CLASS, \ - /*.bInterfaceSubClass = */ subclass, \ - /*.bInterfaceProtocol = */ protocol, \ - /*.iInterface = 0, */ 0x00, \ - - - -/** - * @brief Initializer of endpoint descriptor for CDC COM class. - * - * @param endpoint_in IN endpoint. - * @param ep_size Endpoint size. - */ -#define APP_USBD_CDC_COM_EP_DSC(endpoint_in, ep_size) \ - /*.bLength = */ sizeof(app_usbd_descriptor_ep_t), \ - /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_ENDPOINT, \ - /*.bEndpointAddress = */ endpoint_in, \ - /*.bmAttributes = */ APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_INTERRUPT, \ - /*.wMaxPacketSize = */ APP_USBD_U16_TO_RAW_DSC(ep_size), \ - /*.bInterval = */ 16, \ - -/** - * @brief Initializer of endpoint descriptors for CDC DATA class. - * - * @param endpoint_in IN endpoint. - * @param endpoint_out OUT endpoint. - * @param ep_size Endpoint size. - */ -#define APP_USBD_CDC_DATA_EP_DSC(endpoint_in, endpoint_out, ep_size) \ - /*.bLength = */ sizeof(app_usbd_descriptor_ep_t), \ - /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_ENDPOINT, \ - /*.bEndpointAddress = */ endpoint_in, \ - /*.bmAttributes = */ APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK, \ - /*.wMaxPacketSize = */ APP_USBD_U16_TO_RAW_DSC(ep_size), \ - /*.bInterval = */ 0, \ - /*.bLength = */ sizeof(app_usbd_descriptor_ep_t), \ - /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_ENDPOINT, \ - /*.bEndpointAddress = */ endpoint_out, \ - /*.bmAttributes = */ APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK, \ - /*.wMaxPacketSize = */ APP_USBD_U16_TO_RAW_DSC(ep_size), \ - /*.bInterval = */ 0, \ - -/** - * @brief Initializer of endpoint descriptors for CDC header descriptor. - * - * @param bcd_cdc BCD CDC version. - */ -#define APP_USBD_CDC_HEADER_DSC(bcd_cdc) \ - /*.bLength = */ sizeof(app_usbd_cdc_desc_header_t), \ - /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ - /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_HEADER, \ - /*.bcdCDC = */ APP_USBD_U16_TO_RAW_DSC(bcd_cdc), \ - -/** - * @brief Initializer of endpoint descriptors for CDC call management descriptor. - * - * @param capabilities Capabilities. - * @param data_interface Data interface. - */ -#define APP_USBD_CDC_CALL_MGMT_DSC(capabilities, data_interface) \ - /*.bLength = */ sizeof(app_usbd_cdc_desc_call_mgmt_t), \ - /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ - /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_CALL_MGMT, \ - /*.bmCapabilities = */ capabilities, \ - /*.bDataInterface = */ data_interface, \ - - -/** - * @brief Initializer of endpoint descriptors for CDC DATA class. - * - * @param capabilities Capabilities. - */ -#define APP_USBD_CDC_ACM_DSC(capabilities) \ - /*.bLength = */ sizeof(app_usbd_cdc_desc_acm_t), \ - /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ - /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_ACM, \ - /*.bmCapabilities = */ capabilities, \ - -/** - * @brief Initializer of endpoint descriptors for CDC DATA class. - * - * @param control_interface Control interface. - * @param ... Subordinate interfaces list. - */ -#define APP_USBD_CDC_UNION_DSC(control_interface, ...) \ - /*.bLength = */ sizeof(app_usbd_cdc_desc_union_t) + (NUM_VA_ARGS(__VA_ARGS__)), \ - /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ - /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_UNION, \ - /*.bControlInterface = */ control_interface, \ - /*.bSubordinateInterface = */ __VA_ARGS__, \ - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_CDC_H__ */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef APP_USBD_CDC_DESC_H__ +#define APP_USBD_CDC_DESC_H__ + +#include +#include + +#include "app_usbd_descriptor.h" +#include "app_usbd_cdc_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup app_usbd_cdc_desc CDC class descriptors + * @brief @tagAPI52840 Descriptors used in the USB CDC class implementation. + * @ingroup app_usbd_cdc_acm + * + * A group of macros used to initialize CDC descriptors + * @{ + */ + +/** + * @brief Initializer of IAD descriptor for CDC class. + * + * @param interface_number Interface number. + * @param subclass Subclass, @ref app_usbd_cdc_subclass_t. + * @param protocol Protocol, @ref app_usbd_cdc_comm_protocol_t. + */ +#define APP_USBD_CDC_IAD_DSC(interface_number, subclass, protocol) \ + /*.bLength = */ sizeof(app_usbd_descriptor_iad_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_INTERFACE_ASSOCIATION, \ + /*.bFirstInterface = */ interface_number, \ + /*.bInterfaceCount = */ 2, \ + /*.bFunctionClass = */ APP_USBD_CDC_COMM_CLASS, \ + /*.bFunctionSubClass = */ subclass, \ + /*.bFunctionProtocol = */ protocol, \ + /*.iFunction = */ 0, \ + +/** + * @brief Initializer of interface descriptor for CDC COMM class. + * + * @param interface_number Interface number. + * @param subclass Subclass, @ref app_usbd_cdc_subclass_t. + * @param protocol Protocol, @ref app_usbd_cdc_comm_protocol_t. + */ +#define APP_USBD_CDC_COMM_INTERFACE_DSC(interface_number, subclass, protocol) \ + /*.bLength = */ sizeof(app_usbd_descriptor_iface_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_INTERFACE, \ + /*.bInterfaceNumber = */ interface_number, \ + /*.bAlternateSetting = */ 0x00, \ + /*.bNumEndpoints = */ 1, \ + /*.bInterfaceClass = */ APP_USBD_CDC_COMM_CLASS, \ + /*.bInterfaceSubClass = */ subclass, \ + /*.bInterfaceProtocol = */ protocol, \ + /*.iInterface = 0, */ 0x00, \ + + +/** + * @brief Initializer of interface descriptor for CDC DATA class. + * + * @param interface_number Interface number. + * @param subclass Subclass, @ref app_usbd_cdc_subclass_t. + * @param protocol Protocol, @ref app_usbd_cdc_data_protocol_t. + */ +#define APP_USBD_CDC_DATA_INTERFACE_DSC(interface_number, subclass, protocol) \ + /*.bLength = */ sizeof(app_usbd_descriptor_iface_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_INTERFACE, \ + /*.bInterfaceNumber = */ interface_number, \ + /*.bAlternateSetting = */ 0x00, \ + /*.bNumEndpoints = */ 2, \ + /*.bInterfaceClass = */ APP_USBD_CDC_DATA_CLASS, \ + /*.bInterfaceSubClass = */ subclass, \ + /*.bInterfaceProtocol = */ protocol, \ + /*.iInterface = 0, */ 0x00, \ + + + +/** + * @brief Initializer of endpoint descriptor for CDC COM class. + * + * @param endpoint_in IN endpoint. + * @param ep_size Endpoint size. + */ +#define APP_USBD_CDC_COM_EP_DSC(endpoint_in, ep_size) \ + /*.bLength = */ sizeof(app_usbd_descriptor_ep_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_ENDPOINT, \ + /*.bEndpointAddress = */ endpoint_in, \ + /*.bmAttributes = */ APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_INTERRUPT, \ + /*.wMaxPacketSize = */ APP_USBD_U16_TO_RAW_DSC(ep_size), \ + /*.bInterval = */ 16, \ + +/** + * @brief Initializer of endpoint descriptors for CDC DATA class. + * + * @param endpoint_in IN endpoint. + * @param endpoint_out OUT endpoint. + * @param ep_size Endpoint size. + */ +#define APP_USBD_CDC_DATA_EP_DSC(endpoint_in, endpoint_out, ep_size) \ + /*.bLength = */ sizeof(app_usbd_descriptor_ep_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_ENDPOINT, \ + /*.bEndpointAddress = */ endpoint_in, \ + /*.bmAttributes = */ APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK, \ + /*.wMaxPacketSize = */ APP_USBD_U16_TO_RAW_DSC(ep_size), \ + /*.bInterval = */ 0, \ + /*.bLength = */ sizeof(app_usbd_descriptor_ep_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_ENDPOINT, \ + /*.bEndpointAddress = */ endpoint_out, \ + /*.bmAttributes = */ APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK, \ + /*.wMaxPacketSize = */ APP_USBD_U16_TO_RAW_DSC(ep_size), \ + /*.bInterval = */ 0, \ + +/** + * @brief Initializer of endpoint descriptors for CDC header descriptor. + * + * @param bcd_cdc BCD CDC version. + */ +#define APP_USBD_CDC_HEADER_DSC(bcd_cdc) \ + /*.bLength = */ sizeof(app_usbd_cdc_desc_header_t), \ + /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ + /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_HEADER, \ + /*.bcdCDC = */ APP_USBD_U16_TO_RAW_DSC(bcd_cdc), \ + +/** + * @brief Initializer of endpoint descriptors for CDC call management descriptor. + * + * @param capabilities Capabilities. + * @param data_interface Data interface. + */ +#define APP_USBD_CDC_CALL_MGMT_DSC(capabilities, data_interface) \ + /*.bLength = */ sizeof(app_usbd_cdc_desc_call_mgmt_t), \ + /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ + /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_CALL_MGMT, \ + /*.bmCapabilities = */ capabilities, \ + /*.bDataInterface = */ data_interface, \ + + +/** + * @brief Initializer of endpoint descriptors for CDC DATA class. + * + * @param capabilities Capabilities. + */ +#define APP_USBD_CDC_ACM_DSC(capabilities) \ + /*.bLength = */ sizeof(app_usbd_cdc_desc_acm_t), \ + /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ + /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_ACM, \ + /*.bmCapabilities = */ capabilities, \ + +/** + * @brief Initializer of endpoint descriptors for CDC DATA class. + * + * @param control_interface Control interface. + * @param ... Subordinate interfaces list. + */ +#define APP_USBD_CDC_UNION_DSC(control_interface, ...) \ + /*.bLength = */ sizeof(app_usbd_cdc_desc_union_t) + (NUM_VA_ARGS(__VA_ARGS__)), \ + /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ + /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_UNION, \ + /*.bControlInterface = */ control_interface, \ + /*.bSubordinateInterface = */ __VA_ARGS__, \ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CDC_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_types.h b/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_types.h index 5ce083a74..24a0e7354 100644 --- a/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_types.h +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_types.h @@ -1,360 +1,360 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef APP_USBD_CDC_TYPES_H__ -#define APP_USBD_CDC_TYPES_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @defgroup app_usbd_cdc_types CDC class types - * @ingroup app_usbd_cdc_acm - * - * @brief @tagAPI52840 Variable types used by the CDC class implementation. - * @{ - */ - -/** - * @brief Communications Interface Class code. - * - * Used for control interface in communication class. - * @ref app_usbd_descriptor_iface_t::bInterfaceClass - */ -#define APP_USBD_CDC_COMM_CLASS 0x02 - -/** - * @brief Data Class Interface code. - * - * Used for data interface in communication class. - * @ref app_usbd_descriptor_iface_t::bInterfaceClass - */ -#define APP_USBD_CDC_DATA_CLASS 0x0A - -/** - * @brief CDC subclass possible values. - * - * @ref app_usbd_descriptor_iface_t::bInterfaceSubClass - */ -typedef enum { - APP_USBD_CDC_SUBCLASS_RESERVED = 0x00, /**< Reserved in documentation. */ - APP_USBD_CDC_SUBCLASS_DLCM = 0x01, /**< Direct Line Control Model. */ - APP_USBD_CDC_SUBCLASS_ACM = 0x02, /**< Abstract Control Model. */ - APP_USBD_CDC_SUBCLASS_TCM = 0x03, /**< Telephone Control Model. */ - APP_USBD_CDC_SUBCLASS_MCCM = 0x04, /**< Multi-Channel Control Model. */ - APP_USBD_CDC_SUBCLASS_CAPI = 0x05, /**< CAPI Control Model. */ - APP_USBD_CDC_SUBCLASS_ENCM = 0x06, /**< Ethernet Networking Control Model. */ - APP_USBD_CDC_SUBCLASS_ATM = 0x07, /**< ATM Networking Control Model. */ - APP_USBD_CDC_SUBCLASS_WHCM = 0x08, /**< Wireless Handset Control Model. */ - APP_USBD_CDC_SUBCLASS_DM = 0x09, /**< Device Management. */ - APP_USBD_CDC_SUBCLASS_MDLM = 0x0A, /**< Mobile Direct Line Model. */ - APP_USBD_CDC_SUBCLASS_OBEX = 0x0B, /**< OBEX. */ - APP_USBD_CDC_SUBCLASS_EEM = 0x0C, /**< Ethernet Emulation Model. */ - APP_USBD_CDC_SUBCLASS_NCM = 0x0D /**< Network Control Model. */ -} app_usbd_cdc_subclass_t; - -/** - * @brief CDC protocol possible values. - * - * @ref app_usbd_descriptor_iface_t::bInterfaceProtocol - */ -typedef enum { - APP_USBD_CDC_COMM_PROTOCOL_NONE = 0x00, /**< No class specific protocol required. */ - APP_USBD_CDC_COMM_PROTOCOL_AT_V250 = 0x01, /**< AT Commands: V.250 etc. */ - APP_USBD_CDC_COMM_PROTOCOL_AT_PCCA101 = 0x02, /**< AT Commands defined by PCCA-101. */ - APP_USBD_CDC_COMM_PROTOCOL_AT_PCCA101_ANNEXO = 0x03, /**< AT Commands defined by PCCA-101 & Annex O. */ - APP_USBD_CDC_COMM_PROTOCOL_AT_GSM707 = 0x04, /**< AT Commands defined by GSM 07.07. */ - APP_USBD_CDC_COMM_PROTOCOL_AT_3GPP_27007 = 0x05, /**< AT Commands defined by 3GPP 27.007. */ - APP_USBD_CDC_COMM_PROTOCOL_AT_CDMA = 0x06, /**< AT Commands defined by TIA for CDMA. */ - APP_USBD_CDC_COMM_PROTOCOL_EEM = 0x07, /**< Ethernet Emulation Model. */ - APP_USBD_CDC_COMM_PROTOCOL_EXTERNAL = 0xFE, /**< External Protocol: Commands defined by Command Set Functional Descriptor. */ - APP_USBD_CDC_COMM_PROTOCOL_VENDOR = 0xFF /**< Vendor-specific. */ -} app_usbd_cdc_comm_protocol_t; - -/** - * @brief CDC data interface protocols possible values. - */ -typedef enum { - APP_USBD_CDC_DATA_PROTOCOL_NONE = 0x00, /**< No class specific protocol required. */ - APP_USBD_CDC_DATA_PROTOCOL_NTB = 0x01, /**< Network Transfer Block. */ - APP_USBD_CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, /**< Physical interface protocol for ISDN BRI. */ - APP_USBD_CDC_DATA_PROTOCOL_HDLC = 0x31, /**< HDLC. */ - APP_USBD_CDC_DATA_PROTOCOL_TRANSPARENT = 0x32, /**< Transparent. */ - APP_USBD_CDC_DATA_PROTOCOL_Q921M = 0x50, /**< Management protocol for Q.921 data link protocol. */ - APP_USBD_CDC_DATA_PROTOCOL_Q921 = 0x51, /**< Data link protocol for Q.921. */ - APP_USBD_CDC_DATA_PROTOCOL_Q921TM = 0x52, /**< TEI-multiplexor for Q.921 data link protocol. */ - APP_USBD_CDC_DATA_PROTOCOL_V42BIS = 0x90, /**< Data compression procedures. */ - APP_USBD_CDC_DATA_PROTOCOL_Q931 = 0x91, /**< Euro-ISDN protocol control. */ - APP_USBD_CDC_DATA_PROTOCOL_V120 = 0x92, /**< V.24 rate adaptation to ISDN. */ - APP_USBD_CDC_DATA_PROTOCOL_CAPI20 = 0x93, /**< CAPI Commands. */ - APP_USBD_CDC_DATA_PROTOCOL_HOST = 0xFD, /**< Host based driver. - * @note This protocol code should only be used in messages - * between host and device to identify the host driver portion - * of a protocol stack. - */ - APP_USBD_CDC_DATA_PROTOCOL_EXTERNAL = 0xFE, /**< The protocol(s) are described using a Protocol Unit Functional - * Descriptors on Communications Class Interface. - */ - APP_USBD_CDC_DATA_PROTOCOL_VENDOR = 0xFF /**< Vendor-specific. */ -} app_usbd_cdc_data_protocol_t; - -/** - * @brief CDC Functional Descriptor types. - */ -typedef enum { - APP_USBD_CDC_CS_INTERFACE = 0x24, /**< Class specific interface descriptor type.*/ - APP_USBD_CDC_CS_ENDPOINT = 0x25 /**< Class specific endpoint descriptor type.*/ -} app_usbd_cdc_func_type_t; - -/** - * @brief CDC Functional Descriptor subtypes. - */ -typedef enum { - APP_USBD_CDC_SCS_HEADER = 0x00, /**< Header Functional Descriptor, which marks the beginning of the concatenated set of functional descriptors for the interface. */ - APP_USBD_CDC_SCS_CALL_MGMT = 0x01, /**< Call Management Functional Descriptor. */ - APP_USBD_CDC_SCS_ACM = 0x02, /**< Abstract Control Management Functional Descriptor. */ - APP_USBD_CDC_SCS_DLM = 0x03, /**< Direct Line Management Functional Descriptor. */ - APP_USBD_CDC_SCS_TEL_R = 0x04, /**< Telephone Ringer Functional Descriptor. */ - APP_USBD_CDC_SCS_TEL_CAP = 0x05, /**< Telephone Call and Line State Reporting Capabilities Functional Descriptor. */ - APP_USBD_CDC_SCS_UNION = 0x06, /**< Union Functional Descriptor. */ - APP_USBD_CDC_SCS_COUNTRY_SEL = 0x07, /**< Country Selection Functional Descriptor. */ - APP_USBD_CDC_SCS_TEL_OM = 0x08, /**< Telephone Operational Modes Functional Descriptor. */ - APP_USBD_CDC_SCS_USB_TERM = 0x09, /**< USB Terminal Functional Descriptor. */ - APP_USBD_CDC_SCS_NCT = 0x0A, /**< Network Channel Terminal Descriptor. */ - APP_USBD_CDC_SCS_PU = 0x0B, /**< Protocol Unit Functional Descriptor. */ - APP_USBD_CDC_SCS_EU = 0x0C, /**< Extension Unit Functional Descriptor. */ - APP_USBD_CDC_SCS_MCM = 0x0D, /**< Multi-Channel Management Functional Descriptor. */ - APP_USBD_CDC_SCS_CAPI = 0x0E, /**< CAPI Control Management Functional Descriptor. */ - APP_USBD_CDC_SCS_ETH = 0x0F, /**< Ethernet Networking Functional Descriptor. */ - APP_USBD_CDC_SCS_ATM = 0x10, /**< ATM Networking Functional Descriptor. */ - APP_USBD_CDC_SCS_WHCM = 0x11, /**< Wireless Handset Control Model Functional Descriptor. */ - APP_USBD_CDC_SCS_MDLM = 0x12, /**< Mobile Direct Line Model Functional Descriptor. */ - APP_USBD_CDC_SCS_MDLM_DET = 0x13, /**< MDLM Detail Functional Descriptor. */ - APP_USBD_CDC_SCS_DMM = 0x14, /**< Device Management Model Functional Descriptor. */ - APP_USBD_CDC_SCS_OBEX = 0x15, /**< OBEX Functional Descriptor. */ - APP_USBD_CDC_SCS_CS = 0x16, /**< Command Set Functional Descriptor. */ - APP_USBD_CDC_SCS_CS_DET = 0x17, /**< Command Set Detail Functional Descriptor. */ - APP_USBD_CDC_SCS_TEL_CM = 0x18, /**< Telephone Control Model Functional Descriptor. */ - APP_USBD_CDC_SCS_OBEX_SI = 0x19, /**< OBEX Service Identifier Functional Descriptor. */ - APP_USBD_CDC_SCS_NCM = 0x1A /**< NCM Functional Descriptor. */ -} app_usbd_cdc_func_subtype_t; - -/* Make all descriptors packed */ -#pragma pack(push, 1) - -/** - * @brief Header Functional Descriptor. - */ -typedef struct { - uint8_t bFunctionLength; //!< Size of this descriptor in bytes. - uint8_t bDescriptorType; //!< @ref APP_USBD_CDC_CS_INTERFACE descriptor type. - uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_HEADER. - uint8_t bcdCDC[2]; //!< USB Class Definitions for Communications Devices Specification release number in binary-coded decimal. -} app_usbd_cdc_desc_header_t; - -/** - * @brief Call management capabilities. - * - * @ref app_usbd_cdc_desc_call_mgmt_t::bmCapabilities bit. - * */ -typedef enum { - APP_USBD_CDC_CALL_MGMT_SUPPORTED = (1 << 0), /**< Call management capability bit 0.*/ - APP_USBD_CDC_CALL_MGMT_OVER_DCI = (1 << 1), /**< Call management capability bit 1.*/ -} app_subd_cdc_call_mgmt_cap_t; - -/** - * @brief CDC Call Management Functional Descriptor. - */ -typedef struct { - uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. - uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. - uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_CALL_MGMT. - uint8_t bmCapabilities; //!< Capabilities @ref app_subd_cdc_call_mgmt_cap_t. - uint8_t bDataInterface; //!< Data interface number. -} app_usbd_cdc_desc_call_mgmt_t; - -/** - * @brief ACM capabilities. - * - * @ref app_usbd_cdc_desc_acm_t::bmCapabilities bit. - * */ -typedef enum { - APP_USBD_CDC_ACM_FEATURE_REQUESTS = (1 << 0), /**< ACM capability bit FEATURE_REQUESTS. */ - APP_USBD_CDC_ACM_LINE_REQUESTS = (1 << 1), /**< ACM capability bit LINE_REQUESTS. */ - APP_USBD_CDC_ACM_SENDBREAK_REQUESTS = (1 << 2), /**< ACM capability bit SENDBREAK_REQUESTS.*/ - APP_USBD_CDC_ACM_NOTIFY_REQUESTS = (1 << 3), /**< ACM capability bit NOTIFY_REQUESTS. */ -} app_subd_cdc_acm_cap_t; - -/** - * @brief CDC ACM Functional Descriptor. - */ -typedef struct { - uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. - uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. - uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_ACM. - uint8_t bmCapabilities; //!< Capabilities @ref app_subd_cdc_acm_cap_t. -} app_usbd_cdc_desc_acm_t; - -/** - * @brief Union Functional Descriptor. - */ -typedef struct { - uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. - uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. - uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_UNION. - uint8_t bControlInterface; //!< The interface number of the Communications or Data Class interface, designated as the controlling interface for the union. - uint8_t bSubordinateInterface[]; //!< Interface number of subordinate interfaces in the union. Number of interfaced depends on descriptor size. -} app_usbd_cdc_desc_union_t; - -/** - * @brief Country Selection Functional Descriptor. - */ -typedef struct { - uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. - uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. - uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_COUNTRY_SEL. - uint8_t iCountryCodeRelDate; //!< Index of a string giving the release date for the implemented ISO 3166 Country Codes. -} app_usbd_cdc_desc_country_sel_t; - -/** - * @brief CDC Requests - * - */ -typedef enum { - /* CDC General */ - APP_USBD_CDC_REQ_SEND_ENCAPSULATED_COMMAND = 0x00, /**< This request is used to issue a command in the format of the supported control protocol of the Communications Class interface. */ - APP_USBD_CDC_REQ_GET_ENCAPSULATED_RESPONSE = 0x01, /**< This request is used to request a response in the format of the supported control protocol of the Communications Class interface. */ - /* CDC PSTN */ - APP_USBD_CDC_REQ_SET_COMM_FEATURE = 0x02, /**< This request controls the settings for a particular communications feature of a particular target. */ - APP_USBD_CDC_REQ_GET_COMM_FEATURE = 0x03, /**< This request returns the current settings for the communications feature as selected. */ - APP_USBD_CDC_REQ_CLEAR_COMM_FEATURE = 0x04, /**< This request controls the settings for a particular communications feature of a particular target, setting the selected feature to its default state. */ - APP_USBD_CDC_REQ_SET_AUX_LINE_STATE = 0x10, /**< This request is used to connect or disconnect a secondary jack to POTS circuit or CODEC, depending on hook state. */ - APP_USBD_CDC_REQ_SET_HOOK_STATE = 0x11, /**< This request is used to set the necessary PSTN line relay code for on-hook, off-hook, and caller ID states. */ - APP_USBD_CDC_REQ_PULSE_SETUP = 0x12, /**< This request is used to prepare for a pulse-dialing cycle. */ - APP_USBD_CDC_REQ_SEND_PULSE = 0x13, /**< This request is used to generate a specified number of make/break pulse cycles. */ - APP_USBD_CDC_REQ_SET_PULSE_TIME = 0x14, /**< This request sets the timing of the make and break periods for pulse dialing. */ - APP_USBD_CDC_REQ_RING_AUX_JACK = 0x15, /**< This request is used to generate a ring signal on a secondary phone jack. */ - APP_USBD_CDC_REQ_SET_LINE_CODING = 0x20, /**< This request allows the host to specify typical asynchronous line-character formatting properties. */ - APP_USBD_CDC_REQ_GET_LINE_CODING = 0x21, /**< This request allows the host to find out the currently configured line coding. */ - APP_USBD_CDC_REQ_SET_CONTROL_LINE_STATE = 0x22, /**< This request generates RS-232/V.24 style control signals. */ - APP_USBD_CDC_REQ_SEND_BREAK = 0x23, /**< This request sends special carrier modulation that generates an RS-232 style break. */ - APP_USBD_CDC_REQ_SET_RINGER_PARMS = 0x30, /**< This request configures the ringer for the communications device. */ - APP_USBD_CDC_REQ_GET_RINGER_PARMS = 0x31, /**< This request returns the ringer capabilities of the device and the current status of the device’s ringer. */ - APP_USBD_CDC_REQ_SET_OPERATION_PARMS = 0x32, /**< Sets the operational mode for the device, between a simple mode, standalone mode and a host centric mode. */ - APP_USBD_CDC_REQ_GET_OPERATION_PARMS = 0x33, /**< This request gets the current operational mode for the device. */ - APP_USBD_CDC_REQ_SET_LINE_PARMS = 0x34, /**< This request is used to change the state of the line, corresponding to the interface or master interface of a union to which the command was sent. */ - APP_USBD_CDC_REQ_GET_LINE_PARMS = 0x35, /**< This request is used to report the state of the line that corresponds to the interface or master interface of a union to which the command was sent. */ - APP_USBD_CDC_REQ_DIAL_DIGITS = 0x36, /**< This request dials the DTMF digits over the specified line. */ -} app_usbd_cdc_req_id_t; - -/** - * @brief CDC Notifications. - */ -typedef enum { - /* CDC General */ - APP_USBD_CDC_NOTIF_NETWORK_CONNECTION = 0x00, /**< This notification allows the device to notify the host about network connection status. */ - APP_USBD_CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, /**< This notification allows the device to notify the host that a response is available. - * This response can be retrieved with a subsequent GetEncapsulatedResponse request. - _ */ - APP_USBD_CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, /**< This notification allows the device to inform the host-networking driver - * that a change in either the up-link or the down-link bit rate of the connection has occurred. - */ - /* CDC PSTN */ - APP_USBD_CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, /**< (DLM) This notification indicates the loop has changed on the auxiliary phone interface of the USB device. */ - APP_USBD_CDC_NOTIF_RING_DETECT = 0x09, /**< (DLM) This notification indicates ring voltage on the POTS line interface of the USB device. */ - APP_USBD_CDC_NOTIF_SERIAL_STATE = 0x20, /**< (ACM) This notification sends asynchronous notification of UART status. */ - APP_USBD_CDC_NOTIF_CALL_STATE_CHANGE = 0x28, /**< (TCM) This notification identifies that a change has occurred to the state of a call on the line corresponding to the interface or union for the line. */ - APP_USBD_CDC_NOTIF_LINE_STATE_CHANGE = 0x29 /**< (TCM) This notification identifies that a change has occurred to the state of the line corresponding to the interface or master interface of a union sending the notification message. */ -} app_usbd_cdc_notify_id_t; - -/** - * @brief Notification sent via CDC COMM endpoint. - * */ -typedef struct { - uint8_t bmRequestType; //!< Request type. - uint8_t bmRequest; //!< Request ID @ref app_usbd_cdc_req_id_t. - uint16_t wValue; //!< Value field. - uint16_t wIndex; //!< Index field. - uint16_t wLength; //!< Length of payload following. -} app_usbd_cdc_notify_t; - -/** - * @brief CDC line coding structure. - */ -typedef struct { - uint8_t dwDTERate[4]; //!< Line baudrate. - uint8_t bCharFormat; //!< Character format @ref app_usbd_cdc_line_stopbit_t. - uint8_t bParityType; //!< Parity bits @ref app_usbd_cdc_line_parity_t. - uint8_t bDataBits; //!< Number of data bits. -} app_usbd_cdc_line_coding_t; - -/** - * @brief Possible values of @ref app_usbd_cdc_line_coding_t::bCharFormat. - */ -typedef enum { - APP_USBD_CDC_LINE_STOPBIT_1 = 0, /**< 1 stop bit. */ - APP_USBD_CDC_LINE_STOPBIT_1_5 = 1, /**< 1.5 stop bits. */ - APP_USBD_CDC_LINE_STOPBIT_2 = 2, /**< 2 stop bits. */ -} app_usbd_cdc_line_stopbit_t; - -/** - * @brief Possible values of @ref app_usbd_cdc_line_coding_t::bParityType. - */ -typedef enum { - APP_USBD_CDC_LINE_PARITY_NONE = 0, /**< No parity. */ - APP_USBD_CDC_LINE_PARITY_ODD = 1, /**< Odd parity. */ - APP_USBD_CDC_LINE_PARITY_EVEN = 2, /**< Even parity. */ - APP_USBD_CDC_LINE_PARITY_MARK = 3, /**< Parity forced to 0 (space).*/ - APP_USBD_CDC_LINE_PARITY_SPACE = 4, /**< Parity forced to 1 (mark). */ -} app_usbd_cdc_line_parity_t; - - -#pragma pack(pop) - -/** @} */ -#ifdef __cplusplus -} -#endif - -#endif /* APP_USBD_TYPES_H__ */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef APP_USBD_CDC_TYPES_H__ +#define APP_USBD_CDC_TYPES_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @defgroup app_usbd_cdc_types CDC class types + * @ingroup app_usbd_cdc_acm + * + * @brief @tagAPI52840 Variable types used by the CDC class implementation. + * @{ + */ + +/** + * @brief Communications Interface Class code. + * + * Used for control interface in communication class. + * @ref app_usbd_descriptor_iface_t::bInterfaceClass + */ +#define APP_USBD_CDC_COMM_CLASS 0x02 + +/** + * @brief Data Class Interface code. + * + * Used for data interface in communication class. + * @ref app_usbd_descriptor_iface_t::bInterfaceClass + */ +#define APP_USBD_CDC_DATA_CLASS 0x0A + +/** + * @brief CDC subclass possible values. + * + * @ref app_usbd_descriptor_iface_t::bInterfaceSubClass + */ +typedef enum { + APP_USBD_CDC_SUBCLASS_RESERVED = 0x00, /**< Reserved in documentation. */ + APP_USBD_CDC_SUBCLASS_DLCM = 0x01, /**< Direct Line Control Model. */ + APP_USBD_CDC_SUBCLASS_ACM = 0x02, /**< Abstract Control Model. */ + APP_USBD_CDC_SUBCLASS_TCM = 0x03, /**< Telephone Control Model. */ + APP_USBD_CDC_SUBCLASS_MCCM = 0x04, /**< Multi-Channel Control Model. */ + APP_USBD_CDC_SUBCLASS_CAPI = 0x05, /**< CAPI Control Model. */ + APP_USBD_CDC_SUBCLASS_ENCM = 0x06, /**< Ethernet Networking Control Model. */ + APP_USBD_CDC_SUBCLASS_ATM = 0x07, /**< ATM Networking Control Model. */ + APP_USBD_CDC_SUBCLASS_WHCM = 0x08, /**< Wireless Handset Control Model. */ + APP_USBD_CDC_SUBCLASS_DM = 0x09, /**< Device Management. */ + APP_USBD_CDC_SUBCLASS_MDLM = 0x0A, /**< Mobile Direct Line Model. */ + APP_USBD_CDC_SUBCLASS_OBEX = 0x0B, /**< OBEX. */ + APP_USBD_CDC_SUBCLASS_EEM = 0x0C, /**< Ethernet Emulation Model. */ + APP_USBD_CDC_SUBCLASS_NCM = 0x0D /**< Network Control Model. */ +} app_usbd_cdc_subclass_t; + +/** + * @brief CDC protocol possible values. + * + * @ref app_usbd_descriptor_iface_t::bInterfaceProtocol + */ +typedef enum { + APP_USBD_CDC_COMM_PROTOCOL_NONE = 0x00, /**< No class specific protocol required. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_V250 = 0x01, /**< AT Commands: V.250 etc. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_PCCA101 = 0x02, /**< AT Commands defined by PCCA-101. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_PCCA101_ANNEXO = 0x03, /**< AT Commands defined by PCCA-101 & Annex O. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_GSM707 = 0x04, /**< AT Commands defined by GSM 07.07. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_3GPP_27007 = 0x05, /**< AT Commands defined by 3GPP 27.007. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_CDMA = 0x06, /**< AT Commands defined by TIA for CDMA. */ + APP_USBD_CDC_COMM_PROTOCOL_EEM = 0x07, /**< Ethernet Emulation Model. */ + APP_USBD_CDC_COMM_PROTOCOL_EXTERNAL = 0xFE, /**< External Protocol: Commands defined by Command Set Functional Descriptor. */ + APP_USBD_CDC_COMM_PROTOCOL_VENDOR = 0xFF /**< Vendor-specific. */ +} app_usbd_cdc_comm_protocol_t; + +/** + * @brief CDC data interface protocols possible values. + */ +typedef enum { + APP_USBD_CDC_DATA_PROTOCOL_NONE = 0x00, /**< No class specific protocol required. */ + APP_USBD_CDC_DATA_PROTOCOL_NTB = 0x01, /**< Network Transfer Block. */ + APP_USBD_CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, /**< Physical interface protocol for ISDN BRI. */ + APP_USBD_CDC_DATA_PROTOCOL_HDLC = 0x31, /**< HDLC. */ + APP_USBD_CDC_DATA_PROTOCOL_TRANSPARENT = 0x32, /**< Transparent. */ + APP_USBD_CDC_DATA_PROTOCOL_Q921M = 0x50, /**< Management protocol for Q.921 data link protocol. */ + APP_USBD_CDC_DATA_PROTOCOL_Q921 = 0x51, /**< Data link protocol for Q.921. */ + APP_USBD_CDC_DATA_PROTOCOL_Q921TM = 0x52, /**< TEI-multiplexor for Q.921 data link protocol. */ + APP_USBD_CDC_DATA_PROTOCOL_V42BIS = 0x90, /**< Data compression procedures. */ + APP_USBD_CDC_DATA_PROTOCOL_Q931 = 0x91, /**< Euro-ISDN protocol control. */ + APP_USBD_CDC_DATA_PROTOCOL_V120 = 0x92, /**< V.24 rate adaptation to ISDN. */ + APP_USBD_CDC_DATA_PROTOCOL_CAPI20 = 0x93, /**< CAPI Commands. */ + APP_USBD_CDC_DATA_PROTOCOL_HOST = 0xFD, /**< Host based driver. + * @note This protocol code should only be used in messages + * between host and device to identify the host driver portion + * of a protocol stack. + */ + APP_USBD_CDC_DATA_PROTOCOL_EXTERNAL = 0xFE, /**< The protocol(s) are described using a Protocol Unit Functional + * Descriptors on Communications Class Interface. + */ + APP_USBD_CDC_DATA_PROTOCOL_VENDOR = 0xFF /**< Vendor-specific. */ +} app_usbd_cdc_data_protocol_t; + +/** + * @brief CDC Functional Descriptor types. + */ +typedef enum { + APP_USBD_CDC_CS_INTERFACE = 0x24, /**< Class specific interface descriptor type.*/ + APP_USBD_CDC_CS_ENDPOINT = 0x25 /**< Class specific endpoint descriptor type.*/ +} app_usbd_cdc_func_type_t; + +/** + * @brief CDC Functional Descriptor subtypes. + */ +typedef enum { + APP_USBD_CDC_SCS_HEADER = 0x00, /**< Header Functional Descriptor, which marks the beginning of the concatenated set of functional descriptors for the interface. */ + APP_USBD_CDC_SCS_CALL_MGMT = 0x01, /**< Call Management Functional Descriptor. */ + APP_USBD_CDC_SCS_ACM = 0x02, /**< Abstract Control Management Functional Descriptor. */ + APP_USBD_CDC_SCS_DLM = 0x03, /**< Direct Line Management Functional Descriptor. */ + APP_USBD_CDC_SCS_TEL_R = 0x04, /**< Telephone Ringer Functional Descriptor. */ + APP_USBD_CDC_SCS_TEL_CAP = 0x05, /**< Telephone Call and Line State Reporting Capabilities Functional Descriptor. */ + APP_USBD_CDC_SCS_UNION = 0x06, /**< Union Functional Descriptor. */ + APP_USBD_CDC_SCS_COUNTRY_SEL = 0x07, /**< Country Selection Functional Descriptor. */ + APP_USBD_CDC_SCS_TEL_OM = 0x08, /**< Telephone Operational Modes Functional Descriptor. */ + APP_USBD_CDC_SCS_USB_TERM = 0x09, /**< USB Terminal Functional Descriptor. */ + APP_USBD_CDC_SCS_NCT = 0x0A, /**< Network Channel Terminal Descriptor. */ + APP_USBD_CDC_SCS_PU = 0x0B, /**< Protocol Unit Functional Descriptor. */ + APP_USBD_CDC_SCS_EU = 0x0C, /**< Extension Unit Functional Descriptor. */ + APP_USBD_CDC_SCS_MCM = 0x0D, /**< Multi-Channel Management Functional Descriptor. */ + APP_USBD_CDC_SCS_CAPI = 0x0E, /**< CAPI Control Management Functional Descriptor. */ + APP_USBD_CDC_SCS_ETH = 0x0F, /**< Ethernet Networking Functional Descriptor. */ + APP_USBD_CDC_SCS_ATM = 0x10, /**< ATM Networking Functional Descriptor. */ + APP_USBD_CDC_SCS_WHCM = 0x11, /**< Wireless Handset Control Model Functional Descriptor. */ + APP_USBD_CDC_SCS_MDLM = 0x12, /**< Mobile Direct Line Model Functional Descriptor. */ + APP_USBD_CDC_SCS_MDLM_DET = 0x13, /**< MDLM Detail Functional Descriptor. */ + APP_USBD_CDC_SCS_DMM = 0x14, /**< Device Management Model Functional Descriptor. */ + APP_USBD_CDC_SCS_OBEX = 0x15, /**< OBEX Functional Descriptor. */ + APP_USBD_CDC_SCS_CS = 0x16, /**< Command Set Functional Descriptor. */ + APP_USBD_CDC_SCS_CS_DET = 0x17, /**< Command Set Detail Functional Descriptor. */ + APP_USBD_CDC_SCS_TEL_CM = 0x18, /**< Telephone Control Model Functional Descriptor. */ + APP_USBD_CDC_SCS_OBEX_SI = 0x19, /**< OBEX Service Identifier Functional Descriptor. */ + APP_USBD_CDC_SCS_NCM = 0x1A /**< NCM Functional Descriptor. */ +} app_usbd_cdc_func_subtype_t; + +/* Make all descriptors packed */ +#pragma pack(push, 1) + +/** + * @brief Header Functional Descriptor. + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this descriptor in bytes. + uint8_t bDescriptorType; //!< @ref APP_USBD_CDC_CS_INTERFACE descriptor type. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_HEADER. + uint8_t bcdCDC[2]; //!< USB Class Definitions for Communications Devices Specification release number in binary-coded decimal. +} app_usbd_cdc_desc_header_t; + +/** + * @brief Call management capabilities. + * + * @ref app_usbd_cdc_desc_call_mgmt_t::bmCapabilities bit. + * */ +typedef enum { + APP_USBD_CDC_CALL_MGMT_SUPPORTED = (1 << 0), /**< Call management capability bit 0.*/ + APP_USBD_CDC_CALL_MGMT_OVER_DCI = (1 << 1), /**< Call management capability bit 1.*/ +} app_subd_cdc_call_mgmt_cap_t; + +/** + * @brief CDC Call Management Functional Descriptor. + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. + uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_CALL_MGMT. + uint8_t bmCapabilities; //!< Capabilities @ref app_subd_cdc_call_mgmt_cap_t. + uint8_t bDataInterface; //!< Data interface number. +} app_usbd_cdc_desc_call_mgmt_t; + +/** + * @brief ACM capabilities. + * + * @ref app_usbd_cdc_desc_acm_t::bmCapabilities bit. + * */ +typedef enum { + APP_USBD_CDC_ACM_FEATURE_REQUESTS = (1 << 0), /**< ACM capability bit FEATURE_REQUESTS. */ + APP_USBD_CDC_ACM_LINE_REQUESTS = (1 << 1), /**< ACM capability bit LINE_REQUESTS. */ + APP_USBD_CDC_ACM_SENDBREAK_REQUESTS = (1 << 2), /**< ACM capability bit SENDBREAK_REQUESTS.*/ + APP_USBD_CDC_ACM_NOTIFY_REQUESTS = (1 << 3), /**< ACM capability bit NOTIFY_REQUESTS. */ +} app_subd_cdc_acm_cap_t; + +/** + * @brief CDC ACM Functional Descriptor. + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. + uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_ACM. + uint8_t bmCapabilities; //!< Capabilities @ref app_subd_cdc_acm_cap_t. +} app_usbd_cdc_desc_acm_t; + +/** + * @brief Union Functional Descriptor. + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. + uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_UNION. + uint8_t bControlInterface; //!< The interface number of the Communications or Data Class interface, designated as the controlling interface for the union. + uint8_t bSubordinateInterface[]; //!< Interface number of subordinate interfaces in the union. Number of interfaced depends on descriptor size. +} app_usbd_cdc_desc_union_t; + +/** + * @brief Country Selection Functional Descriptor. + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. + uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_COUNTRY_SEL. + uint8_t iCountryCodeRelDate; //!< Index of a string giving the release date for the implemented ISO 3166 Country Codes. +} app_usbd_cdc_desc_country_sel_t; + +/** + * @brief CDC Requests + * + */ +typedef enum { + /* CDC General */ + APP_USBD_CDC_REQ_SEND_ENCAPSULATED_COMMAND = 0x00, /**< This request is used to issue a command in the format of the supported control protocol of the Communications Class interface. */ + APP_USBD_CDC_REQ_GET_ENCAPSULATED_RESPONSE = 0x01, /**< This request is used to request a response in the format of the supported control protocol of the Communications Class interface. */ + /* CDC PSTN */ + APP_USBD_CDC_REQ_SET_COMM_FEATURE = 0x02, /**< This request controls the settings for a particular communications feature of a particular target. */ + APP_USBD_CDC_REQ_GET_COMM_FEATURE = 0x03, /**< This request returns the current settings for the communications feature as selected. */ + APP_USBD_CDC_REQ_CLEAR_COMM_FEATURE = 0x04, /**< This request controls the settings for a particular communications feature of a particular target, setting the selected feature to its default state. */ + APP_USBD_CDC_REQ_SET_AUX_LINE_STATE = 0x10, /**< This request is used to connect or disconnect a secondary jack to POTS circuit or CODEC, depending on hook state. */ + APP_USBD_CDC_REQ_SET_HOOK_STATE = 0x11, /**< This request is used to set the necessary PSTN line relay code for on-hook, off-hook, and caller ID states. */ + APP_USBD_CDC_REQ_PULSE_SETUP = 0x12, /**< This request is used to prepare for a pulse-dialing cycle. */ + APP_USBD_CDC_REQ_SEND_PULSE = 0x13, /**< This request is used to generate a specified number of make/break pulse cycles. */ + APP_USBD_CDC_REQ_SET_PULSE_TIME = 0x14, /**< This request sets the timing of the make and break periods for pulse dialing. */ + APP_USBD_CDC_REQ_RING_AUX_JACK = 0x15, /**< This request is used to generate a ring signal on a secondary phone jack. */ + APP_USBD_CDC_REQ_SET_LINE_CODING = 0x20, /**< This request allows the host to specify typical asynchronous line-character formatting properties. */ + APP_USBD_CDC_REQ_GET_LINE_CODING = 0x21, /**< This request allows the host to find out the currently configured line coding. */ + APP_USBD_CDC_REQ_SET_CONTROL_LINE_STATE = 0x22, /**< This request generates RS-232/V.24 style control signals. */ + APP_USBD_CDC_REQ_SEND_BREAK = 0x23, /**< This request sends special carrier modulation that generates an RS-232 style break. */ + APP_USBD_CDC_REQ_SET_RINGER_PARMS = 0x30, /**< This request configures the ringer for the communications device. */ + APP_USBD_CDC_REQ_GET_RINGER_PARMS = 0x31, /**< This request returns the ringer capabilities of the device and the current status of the device’s ringer. */ + APP_USBD_CDC_REQ_SET_OPERATION_PARMS = 0x32, /**< Sets the operational mode for the device, between a simple mode, standalone mode and a host centric mode. */ + APP_USBD_CDC_REQ_GET_OPERATION_PARMS = 0x33, /**< This request gets the current operational mode for the device. */ + APP_USBD_CDC_REQ_SET_LINE_PARMS = 0x34, /**< This request is used to change the state of the line, corresponding to the interface or master interface of a union to which the command was sent. */ + APP_USBD_CDC_REQ_GET_LINE_PARMS = 0x35, /**< This request is used to report the state of the line that corresponds to the interface or master interface of a union to which the command was sent. */ + APP_USBD_CDC_REQ_DIAL_DIGITS = 0x36, /**< This request dials the DTMF digits over the specified line. */ +} app_usbd_cdc_req_id_t; + +/** + * @brief CDC Notifications. + */ +typedef enum { + /* CDC General */ + APP_USBD_CDC_NOTIF_NETWORK_CONNECTION = 0x00, /**< This notification allows the device to notify the host about network connection status. */ + APP_USBD_CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, /**< This notification allows the device to notify the host that a response is available. + * This response can be retrieved with a subsequent GetEncapsulatedResponse request. + _ */ + APP_USBD_CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, /**< This notification allows the device to inform the host-networking driver + * that a change in either the up-link or the down-link bit rate of the connection has occurred. + */ + /* CDC PSTN */ + APP_USBD_CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, /**< (DLM) This notification indicates the loop has changed on the auxiliary phone interface of the USB device. */ + APP_USBD_CDC_NOTIF_RING_DETECT = 0x09, /**< (DLM) This notification indicates ring voltage on the POTS line interface of the USB device. */ + APP_USBD_CDC_NOTIF_SERIAL_STATE = 0x20, /**< (ACM) This notification sends asynchronous notification of UART status. */ + APP_USBD_CDC_NOTIF_CALL_STATE_CHANGE = 0x28, /**< (TCM) This notification identifies that a change has occurred to the state of a call on the line corresponding to the interface or union for the line. */ + APP_USBD_CDC_NOTIF_LINE_STATE_CHANGE = 0x29 /**< (TCM) This notification identifies that a change has occurred to the state of the line corresponding to the interface or master interface of a union sending the notification message. */ +} app_usbd_cdc_notify_id_t; + +/** + * @brief Notification sent via CDC COMM endpoint. + * */ +typedef struct { + uint8_t bmRequestType; //!< Request type. + uint8_t bmRequest; //!< Request ID @ref app_usbd_cdc_req_id_t. + uint16_t wValue; //!< Value field. + uint16_t wIndex; //!< Index field. + uint16_t wLength; //!< Length of payload following. +} app_usbd_cdc_notify_t; + +/** + * @brief CDC line coding structure. + */ +typedef struct { + uint8_t dwDTERate[4]; //!< Line baudrate. + uint8_t bCharFormat; //!< Character format @ref app_usbd_cdc_line_stopbit_t. + uint8_t bParityType; //!< Parity bits @ref app_usbd_cdc_line_parity_t. + uint8_t bDataBits; //!< Number of data bits. +} app_usbd_cdc_line_coding_t; + +/** + * @brief Possible values of @ref app_usbd_cdc_line_coding_t::bCharFormat. + */ +typedef enum { + APP_USBD_CDC_LINE_STOPBIT_1 = 0, /**< 1 stop bit. */ + APP_USBD_CDC_LINE_STOPBIT_1_5 = 1, /**< 1.5 stop bits. */ + APP_USBD_CDC_LINE_STOPBIT_2 = 2, /**< 2 stop bits. */ +} app_usbd_cdc_line_stopbit_t; + +/** + * @brief Possible values of @ref app_usbd_cdc_line_coding_t::bParityType. + */ +typedef enum { + APP_USBD_CDC_LINE_PARITY_NONE = 0, /**< No parity. */ + APP_USBD_CDC_LINE_PARITY_ODD = 1, /**< Odd parity. */ + APP_USBD_CDC_LINE_PARITY_EVEN = 2, /**< Even parity. */ + APP_USBD_CDC_LINE_PARITY_MARK = 3, /**< Parity forced to 0 (space).*/ + APP_USBD_CDC_LINE_PARITY_SPACE = 4, /**< Parity forced to 1 (mark). */ +} app_usbd_cdc_line_parity_t; + + +#pragma pack(pop) + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_TYPES_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/config/app_usbd_string_config.h b/third_party/NordicSemiconductor/libraries/usb/config/app_usbd_string_config.h index 2dc8603e1..d90603cb7 100644 --- a/third_party/NordicSemiconductor/libraries/usb/config/app_usbd_string_config.h +++ b/third_party/NordicSemiconductor/libraries/usb/config/app_usbd_string_config.h @@ -1,130 +1,130 @@ -/** - * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef APP_USBD_STRING_CONFIG_H -#define APP_USBD_STRING_CONFIG_H - -/** - * @defgroup app_usbd_string_conf USBD string configuration - * @ingroup app_usbd_string_desc - * - * @brief @tagAPI52840 Configuration of the string module that can be easily affected by the final - * user. - * @{ - */ - -/** - * @brief Supported languages identifiers - * - * Comma separated list of supported languages. - */ -#define APP_USBD_STRINGS_LANGIDS \ - ((uint16_t)APP_USBD_LANG_ENGLISH | (uint16_t)APP_USBD_SUBLANG_ENGLISH_US) - -/** - * @brief Manufacturer name string descriptor - * - * Comma separated list of manufacturer names for each defined language. - * Use @ref APP_USBD_STRING_DESC macro to create string descriptor. - * - * The order of manufacturer names has to be the same like in - * @ref APP_USBD_STRINGS_LANGIDS. - */ -#define APP_USBD_STRINGS_MANUFACTURER \ - APP_USBD_STRING_DESC("Nordic Semiconductor") - -/** - * @brief Define whether @ref APP_USBD_STRINGS_MANUFACTURER is created by @ref APP_USBD_STRING_DESC - * or declared as global variable. - * */ -#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0 - -/** - * @brief Product name string descriptor - * - * List of product names defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER - */ -#define APP_USBD_STRINGS_PRODUCT \ - APP_USBD_STRING_DESC("nRF52840 OpenThread Device") - - -/** - * @brief Define whether @ref APP_USBD_STRINGS_PRODUCT is created by @ref APP_USBD_STRING_DESC - * or declared as global variable. - * */ -#define APP_USBD_STRINGS_PRODUCT_EXTERN 0 - -/** - * @brief Serial number string descriptor - * - * Create serial number string descriptor using @ref APP_USBD_STRING_DESC, - * or configure it to point to any internal variable pointer filled with descriptor. - * - * @note - * There is only one SERIAL number inside the library and it is Language independent. - */ -#define APP_USBD_STRING_SERIAL g_extern_serial_number - -/** - * @brief Define whether @ref APP_USBD_STRING_SERIAL is created by @ref APP_USBD_STRING_DESC - * or declared as global variable. - * */ -#define APP_USBD_STRING_SERIAL_EXTERN 1 - -/** - * @brief User strings default values - * - * This value stores all application specific user strings with its default initialization. - * The setup is done by X-macros. - * Expected macro parameters: - * @code - * X(mnemonic, [=str_idx], ...) - * @endcode - * - @c mnemonic: Mnemonic of the string descriptor that would be added to - * @ref app_usbd_string_desc_idx_t enumerator. - * - @c str_idx : String index value, may be set or left empty. - * For example WinUSB driver requires descriptor to be present on 0xEE index. - * Then use X(USBD_STRING_WINUSB, =0xEE, (APP_USBD_STRING_DESC(...))) - * - @c ... : List of string descriptors for each defined language. - */ -#define APP_USBD_STRINGS_USER \ - X(APP_USER_1, , APP_USBD_STRING_DESC("User 1")) - -/** @} */ -#endif /* APP_USBD_STRING_CONFIG_H */ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef APP_USBD_STRING_CONFIG_H +#define APP_USBD_STRING_CONFIG_H + +/** + * @defgroup app_usbd_string_conf USBD string configuration + * @ingroup app_usbd_string_desc + * + * @brief @tagAPI52840 Configuration of the string module that can be easily affected by the final + * user. + * @{ + */ + +/** + * @brief Supported languages identifiers + * + * Comma separated list of supported languages. + */ +#define APP_USBD_STRINGS_LANGIDS \ + ((uint16_t)APP_USBD_LANG_ENGLISH | (uint16_t)APP_USBD_SUBLANG_ENGLISH_US) + +/** + * @brief Manufacturer name string descriptor + * + * Comma separated list of manufacturer names for each defined language. + * Use @ref APP_USBD_STRING_DESC macro to create string descriptor. + * + * The order of manufacturer names has to be the same like in + * @ref APP_USBD_STRINGS_LANGIDS. + */ +#define APP_USBD_STRINGS_MANUFACTURER \ + APP_USBD_STRING_DESC("Nordic Semiconductor") + +/** + * @brief Define whether @ref APP_USBD_STRINGS_MANUFACTURER is created by @ref APP_USBD_STRING_DESC + * or declared as global variable. + * */ +#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0 + +/** + * @brief Product name string descriptor + * + * List of product names defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER + */ +#define APP_USBD_STRINGS_PRODUCT \ + APP_USBD_STRING_DESC("nRF52840 OpenThread Device") + + +/** + * @brief Define whether @ref APP_USBD_STRINGS_PRODUCT is created by @ref APP_USBD_STRING_DESC + * or declared as global variable. + * */ +#define APP_USBD_STRINGS_PRODUCT_EXTERN 0 + +/** + * @brief Serial number string descriptor + * + * Create serial number string descriptor using @ref APP_USBD_STRING_DESC, + * or configure it to point to any internal variable pointer filled with descriptor. + * + * @note + * There is only one SERIAL number inside the library and it is Language independent. + */ +#define APP_USBD_STRING_SERIAL g_extern_serial_number + +/** + * @brief Define whether @ref APP_USBD_STRING_SERIAL is created by @ref APP_USBD_STRING_DESC + * or declared as global variable. + * */ +#define APP_USBD_STRING_SERIAL_EXTERN 1 + +/** + * @brief User strings default values + * + * This value stores all application specific user strings with its default initialization. + * The setup is done by X-macros. + * Expected macro parameters: + * @code + * X(mnemonic, [=str_idx], ...) + * @endcode + * - @c mnemonic: Mnemonic of the string descriptor that would be added to + * @ref app_usbd_string_desc_idx_t enumerator. + * - @c str_idx : String index value, may be set or left empty. + * For example WinUSB driver requires descriptor to be present on 0xEE index. + * Then use X(USBD_STRING_WINUSB, =0xEE, (APP_USBD_STRING_DESC(...))) + * - @c ... : List of string descriptors for each defined language. + */ +#define APP_USBD_STRINGS_USER \ + X(APP_USER_1, , APP_USBD_STRING_DESC("User 1")) + +/** @} */ +#endif /* APP_USBD_STRING_CONFIG_H */ diff --git a/third_party/NordicSemiconductor/libraries/utf_converter/LICENSE b/third_party/NordicSemiconductor/libraries/utf_converter/LICENSE index 9f7df6b95..fdee8ad7e 100644 --- a/third_party/NordicSemiconductor/libraries/utf_converter/LICENSE +++ b/third_party/NordicSemiconductor/libraries/utf_converter/LICENSE @@ -1,9 +1,9 @@ -Copyright (c) 2016 Pietro Gagliardi - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -(this is called the MIT License or Expat License; see http://www.opensource.org/licenses/MIT) +Copyright (c) 2016 Pietro Gagliardi + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(this is called the MIT License or Expat License; see http://www.opensource.org/licenses/MIT) diff --git a/third_party/NordicSemiconductor/libraries/utf_converter/utf.c b/third_party/NordicSemiconductor/libraries/utf_converter/utf.c index 63a36c99b..e76afe79c 100644 --- a/third_party/NordicSemiconductor/libraries/utf_converter/utf.c +++ b/third_party/NordicSemiconductor/libraries/utf_converter/utf.c @@ -1,350 +1,350 @@ -// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/ -// 10 november 2016 -#include "utf.h" - -// this code imitates Go's unicode/utf8 and unicode/utf16 -// the biggest difference is that a rune is unsigned instead of signed (because Go guarantees what a right shift on a signed number will do, whereas C does not) -// it is also an imitation so we can license it under looser terms than the Go source -#define badrune 0xFFFD - -// encoded must be at most 4 bytes -// TODO clean this code up somehow -size_t utf8EncodeRune(uint32_t rune, char *encoded) -{ - uint8_t b; - uint8_t c = 0; - uint8_t d = 0; - uint8_t e = 0; - size_t n; - - // not in the valid range for Unicode - if (rune > 0x10FFFF) - rune = badrune; - // surrogate runes cannot be encoded - if (rune >= 0xD800 && rune < 0xE000) - rune = badrune; - - if (rune < 0x80) { // ASCII bytes represent themselves - b = (uint8_t) (rune & 0xFF); - n = 1; - goto done; - } - if (rune < 0x800) { // two-byte encoding - c = (uint8_t) (rune & 0x3F); - c |= 0x80; - rune >>= 6; - b = (uint8_t) (rune & 0x1F); - b |= 0xC0; - n = 2; - goto done; - } - if (rune < 0x10000) { // three-byte encoding - d = (uint8_t) (rune & 0x3F); - d |= 0x80; - rune >>= 6; - c = (uint8_t) (rune & 0x3F); - c |= 0x80; - rune >>= 6; - b = (uint8_t) (rune & 0x0F); - b |= 0xE0; - n = 3; - goto done; - } - // otherwise use a four-byte encoding - e = (uint8_t) (rune & 0x3F); - e |= 0x80; - rune >>= 6; - d = (uint8_t) (rune & 0x3F); - d |= 0x80; - rune >>= 6; - c = (uint8_t) (rune & 0x3F); - c |= 0x80; - rune >>= 6; - b = (uint8_t) (rune & 0x07); - b |= 0xF0; - n = 4; - -done: - encoded[0] = b; - if (n > 1) - encoded[1] = c; - if (n > 2) - encoded[2] = d; - if (n > 3) - encoded[3] = e; - return n; -} - -const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune) -{ - uint8_t b, c; - uint8_t lowestAllowed, highestAllowed; - size_t i, expected; - int bad; - - b = (uint8_t) (*s); - if (b < 0x80) { // ASCII bytes represent themselves - *rune = b; - s++; - return s; - } - // 0xC0 and 0xC1 cover 2-byte overlong equivalents - // 0xF5 to 0xFD cover values > 0x10FFFF - // 0xFE and 0xFF were never defined (always illegal) - if (b < 0xC2 || b > 0xF4) { // invalid - *rune = badrune; - s++; - return s; - } - - // this determines the range of allowed first continuation bytes - lowestAllowed = 0x80; - highestAllowed = 0xBF; - switch (b) { - case 0xE0: - // disallow 3-byte overlong equivalents - lowestAllowed = 0xA0; - break; - case 0xED: - // disallow surrogate characters - highestAllowed = 0x9F; - break; - case 0xF0: - // disallow 4-byte overlong equivalents - lowestAllowed = 0x90; - break; - case 0xF4: - // disallow values > 0x10FFFF - highestAllowed = 0x8F; - break; - } - - // and this determines how many continuation bytes are expected - expected = 1; - if (b >= 0xE0) - expected++; - if (b >= 0xF0) - expected++; - if (nElem != 0) { // are there enough bytes? - nElem--; - if (nElem < expected) { // nope - *rune = badrune; - s++; - return s; - } - } - - // ensure that everything is correct - // if not, **only** consume the initial byte - bad = 0; - for (i = 0; i < expected; i++) { - c = (uint8_t) (s[1 + i]); - if (c < lowestAllowed || c > highestAllowed) { - bad = 1; - break; - } - // the old lowestAllowed and highestAllowed is only for the first continuation byte - lowestAllowed = 0x80; - highestAllowed = 0xBF; - } - if (bad) { - *rune = badrune; - s++; - return s; - } - - // now do the topmost bits - if (b < 0xE0) - *rune = b & 0x1F; - else if (b < 0xF0) - *rune = b & 0x0F; - else - *rune = b & 0x07; - s++; // we can finally move on - - // now do the continuation bytes - for (; expected; expected--) { - c = (uint8_t) (*s); - s++; - c &= 0x3F; // strip continuation bits - *rune <<= 6; - *rune |= c; - } - - return s; -} - -// encoded must have at most 2 elements -size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded) -{ - uint16_t low, high; - - // not in the valid range for Unicode - if (rune > 0x10FFFF) - rune = badrune; - // surrogate runes cannot be encoded - if (rune >= 0xD800 && rune < 0xE000) - rune = badrune; - - if (rune < 0x10000) { - encoded[0] = (uint16_t) rune; - return 1; - } - - rune -= 0x10000; - low = (uint16_t) (rune & 0x3FF); - rune >>= 10; - high = (uint16_t) (rune & 0x3FF); - encoded[0] = high | 0xD800; - encoded[1] = low | 0xDC00; - return 2; -} - -// TODO see if this can be cleaned up somehow -const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune) -{ - uint16_t high, low; - - if (*s < 0xD800 || *s >= 0xE000) { - // self-representing character - *rune = *s; - s++; - return s; - } - if (*s >= 0xDC00) { - // out-of-order surrogates - *rune = badrune; - s++; - return s; - } - if (nElem == 1) { // not enough elements - *rune = badrune; - s++; - return s; - } - high = *s; - high &= 0x3FF; - if (s[1] < 0xDC00 || s[1] >= 0xE000) { - // bad surrogate pair - *rune = badrune; - s++; - return s; - } - s++; - low = *s; - s++; - low &= 0x3FF; - *rune = high; - *rune <<= 10; - *rune |= low; - *rune += 0x10000; - return s; -} - -// TODO find a way to reduce the code in all of these somehow -// TODO find a way to remove u as well -size_t utf8RuneCount(const char *s, size_t nElem) -{ - size_t len; - uint32_t rune; - - if (nElem != 0) { - const char *t, *u; - - len = 0; - t = s; - while (nElem != 0) { - u = utf8DecodeRune(t, nElem, &rune); - len++; - nElem -= u - t; - t = u; - } - return len; - } - len = 0; - while (*s) { - s = utf8DecodeRune(s, nElem, &rune); - len++; - } - return len; -} - -size_t utf8UTF16Count(const char *s, size_t nElem) -{ - size_t len; - uint32_t rune; - uint16_t encoded[2]; - - if (nElem != 0) { - const char *t, *u; - - len = 0; - t = s; - while (nElem != 0) { - u = utf8DecodeRune(t, nElem, &rune); - len += utf16EncodeRune(rune, encoded); - nElem -= u - t; - t = u; - } - return len; - } - len = 0; - while (*s) { - s = utf8DecodeRune(s, nElem, &rune); - len += utf16EncodeRune(rune, encoded); - } - return len; -} - -size_t utf16RuneCount(const uint16_t *s, size_t nElem) -{ - size_t len; - uint32_t rune; - - if (nElem != 0) { - const uint16_t *t, *u; - - len = 0; - t = s; - while (nElem != 0) { - u = utf16DecodeRune(t, nElem, &rune); - len++; - nElem -= u - t; - t = u; - } - return len; - } - len = 0; - while (*s) { - s = utf16DecodeRune(s, nElem, &rune); - len++; - } - return len; -} - -size_t utf16UTF8Count(const uint16_t *s, size_t nElem) -{ - size_t len; - uint32_t rune; - char encoded[4]; - - if (nElem != 0) { - const uint16_t *t, *u; - - len = 0; - t = s; - while (nElem != 0) { - u = utf16DecodeRune(t, nElem, &rune); - len += utf8EncodeRune(rune, encoded); - nElem -= u - t; - t = u; - } - return len; - } - len = 0; - while (*s) { - s = utf16DecodeRune(s, nElem, &rune); - len += utf8EncodeRune(rune, encoded); - } - return len; -} +// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/ +// 10 november 2016 +#include "utf.h" + +// this code imitates Go's unicode/utf8 and unicode/utf16 +// the biggest difference is that a rune is unsigned instead of signed (because Go guarantees what a right shift on a signed number will do, whereas C does not) +// it is also an imitation so we can license it under looser terms than the Go source +#define badrune 0xFFFD + +// encoded must be at most 4 bytes +// TODO clean this code up somehow +size_t utf8EncodeRune(uint32_t rune, char *encoded) +{ + uint8_t b; + uint8_t c = 0; + uint8_t d = 0; + uint8_t e = 0; + size_t n; + + // not in the valid range for Unicode + if (rune > 0x10FFFF) + rune = badrune; + // surrogate runes cannot be encoded + if (rune >= 0xD800 && rune < 0xE000) + rune = badrune; + + if (rune < 0x80) { // ASCII bytes represent themselves + b = (uint8_t) (rune & 0xFF); + n = 1; + goto done; + } + if (rune < 0x800) { // two-byte encoding + c = (uint8_t) (rune & 0x3F); + c |= 0x80; + rune >>= 6; + b = (uint8_t) (rune & 0x1F); + b |= 0xC0; + n = 2; + goto done; + } + if (rune < 0x10000) { // three-byte encoding + d = (uint8_t) (rune & 0x3F); + d |= 0x80; + rune >>= 6; + c = (uint8_t) (rune & 0x3F); + c |= 0x80; + rune >>= 6; + b = (uint8_t) (rune & 0x0F); + b |= 0xE0; + n = 3; + goto done; + } + // otherwise use a four-byte encoding + e = (uint8_t) (rune & 0x3F); + e |= 0x80; + rune >>= 6; + d = (uint8_t) (rune & 0x3F); + d |= 0x80; + rune >>= 6; + c = (uint8_t) (rune & 0x3F); + c |= 0x80; + rune >>= 6; + b = (uint8_t) (rune & 0x07); + b |= 0xF0; + n = 4; + +done: + encoded[0] = b; + if (n > 1) + encoded[1] = c; + if (n > 2) + encoded[2] = d; + if (n > 3) + encoded[3] = e; + return n; +} + +const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune) +{ + uint8_t b, c; + uint8_t lowestAllowed, highestAllowed; + size_t i, expected; + int bad; + + b = (uint8_t) (*s); + if (b < 0x80) { // ASCII bytes represent themselves + *rune = b; + s++; + return s; + } + // 0xC0 and 0xC1 cover 2-byte overlong equivalents + // 0xF5 to 0xFD cover values > 0x10FFFF + // 0xFE and 0xFF were never defined (always illegal) + if (b < 0xC2 || b > 0xF4) { // invalid + *rune = badrune; + s++; + return s; + } + + // this determines the range of allowed first continuation bytes + lowestAllowed = 0x80; + highestAllowed = 0xBF; + switch (b) { + case 0xE0: + // disallow 3-byte overlong equivalents + lowestAllowed = 0xA0; + break; + case 0xED: + // disallow surrogate characters + highestAllowed = 0x9F; + break; + case 0xF0: + // disallow 4-byte overlong equivalents + lowestAllowed = 0x90; + break; + case 0xF4: + // disallow values > 0x10FFFF + highestAllowed = 0x8F; + break; + } + + // and this determines how many continuation bytes are expected + expected = 1; + if (b >= 0xE0) + expected++; + if (b >= 0xF0) + expected++; + if (nElem != 0) { // are there enough bytes? + nElem--; + if (nElem < expected) { // nope + *rune = badrune; + s++; + return s; + } + } + + // ensure that everything is correct + // if not, **only** consume the initial byte + bad = 0; + for (i = 0; i < expected; i++) { + c = (uint8_t) (s[1 + i]); + if (c < lowestAllowed || c > highestAllowed) { + bad = 1; + break; + } + // the old lowestAllowed and highestAllowed is only for the first continuation byte + lowestAllowed = 0x80; + highestAllowed = 0xBF; + } + if (bad) { + *rune = badrune; + s++; + return s; + } + + // now do the topmost bits + if (b < 0xE0) + *rune = b & 0x1F; + else if (b < 0xF0) + *rune = b & 0x0F; + else + *rune = b & 0x07; + s++; // we can finally move on + + // now do the continuation bytes + for (; expected; expected--) { + c = (uint8_t) (*s); + s++; + c &= 0x3F; // strip continuation bits + *rune <<= 6; + *rune |= c; + } + + return s; +} + +// encoded must have at most 2 elements +size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded) +{ + uint16_t low, high; + + // not in the valid range for Unicode + if (rune > 0x10FFFF) + rune = badrune; + // surrogate runes cannot be encoded + if (rune >= 0xD800 && rune < 0xE000) + rune = badrune; + + if (rune < 0x10000) { + encoded[0] = (uint16_t) rune; + return 1; + } + + rune -= 0x10000; + low = (uint16_t) (rune & 0x3FF); + rune >>= 10; + high = (uint16_t) (rune & 0x3FF); + encoded[0] = high | 0xD800; + encoded[1] = low | 0xDC00; + return 2; +} + +// TODO see if this can be cleaned up somehow +const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune) +{ + uint16_t high, low; + + if (*s < 0xD800 || *s >= 0xE000) { + // self-representing character + *rune = *s; + s++; + return s; + } + if (*s >= 0xDC00) { + // out-of-order surrogates + *rune = badrune; + s++; + return s; + } + if (nElem == 1) { // not enough elements + *rune = badrune; + s++; + return s; + } + high = *s; + high &= 0x3FF; + if (s[1] < 0xDC00 || s[1] >= 0xE000) { + // bad surrogate pair + *rune = badrune; + s++; + return s; + } + s++; + low = *s; + s++; + low &= 0x3FF; + *rune = high; + *rune <<= 10; + *rune |= low; + *rune += 0x10000; + return s; +} + +// TODO find a way to reduce the code in all of these somehow +// TODO find a way to remove u as well +size_t utf8RuneCount(const char *s, size_t nElem) +{ + size_t len; + uint32_t rune; + + if (nElem != 0) { + const char *t, *u; + + len = 0; + t = s; + while (nElem != 0) { + u = utf8DecodeRune(t, nElem, &rune); + len++; + nElem -= u - t; + t = u; + } + return len; + } + len = 0; + while (*s) { + s = utf8DecodeRune(s, nElem, &rune); + len++; + } + return len; +} + +size_t utf8UTF16Count(const char *s, size_t nElem) +{ + size_t len; + uint32_t rune; + uint16_t encoded[2]; + + if (nElem != 0) { + const char *t, *u; + + len = 0; + t = s; + while (nElem != 0) { + u = utf8DecodeRune(t, nElem, &rune); + len += utf16EncodeRune(rune, encoded); + nElem -= u - t; + t = u; + } + return len; + } + len = 0; + while (*s) { + s = utf8DecodeRune(s, nElem, &rune); + len += utf16EncodeRune(rune, encoded); + } + return len; +} + +size_t utf16RuneCount(const uint16_t *s, size_t nElem) +{ + size_t len; + uint32_t rune; + + if (nElem != 0) { + const uint16_t *t, *u; + + len = 0; + t = s; + while (nElem != 0) { + u = utf16DecodeRune(t, nElem, &rune); + len++; + nElem -= u - t; + t = u; + } + return len; + } + len = 0; + while (*s) { + s = utf16DecodeRune(s, nElem, &rune); + len++; + } + return len; +} + +size_t utf16UTF8Count(const uint16_t *s, size_t nElem) +{ + size_t len; + uint32_t rune; + char encoded[4]; + + if (nElem != 0) { + const uint16_t *t, *u; + + len = 0; + t = s; + while (nElem != 0) { + u = utf16DecodeRune(t, nElem, &rune); + len += utf8EncodeRune(rune, encoded); + nElem -= u - t; + t = u; + } + return len; + } + len = 0; + while (*s) { + s = utf16DecodeRune(s, nElem, &rune); + len += utf8EncodeRune(rune, encoded); + } + return len; +} diff --git a/third_party/NordicSemiconductor/libraries/utf_converter/utf.h b/third_party/NordicSemiconductor/libraries/utf_converter/utf.h index c805736b7..b810a49de 100644 --- a/third_party/NordicSemiconductor/libraries/utf_converter/utf.h +++ b/third_party/NordicSemiconductor/libraries/utf_converter/utf.h @@ -1,61 +1,61 @@ -// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/ -// 10 november 2016 - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -// if nElem == 0, assume the buffer has no upper limit and is '\0' terminated -// otherwise, assume buffer is NOT '\0' terminated but is bounded by nElem *elements* - -extern size_t utf8EncodeRune(uint32_t rune, char *encoded); -extern const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune); -extern size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded); -extern const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune); - -extern size_t utf8RuneCount(const char *s, size_t nElem); -extern size_t utf8UTF16Count(const char *s, size_t nElem); -extern size_t utf16RuneCount(const uint16_t *s, size_t nElem); -extern size_t utf16UTF8Count(const uint16_t *s, size_t nElem); - -#ifdef __cplusplus -} - -// Provide overloads on Windows for using these functions with wchar_t and WCHAR when wchar_t is a keyword in C++ mode (the default). -// Otherwise, you'd need to cast to pass a wchar_t pointer, WCHAR pointer, or equivalent to these functions. -// We use __wchar_t to be independent of the setting; see https://blogs.msdn.microsoft.com/oldnewthing/20161201-00/?p=94836 (ironically posted one day after I initially wrote this code!). -// TODO check this on MinGW-w64 -// TODO check this under /Wall -// TODO C-style casts enough? or will that fail in /Wall? -// TODO same for UniChar/unichar on Mac? if both are unsigned then we have nothing to worry about -#if defined(_MSC_VER) - -inline size_t utf16EncodeRune(uint32_t rune, __wchar_t *encoded) -{ - return utf16EncodeRune(rune, reinterpret_cast(encoded)); -} - -inline const __wchar_t *utf16DecodeRune(const __wchar_t *s, size_t nElem, uint32_t *rune) -{ - const uint16_t *ret; - - ret = utf16DecodeRune(reinterpret_cast(s), nElem, rune); - return reinterpret_cast(ret); -} - -inline size_t utf16RuneCount(const __wchar_t *s, size_t nElem) -{ - return utf16RuneCount(reinterpret_cast(s), nElem); -} - -inline size_t utf16UTF8Count(const __wchar_t *s, size_t nElem) -{ - return utf16UTF8Count(reinterpret_cast(s), nElem); -} - -#endif - -#endif +// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/ +// 10 november 2016 + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +// if nElem == 0, assume the buffer has no upper limit and is '\0' terminated +// otherwise, assume buffer is NOT '\0' terminated but is bounded by nElem *elements* + +extern size_t utf8EncodeRune(uint32_t rune, char *encoded); +extern const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune); +extern size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded); +extern const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune); + +extern size_t utf8RuneCount(const char *s, size_t nElem); +extern size_t utf8UTF16Count(const char *s, size_t nElem); +extern size_t utf16RuneCount(const uint16_t *s, size_t nElem); +extern size_t utf16UTF8Count(const uint16_t *s, size_t nElem); + +#ifdef __cplusplus +} + +// Provide overloads on Windows for using these functions with wchar_t and WCHAR when wchar_t is a keyword in C++ mode (the default). +// Otherwise, you'd need to cast to pass a wchar_t pointer, WCHAR pointer, or equivalent to these functions. +// We use __wchar_t to be independent of the setting; see https://blogs.msdn.microsoft.com/oldnewthing/20161201-00/?p=94836 (ironically posted one day after I initially wrote this code!). +// TODO check this on MinGW-w64 +// TODO check this under /Wall +// TODO C-style casts enough? or will that fail in /Wall? +// TODO same for UniChar/unichar on Mac? if both are unsigned then we have nothing to worry about +#if defined(_MSC_VER) + +inline size_t utf16EncodeRune(uint32_t rune, __wchar_t *encoded) +{ + return utf16EncodeRune(rune, reinterpret_cast(encoded)); +} + +inline const __wchar_t *utf16DecodeRune(const __wchar_t *s, size_t nElem, uint32_t *rune) +{ + const uint16_t *ret; + + ret = utf16DecodeRune(reinterpret_cast(s), nElem, rune); + return reinterpret_cast(ret); +} + +inline size_t utf16RuneCount(const __wchar_t *s, size_t nElem) +{ + return utf16RuneCount(reinterpret_cast(s), nElem); +} + +inline size_t utf16UTF8Count(const __wchar_t *s, size_t nElem) +{ + return utf16UTF8Count(reinterpret_cast(s), nElem); +} + +#endif + +#endif diff --git a/third_party/NordicSemiconductor/softdevice/s140/doc/s140_nrf52_6.1.1_license-agreement.txt b/third_party/NordicSemiconductor/softdevice/s140/doc/s140_nrf52_6.1.1_license-agreement.txt index 2d1bc127c..a71adee7b 100644 --- a/third_party/NordicSemiconductor/softdevice/s140/doc/s140_nrf52_6.1.1_license-agreement.txt +++ b/third_party/NordicSemiconductor/softdevice/s140/doc/s140_nrf52_6.1.1_license-agreement.txt @@ -1,35 +1,35 @@ -Copyright (c) 2007 - 2018, Nordic Semiconductor ASA -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form, except as embedded into a Nordic - Semiconductor ASA integrated circuit in a product or a software update for - such product, must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - -3. Neither the name of Nordic Semiconductor ASA nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -4. This software, with or without modification, must only be used with a - Nordic Semiconductor ASA integrated circuit. - -5. Any software provided in binary form under this license must not be reverse - engineered, decompiled, modified and/or disassembled. - -THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Copyright (c) 2007 - 2018, Nordic Semiconductor ASA +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form, except as embedded into a Nordic + Semiconductor ASA integrated circuit in a product or a software update for + such product, must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +3. Neither the name of Nordic Semiconductor ASA nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +4. This software, with or without modification, must only be used with a + Nordic Semiconductor ASA integrated circuit. + +5. Any software provided in binary form under this license must not be reverse + engineered, decompiled, modified and/or disassembled. + +THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/NordicSemiconductor/softdevice/s140/headers/nrf52/nrf_mbr.h b/third_party/NordicSemiconductor/softdevice/s140/headers/nrf52/nrf_mbr.h index 389cc377d..42e09fc87 100644 --- a/third_party/NordicSemiconductor/softdevice/s140/headers/nrf52/nrf_mbr.h +++ b/third_party/NordicSemiconductor/softdevice/s140/headers/nrf52/nrf_mbr.h @@ -1,268 +1,268 @@ -/* - * Copyright (c) 2014 - 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - @defgroup nrf_mbr_api Master Boot Record API - @{ - - @brief APIs for updating SoftDevice and BootLoader - -*/ - -#ifndef NRF_MBR_H__ -#define NRF_MBR_H__ - -#include "nrf_svc.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** @addtogroup NRF_MBR_DEFINES Defines - * @{ */ - -/**@brief MBR SVC Base number. */ -#define MBR_SVC_BASE (0x18) - -/**@brief Page size in words. */ -#define MBR_PAGE_SIZE_IN_WORDS (1024) - -/** @brief The size that must be reserved for the MBR when a SoftDevice is written to flash. -This is the offset where the first byte of the SoftDevice hex file is written. */ -#define MBR_SIZE (0x1000) - -/** @brief Location (in the flash memory) of the bootloader address. */ -#define MBR_BOOTLOADER_ADDR (0xFF8) - -/** @brief Location (in UICR) of the bootloader address. */ -#define MBR_UICR_BOOTLOADER_ADDR (&(NRF_UICR->NRFFW[0])) - -/** @brief Location (in the flash memory) of the address of the MBR parameter page. */ -#define MBR_PARAM_PAGE_ADDR (0xFFC) - -/** @brief Location (in UICR) of the address of the MBR parameter page. */ -#define MBR_UICR_PARAM_PAGE_ADDR (&(NRF_UICR->NRFFW[1])) - - -/** @} */ - -/** @addtogroup NRF_MBR_ENUMS Enumerations - * @{ */ - -/**@brief nRF Master Boot Record API SVC numbers. */ -enum NRF_MBR_SVCS -{ - SD_MBR_COMMAND = MBR_SVC_BASE, /**< ::sd_mbr_command */ -}; - -/**@brief Possible values for ::sd_mbr_command_t.command */ -enum NRF_MBR_COMMANDS -{ - SD_MBR_COMMAND_COPY_BL, /**< Copy a new BootLoader. @see ::sd_mbr_command_copy_bl_t*/ - SD_MBR_COMMAND_COPY_SD, /**< Copy a new SoftDevice. @see ::sd_mbr_command_copy_sd_t*/ - SD_MBR_COMMAND_INIT_SD, /**< Initialize forwarding interrupts to SD, and run reset function in SD. Does not require any parameters in ::sd_mbr_command_t params.*/ - SD_MBR_COMMAND_COMPARE, /**< This command works like memcmp. @see ::sd_mbr_command_compare_t*/ - SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET, /**< Change the address the MBR starts after a reset. @see ::sd_mbr_command_vector_table_base_set_t*/ - SD_MBR_COMMAND_RESERVED, - SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, /**< Start forwarding all interrupts to this address. @see ::sd_mbr_command_irq_forward_address_set_t*/ -}; - -/** @} */ - -/** @addtogroup NRF_MBR_TYPES Types - * @{ */ - -/**@brief This command copies part of a new SoftDevice - * - * The destination area is erased before copying. - * If dst is in the middle of a flash page, that whole flash page will be erased. - * If (dst+len) is in the middle of a flash page, that whole flash page will be erased. - * - * The user of this function is responsible for setting the BPROT registers. - * - * @retval ::NRF_SUCCESS indicates that the contents of the memory blocks where copied correctly. - * @retval ::NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying. - */ -typedef struct -{ - uint32_t *src; /**< Pointer to the source of data to be copied.*/ - uint32_t *dst; /**< Pointer to the destination where the content is to be copied.*/ - uint32_t len; /**< Number of 32 bit words to copy. Must be a multiple of @ref MBR_PAGE_SIZE_IN_WORDS words.*/ -} sd_mbr_command_copy_sd_t; - - -/**@brief This command works like memcmp, but takes the length in words. - * - * @retval ::NRF_SUCCESS indicates that the contents of both memory blocks are equal. - * @retval ::NRF_ERROR_NULL indicates that the contents of the memory blocks are not equal. - */ -typedef struct -{ - uint32_t *ptr1; /**< Pointer to block of memory. */ - uint32_t *ptr2; /**< Pointer to block of memory. */ - uint32_t len; /**< Number of 32 bit words to compare.*/ -} sd_mbr_command_compare_t; - - -/**@brief This command copies a new BootLoader. - * - * The MBR assumes that either @ref MBR_BOOTLOADER_ADDR or @ref MBR_UICR_BOOTLOADER_ADDR is set to - * the address where the bootloader will be copied. If both addresses are set, the MBR will prioritize - * @ref MBR_BOOTLOADER_ADDR. - * - * The bootloader destination is erased by this function. - * If (destination+bl_len) is in the middle of a flash page, that whole flash page will be erased. - * - * This command requires that @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR is set, - * see @ref sd_mbr_command. - * - * This command will use the flash protect peripheral (BPROT or ACL) to protect the flash that is - * not intended to be written. - * - * On success, this function will not return. It will start the new bootloader from reset-vector as normal. - * - * @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen. - * @retval ::NRF_ERROR_FORBIDDEN if the bootloader address is not set. - * @retval ::NRF_ERROR_INVALID_LENGTH if parameters attempts to read or write outside flash area. - * @retval ::NRF_ERROR_NO_MEM No MBR parameter page is provided. See @ref sd_mbr_command. - */ -typedef struct -{ - uint32_t *bl_src; /**< Pointer to the source of the bootloader to be be copied.*/ - uint32_t bl_len; /**< Number of 32 bit words to copy for BootLoader. */ -} sd_mbr_command_copy_bl_t; - -/**@brief Change the address the MBR starts after a reset - * - * Once this function has been called, this address is where the MBR will start to forward - * interrupts to after a reset. - * - * To restore default forwarding, this function should be called with @ref address set to 0. If a - * bootloader is present, interrupts will be forwarded to the bootloader. If not, interrupts will - * be forwarded to the SoftDevice. - * - * The location of a bootloader can be specified in @ref MBR_BOOTLOADER_ADDR or - * @ref MBR_UICR_BOOTLOADER_ADDR. If both addresses are set, the MBR will prioritize - * @ref MBR_BOOTLOADER_ADDR. - * - * This command requires that @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR is set, - * see @ref sd_mbr_command. - * - * On success, this function will not return. It will reset the device. - * - * @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen. - * @retval ::NRF_ERROR_INVALID_ADDR if parameter address is outside of the flash size. - * @retval ::NRF_ERROR_NO_MEM No MBR parameter page is provided. See @ref sd_mbr_command. - */ -typedef struct -{ - uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/ -} sd_mbr_command_vector_table_base_set_t; - -/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the MBR - * - * Unlike sd_mbr_command_vector_table_base_set_t, this function does not reset, and it does not - * change where the MBR starts after reset. - * - * @retval ::NRF_SUCCESS - */ -typedef struct -{ - uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/ -} sd_mbr_command_irq_forward_address_set_t; - -/**@brief Input structure containing data used when calling ::sd_mbr_command - * - * Depending on what command value that is set, the corresponding params value type must also be - * set. See @ref NRF_MBR_COMMANDS for command types and corresponding params value type. If command - * @ref SD_MBR_COMMAND_INIT_SD is set, it is not necessary to set any values under params. - */ -typedef struct -{ - uint32_t command; /**< Type of command to be issued. See @ref NRF_MBR_COMMANDS. */ - union - { - sd_mbr_command_copy_sd_t copy_sd; /**< Parameters for copy SoftDevice.*/ - sd_mbr_command_compare_t compare; /**< Parameters for verify.*/ - sd_mbr_command_copy_bl_t copy_bl; /**< Parameters for copy BootLoader. Requires parameter page. */ - sd_mbr_command_vector_table_base_set_t base_set; /**< Parameters for vector table base set. Requires parameter page.*/ - sd_mbr_command_irq_forward_address_set_t irq_forward_address_set; /**< Parameters for irq forward address set*/ - } params; /**< Command parameters. */ -} sd_mbr_command_t; - -/** @} */ - -/** @addtogroup NRF_MBR_FUNCTIONS Functions - * @{ */ - -/**@brief Issue Master Boot Record commands - * - * Commands used when updating a SoftDevice and bootloader. - * - * The @ref SD_MBR_COMMAND_COPY_BL and @ref SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET requires - * parameters to be retained by the MBR when resetting the IC. This is done in a separate flash - * page. The location of the flash page should be provided by the application in either - * @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR. If both addresses are set, the MBR - * will prioritize @ref MBR_PARAM_PAGE_ADDR. This page will be cleared by the MBR and is used to - * store the command before reset. When an address is specified, the page it refers to must not be - * used by the application. If no address is provided by the application, i.e. both - * @ref MBR_PARAM_PAGE_ADDR and @ref MBR_UICR_PARAM_PAGE_ADDR is 0xFFFFFFFF, MBR commands which use - * flash will be unavailable and return @ref NRF_ERROR_NO_MEM. - * - * @param[in] param Pointer to a struct describing the command. - * - * @note For a complete set of return values, see ::sd_mbr_command_copy_sd_t, - * ::sd_mbr_command_copy_bl_t, ::sd_mbr_command_compare_t, - * ::sd_mbr_command_vector_table_base_set_t, ::sd_mbr_command_irq_forward_address_set_t - * - * @retval ::NRF_ERROR_NO_MEM No MBR parameter page provided - * @retval ::NRF_ERROR_INVALID_PARAM if an invalid command is given. -*/ -SVCALL(SD_MBR_COMMAND, uint32_t, sd_mbr_command(sd_mbr_command_t* param)); - -/** @} */ - -#ifdef __cplusplus -} -#endif -#endif // NRF_MBR_H__ - -/** - @} -*/ +/* + * Copyright (c) 2014 - 2017, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @defgroup nrf_mbr_api Master Boot Record API + @{ + + @brief APIs for updating SoftDevice and BootLoader + +*/ + +#ifndef NRF_MBR_H__ +#define NRF_MBR_H__ + +#include "nrf_svc.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup NRF_MBR_DEFINES Defines + * @{ */ + +/**@brief MBR SVC Base number. */ +#define MBR_SVC_BASE (0x18) + +/**@brief Page size in words. */ +#define MBR_PAGE_SIZE_IN_WORDS (1024) + +/** @brief The size that must be reserved for the MBR when a SoftDevice is written to flash. +This is the offset where the first byte of the SoftDevice hex file is written. */ +#define MBR_SIZE (0x1000) + +/** @brief Location (in the flash memory) of the bootloader address. */ +#define MBR_BOOTLOADER_ADDR (0xFF8) + +/** @brief Location (in UICR) of the bootloader address. */ +#define MBR_UICR_BOOTLOADER_ADDR (&(NRF_UICR->NRFFW[0])) + +/** @brief Location (in the flash memory) of the address of the MBR parameter page. */ +#define MBR_PARAM_PAGE_ADDR (0xFFC) + +/** @brief Location (in UICR) of the address of the MBR parameter page. */ +#define MBR_UICR_PARAM_PAGE_ADDR (&(NRF_UICR->NRFFW[1])) + + +/** @} */ + +/** @addtogroup NRF_MBR_ENUMS Enumerations + * @{ */ + +/**@brief nRF Master Boot Record API SVC numbers. */ +enum NRF_MBR_SVCS +{ + SD_MBR_COMMAND = MBR_SVC_BASE, /**< ::sd_mbr_command */ +}; + +/**@brief Possible values for ::sd_mbr_command_t.command */ +enum NRF_MBR_COMMANDS +{ + SD_MBR_COMMAND_COPY_BL, /**< Copy a new BootLoader. @see ::sd_mbr_command_copy_bl_t*/ + SD_MBR_COMMAND_COPY_SD, /**< Copy a new SoftDevice. @see ::sd_mbr_command_copy_sd_t*/ + SD_MBR_COMMAND_INIT_SD, /**< Initialize forwarding interrupts to SD, and run reset function in SD. Does not require any parameters in ::sd_mbr_command_t params.*/ + SD_MBR_COMMAND_COMPARE, /**< This command works like memcmp. @see ::sd_mbr_command_compare_t*/ + SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET, /**< Change the address the MBR starts after a reset. @see ::sd_mbr_command_vector_table_base_set_t*/ + SD_MBR_COMMAND_RESERVED, + SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, /**< Start forwarding all interrupts to this address. @see ::sd_mbr_command_irq_forward_address_set_t*/ +}; + +/** @} */ + +/** @addtogroup NRF_MBR_TYPES Types + * @{ */ + +/**@brief This command copies part of a new SoftDevice + * + * The destination area is erased before copying. + * If dst is in the middle of a flash page, that whole flash page will be erased. + * If (dst+len) is in the middle of a flash page, that whole flash page will be erased. + * + * The user of this function is responsible for setting the BPROT registers. + * + * @retval ::NRF_SUCCESS indicates that the contents of the memory blocks where copied correctly. + * @retval ::NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying. + */ +typedef struct +{ + uint32_t *src; /**< Pointer to the source of data to be copied.*/ + uint32_t *dst; /**< Pointer to the destination where the content is to be copied.*/ + uint32_t len; /**< Number of 32 bit words to copy. Must be a multiple of @ref MBR_PAGE_SIZE_IN_WORDS words.*/ +} sd_mbr_command_copy_sd_t; + + +/**@brief This command works like memcmp, but takes the length in words. + * + * @retval ::NRF_SUCCESS indicates that the contents of both memory blocks are equal. + * @retval ::NRF_ERROR_NULL indicates that the contents of the memory blocks are not equal. + */ +typedef struct +{ + uint32_t *ptr1; /**< Pointer to block of memory. */ + uint32_t *ptr2; /**< Pointer to block of memory. */ + uint32_t len; /**< Number of 32 bit words to compare.*/ +} sd_mbr_command_compare_t; + + +/**@brief This command copies a new BootLoader. + * + * The MBR assumes that either @ref MBR_BOOTLOADER_ADDR or @ref MBR_UICR_BOOTLOADER_ADDR is set to + * the address where the bootloader will be copied. If both addresses are set, the MBR will prioritize + * @ref MBR_BOOTLOADER_ADDR. + * + * The bootloader destination is erased by this function. + * If (destination+bl_len) is in the middle of a flash page, that whole flash page will be erased. + * + * This command requires that @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR is set, + * see @ref sd_mbr_command. + * + * This command will use the flash protect peripheral (BPROT or ACL) to protect the flash that is + * not intended to be written. + * + * On success, this function will not return. It will start the new bootloader from reset-vector as normal. + * + * @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen. + * @retval ::NRF_ERROR_FORBIDDEN if the bootloader address is not set. + * @retval ::NRF_ERROR_INVALID_LENGTH if parameters attempts to read or write outside flash area. + * @retval ::NRF_ERROR_NO_MEM No MBR parameter page is provided. See @ref sd_mbr_command. + */ +typedef struct +{ + uint32_t *bl_src; /**< Pointer to the source of the bootloader to be be copied.*/ + uint32_t bl_len; /**< Number of 32 bit words to copy for BootLoader. */ +} sd_mbr_command_copy_bl_t; + +/**@brief Change the address the MBR starts after a reset + * + * Once this function has been called, this address is where the MBR will start to forward + * interrupts to after a reset. + * + * To restore default forwarding, this function should be called with @ref address set to 0. If a + * bootloader is present, interrupts will be forwarded to the bootloader. If not, interrupts will + * be forwarded to the SoftDevice. + * + * The location of a bootloader can be specified in @ref MBR_BOOTLOADER_ADDR or + * @ref MBR_UICR_BOOTLOADER_ADDR. If both addresses are set, the MBR will prioritize + * @ref MBR_BOOTLOADER_ADDR. + * + * This command requires that @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR is set, + * see @ref sd_mbr_command. + * + * On success, this function will not return. It will reset the device. + * + * @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen. + * @retval ::NRF_ERROR_INVALID_ADDR if parameter address is outside of the flash size. + * @retval ::NRF_ERROR_NO_MEM No MBR parameter page is provided. See @ref sd_mbr_command. + */ +typedef struct +{ + uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/ +} sd_mbr_command_vector_table_base_set_t; + +/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the MBR + * + * Unlike sd_mbr_command_vector_table_base_set_t, this function does not reset, and it does not + * change where the MBR starts after reset. + * + * @retval ::NRF_SUCCESS + */ +typedef struct +{ + uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/ +} sd_mbr_command_irq_forward_address_set_t; + +/**@brief Input structure containing data used when calling ::sd_mbr_command + * + * Depending on what command value that is set, the corresponding params value type must also be + * set. See @ref NRF_MBR_COMMANDS for command types and corresponding params value type. If command + * @ref SD_MBR_COMMAND_INIT_SD is set, it is not necessary to set any values under params. + */ +typedef struct +{ + uint32_t command; /**< Type of command to be issued. See @ref NRF_MBR_COMMANDS. */ + union + { + sd_mbr_command_copy_sd_t copy_sd; /**< Parameters for copy SoftDevice.*/ + sd_mbr_command_compare_t compare; /**< Parameters for verify.*/ + sd_mbr_command_copy_bl_t copy_bl; /**< Parameters for copy BootLoader. Requires parameter page. */ + sd_mbr_command_vector_table_base_set_t base_set; /**< Parameters for vector table base set. Requires parameter page.*/ + sd_mbr_command_irq_forward_address_set_t irq_forward_address_set; /**< Parameters for irq forward address set*/ + } params; /**< Command parameters. */ +} sd_mbr_command_t; + +/** @} */ + +/** @addtogroup NRF_MBR_FUNCTIONS Functions + * @{ */ + +/**@brief Issue Master Boot Record commands + * + * Commands used when updating a SoftDevice and bootloader. + * + * The @ref SD_MBR_COMMAND_COPY_BL and @ref SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET requires + * parameters to be retained by the MBR when resetting the IC. This is done in a separate flash + * page. The location of the flash page should be provided by the application in either + * @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR. If both addresses are set, the MBR + * will prioritize @ref MBR_PARAM_PAGE_ADDR. This page will be cleared by the MBR and is used to + * store the command before reset. When an address is specified, the page it refers to must not be + * used by the application. If no address is provided by the application, i.e. both + * @ref MBR_PARAM_PAGE_ADDR and @ref MBR_UICR_PARAM_PAGE_ADDR is 0xFFFFFFFF, MBR commands which use + * flash will be unavailable and return @ref NRF_ERROR_NO_MEM. + * + * @param[in] param Pointer to a struct describing the command. + * + * @note For a complete set of return values, see ::sd_mbr_command_copy_sd_t, + * ::sd_mbr_command_copy_bl_t, ::sd_mbr_command_compare_t, + * ::sd_mbr_command_vector_table_base_set_t, ::sd_mbr_command_irq_forward_address_set_t + * + * @retval ::NRF_ERROR_NO_MEM No MBR parameter page provided + * @retval ::NRF_ERROR_INVALID_PARAM if an invalid command is given. +*/ +SVCALL(SD_MBR_COMMAND, uint32_t, sd_mbr_command(sd_mbr_command_t* param)); + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // NRF_MBR_H__ + +/** + @} +*/ diff --git a/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_InputEchoApp.c b/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_InputEchoApp.c index 156169283..5b453bf40 100644 --- a/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_InputEchoApp.c +++ b/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_InputEchoApp.c @@ -1,43 +1,43 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** - ---------- END-OF-HEADER -------------------------------------------- -File : Main_RTT_MenuApp.c -Purpose : Sample application to demonstrate RTT bi-directional functionality -*/ - -#define MAIN_C - -#include - -#include "SEGGER_RTT.h" - -volatile int _Cnt; -volatile int _Delay; - -static char r; - -/********************************************************************* -* -* main -*/ -void main(void) { - - SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n"); - SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); - do { - r = SEGGER_RTT_WaitKey(); - SEGGER_RTT_Write(0, &r, 1); - r++; - } while (1); -} - -/*************************** End of file ****************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** + +--------- END-OF-HEADER -------------------------------------------- +File : Main_RTT_MenuApp.c +Purpose : Sample application to demonstrate RTT bi-directional functionality +*/ + +#define MAIN_C + +#include + +#include "SEGGER_RTT.h" + +volatile int _Cnt; +volatile int _Delay; + +static char r; + +/********************************************************************* +* +* main +*/ +void main(void) { + + SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n"); + SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); + do { + r = SEGGER_RTT_WaitKey(); + SEGGER_RTT_Write(0, &r, 1); + r++; + } while (1); +} + +/*************************** End of file ****************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_MenuApp.c b/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_MenuApp.c index c6a277ac1..4dbcc84d6 100644 --- a/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_MenuApp.c +++ b/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_MenuApp.c @@ -1,70 +1,70 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** ---------- END-OF-HEADER -------------------------------------------- -File : Main_RTT_MenuApp.c -Purpose : Sample application to demonstrate RTT bi-directional functionality -*/ - -#define MAIN_C - -#include - -#include "SEGGER_RTT.h" - -volatile int _Cnt; -volatile int _Delay; - -/********************************************************************* -* -* main -*/ -void main(void) { - int r; - int CancelOp; - - do { - _Cnt = 0; - - SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n"); - SEGGER_RTT_WriteString(0, "Press <1> to continue in blocking mode (Application waits if necessary, no data lost)\r\n"); - SEGGER_RTT_WriteString(0, "Press <2> to continue in non-blocking mode (Application does not wait, data lost if fifo full)\r\n"); - do { - r = SEGGER_RTT_WaitKey(); - } while ((r != '1') && (r != '2')); - if (r == '1') { - SEGGER_RTT_WriteString(0, "\r\nSelected <1>. Configuring RTT and starting...\r\n"); - SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); - } else { - SEGGER_RTT_WriteString(0, "\r\nSelected <2>. Configuring RTT and starting...\r\n"); - SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); - } - CancelOp = 0; - do { - //for (_Delay = 0; _Delay < 10000; _Delay++); - SEGGER_RTT_printf(0, "Count: %d. Press to get back to menu.\r\n", _Cnt++); - r = SEGGER_RTT_HasKey(); - if (r) { - CancelOp = (SEGGER_RTT_GetKey() == ' ') ? 1 : 0; - } - // - // Check if user selected to cancel the current operation - // - if (CancelOp) { - SEGGER_RTT_WriteString(0, "Operation cancelled, going back to menu...\r\n"); - break; - } - } while (1); - SEGGER_RTT_GetKey(); - SEGGER_RTT_WriteString(0, "\r\n"); - } while (1); -} - -/*************************** End of file ****************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +--------- END-OF-HEADER -------------------------------------------- +File : Main_RTT_MenuApp.c +Purpose : Sample application to demonstrate RTT bi-directional functionality +*/ + +#define MAIN_C + +#include + +#include "SEGGER_RTT.h" + +volatile int _Cnt; +volatile int _Delay; + +/********************************************************************* +* +* main +*/ +void main(void) { + int r; + int CancelOp; + + do { + _Cnt = 0; + + SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n"); + SEGGER_RTT_WriteString(0, "Press <1> to continue in blocking mode (Application waits if necessary, no data lost)\r\n"); + SEGGER_RTT_WriteString(0, "Press <2> to continue in non-blocking mode (Application does not wait, data lost if fifo full)\r\n"); + do { + r = SEGGER_RTT_WaitKey(); + } while ((r != '1') && (r != '2')); + if (r == '1') { + SEGGER_RTT_WriteString(0, "\r\nSelected <1>. Configuring RTT and starting...\r\n"); + SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); + } else { + SEGGER_RTT_WriteString(0, "\r\nSelected <2>. Configuring RTT and starting...\r\n"); + SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); + } + CancelOp = 0; + do { + //for (_Delay = 0; _Delay < 10000; _Delay++); + SEGGER_RTT_printf(0, "Count: %d. Press to get back to menu.\r\n", _Cnt++); + r = SEGGER_RTT_HasKey(); + if (r) { + CancelOp = (SEGGER_RTT_GetKey() == ' ') ? 1 : 0; + } + // + // Check if user selected to cancel the current operation + // + if (CancelOp) { + SEGGER_RTT_WriteString(0, "Operation cancelled, going back to menu...\r\n"); + break; + } + } while (1); + SEGGER_RTT_GetKey(); + SEGGER_RTT_WriteString(0, "\r\n"); + } while (1); +} + +/*************************** End of file ****************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_PrintfTest.c b/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_PrintfTest.c index de81b15db..2d90fff34 100644 --- a/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_PrintfTest.c +++ b/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_PrintfTest.c @@ -1,118 +1,118 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** - ---------- END-OF-HEADER -------------------------------------------- -File : Main_RTT_MenuApp.c -Purpose : Sample application to demonstrate RTT bi-directional functionality -*/ - -#define MAIN_C - -#include - -#include "SEGGER_RTT.h" - -volatile int _Cnt; - -/********************************************************************* -* -* main -*/ -void main(void) { - - SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); - - SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n\r\n"); - SEGGER_RTT_WriteString(0, "###### Testing SEGGER_printf() ######\r\n"); - - SEGGER_RTT_printf(0, "printf Test: %%c, 'S' : %c.\r\n", 'S'); - SEGGER_RTT_printf(0, "printf Test: %%5c, 'E' : %5c.\r\n", 'E'); - SEGGER_RTT_printf(0, "printf Test: %%-5c, 'G' : %-5c.\r\n", 'G'); - SEGGER_RTT_printf(0, "printf Test: %%5.3c, 'G' : %-5c.\r\n", 'G'); - SEGGER_RTT_printf(0, "printf Test: %%.3c, 'E' : %-5c.\r\n", 'E'); - SEGGER_RTT_printf(0, "printf Test: %%c, 'R' : %c.\r\n", 'R'); - - SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\" : %s.\r\n", "RTT"); - SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\\r\\nRocks.\" : %s.\r\n", "RTT\r\nRocks."); - - SEGGER_RTT_printf(0, "printf Test: %%u, 12345 : %u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%+u, 12345 : %+u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%.3u, 12345 : %.3u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%.6u, 12345 : %.6u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%6.3u, 12345 : %6.3u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%8.6u, 12345 : %8.6u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%08u, 12345 : %08u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%08.6u, 12345 : %08.6u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%0u, 12345 : %0u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%-.6u, 12345 : %-.6u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%-6.3u, 12345 : %-6.3u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%-8.6u, 12345 : %-8.6u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%-08u, 12345 : %-08u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%-08.6u, 12345 : %-08.6u.\r\n", 12345); - SEGGER_RTT_printf(0, "printf Test: %%-0u, 12345 : %-0u.\r\n", 12345); - - SEGGER_RTT_printf(0, "printf Test: %%u, -12345 : %u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%+u, -12345 : %+u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%.3u, -12345 : %.3u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%.6u, -12345 : %.6u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%6.3u, -12345 : %6.3u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%8.6u, -12345 : %8.6u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%08u, -12345 : %08u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%08.6u, -12345 : %08.6u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%0u, -12345 : %0u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-.6u, -12345 : %-.6u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-6.3u, -12345 : %-6.3u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-8.6u, -12345 : %-8.6u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-08u, -12345 : %-08u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-08.6u, -12345 : %-08.6u.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-0u, -12345 : %-0u.\r\n", -12345); - - SEGGER_RTT_printf(0, "printf Test: %%d, -12345 : %d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%+d, -12345 : %+d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%.3d, -12345 : %.3d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%.6d, -12345 : %.6d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%6.3d, -12345 : %6.3d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%8.6d, -12345 : %8.6d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%08d, -12345 : %08d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%08.6d, -12345 : %08.6d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%0d, -12345 : %0d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-.6d, -12345 : %-.6d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-6.3d, -12345 : %-6.3d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-8.6d, -12345 : %-8.6d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-08d, -12345 : %-08d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-08.6d, -12345 : %-08.6d.\r\n", -12345); - SEGGER_RTT_printf(0, "printf Test: %%-0d, -12345 : %-0d.\r\n", -12345); - - SEGGER_RTT_printf(0, "printf Test: %%x, 0x1234ABC : %x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%+x, 0x1234ABC : %+x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%.3x, 0x1234ABC : %.3x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%.6x, 0x1234ABC : %.6x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%6.3x, 0x1234ABC : %6.3x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%8.6x, 0x1234ABC : %8.6x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%08x, 0x1234ABC : %08x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%08.6x, 0x1234ABC : %08.6x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%0x, 0x1234ABC : %0x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%-.6x, 0x1234ABC : %-.6x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%-6.3x, 0x1234ABC : %-6.3x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%-8.6x, 0x1234ABC : %-8.6x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%-08x, 0x1234ABC : %-08x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%-08.6x, 0x1234ABC : %-08.6x.\r\n", 0x1234ABC); - SEGGER_RTT_printf(0, "printf Test: %%-0x, 0x1234ABC : %-0x.\r\n", 0x1234ABC); - - SEGGER_RTT_printf(0, "printf Test: %%p, &_Cnt : %p.\r\n", &_Cnt); - - SEGGER_RTT_WriteString(0, "###### SEGGER_printf() Tests done. ######\r\n"); - do { - _Cnt++; - } while (1); -} - -/*************************** End of file ****************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** + +--------- END-OF-HEADER -------------------------------------------- +File : Main_RTT_MenuApp.c +Purpose : Sample application to demonstrate RTT bi-directional functionality +*/ + +#define MAIN_C + +#include + +#include "SEGGER_RTT.h" + +volatile int _Cnt; + +/********************************************************************* +* +* main +*/ +void main(void) { + + SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); + + SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n\r\n"); + SEGGER_RTT_WriteString(0, "###### Testing SEGGER_printf() ######\r\n"); + + SEGGER_RTT_printf(0, "printf Test: %%c, 'S' : %c.\r\n", 'S'); + SEGGER_RTT_printf(0, "printf Test: %%5c, 'E' : %5c.\r\n", 'E'); + SEGGER_RTT_printf(0, "printf Test: %%-5c, 'G' : %-5c.\r\n", 'G'); + SEGGER_RTT_printf(0, "printf Test: %%5.3c, 'G' : %-5c.\r\n", 'G'); + SEGGER_RTT_printf(0, "printf Test: %%.3c, 'E' : %-5c.\r\n", 'E'); + SEGGER_RTT_printf(0, "printf Test: %%c, 'R' : %c.\r\n", 'R'); + + SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\" : %s.\r\n", "RTT"); + SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\\r\\nRocks.\" : %s.\r\n", "RTT\r\nRocks."); + + SEGGER_RTT_printf(0, "printf Test: %%u, 12345 : %u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%+u, 12345 : %+u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%.3u, 12345 : %.3u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%.6u, 12345 : %.6u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%6.3u, 12345 : %6.3u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%8.6u, 12345 : %8.6u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%08u, 12345 : %08u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%08.6u, 12345 : %08.6u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%0u, 12345 : %0u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%-.6u, 12345 : %-.6u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%-6.3u, 12345 : %-6.3u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%-8.6u, 12345 : %-8.6u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%-08u, 12345 : %-08u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%-08.6u, 12345 : %-08.6u.\r\n", 12345); + SEGGER_RTT_printf(0, "printf Test: %%-0u, 12345 : %-0u.\r\n", 12345); + + SEGGER_RTT_printf(0, "printf Test: %%u, -12345 : %u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%+u, -12345 : %+u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%.3u, -12345 : %.3u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%.6u, -12345 : %.6u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%6.3u, -12345 : %6.3u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%8.6u, -12345 : %8.6u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%08u, -12345 : %08u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%08.6u, -12345 : %08.6u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%0u, -12345 : %0u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-.6u, -12345 : %-.6u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-6.3u, -12345 : %-6.3u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-8.6u, -12345 : %-8.6u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-08u, -12345 : %-08u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-08.6u, -12345 : %-08.6u.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-0u, -12345 : %-0u.\r\n", -12345); + + SEGGER_RTT_printf(0, "printf Test: %%d, -12345 : %d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%+d, -12345 : %+d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%.3d, -12345 : %.3d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%.6d, -12345 : %.6d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%6.3d, -12345 : %6.3d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%8.6d, -12345 : %8.6d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%08d, -12345 : %08d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%08.6d, -12345 : %08.6d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%0d, -12345 : %0d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-.6d, -12345 : %-.6d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-6.3d, -12345 : %-6.3d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-8.6d, -12345 : %-8.6d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-08d, -12345 : %-08d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-08.6d, -12345 : %-08.6d.\r\n", -12345); + SEGGER_RTT_printf(0, "printf Test: %%-0d, -12345 : %-0d.\r\n", -12345); + + SEGGER_RTT_printf(0, "printf Test: %%x, 0x1234ABC : %x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%+x, 0x1234ABC : %+x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%.3x, 0x1234ABC : %.3x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%.6x, 0x1234ABC : %.6x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%6.3x, 0x1234ABC : %6.3x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%8.6x, 0x1234ABC : %8.6x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%08x, 0x1234ABC : %08x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%08.6x, 0x1234ABC : %08.6x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%0x, 0x1234ABC : %0x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%-.6x, 0x1234ABC : %-.6x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%-6.3x, 0x1234ABC : %-6.3x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%-8.6x, 0x1234ABC : %-8.6x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%-08x, 0x1234ABC : %-08x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%-08.6x, 0x1234ABC : %-08.6x.\r\n", 0x1234ABC); + SEGGER_RTT_printf(0, "printf Test: %%-0x, 0x1234ABC : %-0x.\r\n", 0x1234ABC); + + SEGGER_RTT_printf(0, "printf Test: %%p, &_Cnt : %p.\r\n", &_Cnt); + + SEGGER_RTT_WriteString(0, "###### SEGGER_printf() Tests done. ######\r\n"); + do { + _Cnt++; + } while (1); +} + +/*************************** End of file ****************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_SpeedTestApp.c b/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_SpeedTestApp.c index 304b16f4f..0dc0c75dc 100644 --- a/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_SpeedTestApp.c +++ b/third_party/jlink/SEGGER_RTT_V640/Examples/Main_RTT_SpeedTestApp.c @@ -1,69 +1,69 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** - ---------- END-OF-HEADER -------------------------------------------- -File : Main_RTT_SpeedTestApp.c -Purpose : Sample program for measuring RTT performance. -*/ - -#include "RTOS.h" -#include "BSP.h" - -#include "SEGGER_RTT.h" -#include - -OS_STACKPTR int StackHP[128], StackLP[128]; /* Task stacks */ -OS_TASK TCBHP, TCBLP; /* Task-control-blocks */ - -static void HPTask(void) { - while (1) { - // - // Measure time needed for RTT output - // Perform dummy write with 0 characters, so we know the overhead of toggling LEDs and RTT in general - // -// Set BP here. Then start sampling on scope - BSP_ClrLED(0); - SEGGER_RTT_Write(0, 0, 0); - BSP_SetLED(0); - BSP_ClrLED(0); - SEGGER_RTT_Write(0, "01234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n", 82); - BSP_SetLED(0); -// Set BP here. Then stop sampling on scope - OS_Delay(200); - } -} - -static void LPTask(void) { - while (1) { - BSP_ToggleLED(1); - OS_Delay (500); - } -} - -/********************************************************************* -* -* main -* -*********************************************************************/ - -int main(void) { - OS_IncDI(); /* Initially disable interrupts */ - OS_InitKern(); /* Initialize OS */ - OS_InitHW(); /* Initialize Hardware for OS */ - BSP_Init(); /* Initialize LED ports */ - BSP_SetLED(0); - /* You need to create at least one task before calling OS_Start() */ - OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP); - OS_CREATETASK(&TCBLP, "LP Task", LPTask, 50, StackLP); - OS_Start(); /* Start multitasking */ - return 0; -} - +/********************************************************************* +* SEGGER Microcontroller GmbH * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** + +--------- END-OF-HEADER -------------------------------------------- +File : Main_RTT_SpeedTestApp.c +Purpose : Sample program for measuring RTT performance. +*/ + +#include "RTOS.h" +#include "BSP.h" + +#include "SEGGER_RTT.h" +#include + +OS_STACKPTR int StackHP[128], StackLP[128]; /* Task stacks */ +OS_TASK TCBHP, TCBLP; /* Task-control-blocks */ + +static void HPTask(void) { + while (1) { + // + // Measure time needed for RTT output + // Perform dummy write with 0 characters, so we know the overhead of toggling LEDs and RTT in general + // +// Set BP here. Then start sampling on scope + BSP_ClrLED(0); + SEGGER_RTT_Write(0, 0, 0); + BSP_SetLED(0); + BSP_ClrLED(0); + SEGGER_RTT_Write(0, "01234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n", 82); + BSP_SetLED(0); +// Set BP here. Then stop sampling on scope + OS_Delay(200); + } +} + +static void LPTask(void) { + while (1) { + BSP_ToggleLED(1); + OS_Delay (500); + } +} + +/********************************************************************* +* +* main +* +*********************************************************************/ + +int main(void) { + OS_IncDI(); /* Initially disable interrupts */ + OS_InitKern(); /* Initialize OS */ + OS_InitHW(); /* Initialize Hardware for OS */ + BSP_Init(); /* Initialize LED ports */ + BSP_SetLED(0); + /* You need to create at least one task before calling OS_Start() */ + OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP); + OS_CREATETASK(&TCBLP, "LP Task", LPTask, 50, StackLP); + OS_Start(); /* Start multitasking */ + return 0; +} + diff --git a/third_party/jlink/SEGGER_RTT_V640/License.txt b/third_party/jlink/SEGGER_RTT_V640/License.txt index 263093a5b..bfe93b39a 100644 --- a/third_party/jlink/SEGGER_RTT_V640/License.txt +++ b/third_party/jlink/SEGGER_RTT_V640/License.txt @@ -1,44 +1,44 @@ -Important - Read carefully: - -SEGGER RTT - Real Time Transfer for embedded targets - -All rights reserved. - -SEGGER strongly recommends to not make any changes -to or modify the source code of this software in order to stay -compatible with the RTT protocol and J-Link. - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the following -conditions are met: - -o Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -o Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - -o Neither the name of SEGGER Microcontroller GmbH - nor the names of its contributors may be used to endorse or - promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. - - -(c) 2014 - 2016 SEGGER Microcontroller GmbH -www.segger.com +Important - Read carefully: + +SEGGER RTT - Real Time Transfer for embedded targets + +All rights reserved. + +SEGGER strongly recommends to not make any changes +to or modify the source code of this software in order to stay +compatible with the RTT protocol and J-Link. + +Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following +conditions are met: + +o Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +o Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +o Neither the name of SEGGER Microcontroller GmbH + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + + +(c) 2014 - 2016 SEGGER Microcontroller GmbH +www.segger.com diff --git a/third_party/jlink/SEGGER_RTT_V640/README.txt b/third_party/jlink/SEGGER_RTT_V640/README.txt index 4dd23eba2..49ec655c4 100644 --- a/third_party/jlink/SEGGER_RTT_V640/README.txt +++ b/third_party/jlink/SEGGER_RTT_V640/README.txt @@ -1,20 +1,20 @@ -README.txt for the SEGGER RTT Implementation Pack. - -Included files: -=============== -Root Directory - - Examples - - Main_RTT_InputEchoApp.c - Sample application which echoes input on Channel 0. - - Main_RTT_MenuApp.c - Sample application to demonstrate RTT bi-directional functionality. - - Main_RTT_PrintfTest.c - Sample application to test RTT small printf implementation. - - Main_RTT_SpeedTestApp.c - Sample application for measuring RTT performance. embOS needed. - - RTT - - SEGGER_RTT.c - The RTT implementation. - - SEGGER_RTT.h - Header for RTT implementation. - - SEGGER_RTT_Conf.h - Pre-processor configuration for the RTT implementation. - - SEGGER_RTT_Printf.c - Simple implementation of printf to write formatted strings via RTT. - - Syscalls - - RTT_Syscalls_GCC.c - Low-level syscalls to retarget printf() to RTT with GCC / Newlib. - - RTT_Syscalls_IAR.c - Low-level syscalls to retarget printf() to RTT with IAR compiler. - - RTT_Syscalls_KEIL.c - Low-level syscalls to retarget printf() to RTT with KEIL/uVision compiler. - - RTT_Syscalls_SES.c - Low-level syscalls to retarget printf() to RTT with SEGGER Embedded Studio. +README.txt for the SEGGER RTT Implementation Pack. + +Included files: +=============== +Root Directory + - Examples + - Main_RTT_InputEchoApp.c - Sample application which echoes input on Channel 0. + - Main_RTT_MenuApp.c - Sample application to demonstrate RTT bi-directional functionality. + - Main_RTT_PrintfTest.c - Sample application to test RTT small printf implementation. + - Main_RTT_SpeedTestApp.c - Sample application for measuring RTT performance. embOS needed. + - RTT + - SEGGER_RTT.c - The RTT implementation. + - SEGGER_RTT.h - Header for RTT implementation. + - SEGGER_RTT_Conf.h - Pre-processor configuration for the RTT implementation. + - SEGGER_RTT_Printf.c - Simple implementation of printf to write formatted strings via RTT. + - Syscalls + - RTT_Syscalls_GCC.c - Low-level syscalls to retarget printf() to RTT with GCC / Newlib. + - RTT_Syscalls_IAR.c - Low-level syscalls to retarget printf() to RTT with IAR compiler. + - RTT_Syscalls_KEIL.c - Low-level syscalls to retarget printf() to RTT with KEIL/uVision compiler. + - RTT_Syscalls_SES.c - Low-level syscalls to retarget printf() to RTT with SEGGER Embedded Studio. diff --git a/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.c b/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.c index 8f278800f..8fc0f6c1f 100644 --- a/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.c +++ b/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.c @@ -1,1761 +1,1761 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* conditions are met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* o Redistributions in binary form must reproduce the above * -* copyright notice, this list of conditions and the following * -* disclaimer in the documentation and/or other materials provided * -* with the distribution. * -* * -* o Neither the name of SEGGER Microcontroller GmbH * -* nor the names of its contributors may be used to endorse or * -* promote products derived from this software without specific * -* prior written permission. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.c -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. -Revision: $Rev: 12804 $ - -Additional information: - Type "int" is assumed to be 32-bits in size - H->T Host to target communication - T->H Target to host communication - - RTT channel 0 is always present and reserved for Terminal usage. - Name is fixed to "Terminal" - - Effective buffer size: SizeOfBuffer - 1 - - WrOff == RdOff: Buffer is empty - WrOff == (RdOff - 1): Buffer is full - WrOff > RdOff: Free space includes wrap-around - WrOff < RdOff: Used space includes wrap-around - (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): - Buffer full and wrap-around after next byte - - ----------------------------------------------------------------------- -*/ - -#include "SEGGER_RTT.h" - -#include // for memcpy - -/********************************************************************* -* -* Configuration, default values -* -********************************************************************** -*/ - -#ifndef BUFFER_SIZE_UP - #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host -#endif - -#ifndef BUFFER_SIZE_DOWN - #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) -#endif - -#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS - #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target -#endif - -#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS - #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target -#endif - -#ifndef SEGGER_RTT_BUFFER_SECTION - #if defined(SEGGER_RTT_SECTION) - #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION - #endif -#endif - -#ifndef SEGGER_RTT_ALIGNMENT - #define SEGGER_RTT_ALIGNMENT 0 -#endif - -#ifndef SEGGER_RTT_BUFFER_ALIGNMENT - #define SEGGER_RTT_BUFFER_ALIGNMENT 0 -#endif - -#ifndef SEGGER_RTT_MODE_DEFAULT - #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP -#endif - -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() -#endif - -#ifndef STRLEN - #define STRLEN(a) strlen((a)) -#endif - -#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP - #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 -#endif - -#ifndef SEGGER_RTT_MEMCPY - #ifdef MEMCPY - #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) - #else - #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) - #endif -#endif - -#ifndef MIN - #define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef MAX - #define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif -// -// For some environments, NULL may not be defined until certain headers are included -// -#ifndef NULL - #define NULL 0 -#endif - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ -#if (defined __ICCARM__) || (defined __ICCRX__) - #define RTT_PRAGMA(P) _Pragma(#P) -#endif - -#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT - #if (defined __GNUC__) - #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) - #elif (defined __ICCARM__) || (defined __ICCRX__) - #define PRAGMA(A) _Pragma(#A) -#define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ - Var - #elif (defined __CC_ARM) - #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) - #else - #error "Alignment not supported for this compiler." - #endif -#else - #define SEGGER_RTT_ALIGN(Var, Alignment) Var -#endif - -#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) - #if (defined __GNUC__) - #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var - #elif (defined __ICCARM__) || (defined __ICCRX__) -#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ - Var - #elif (defined __CC_ARM) - #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var - #else - #error "Section placement not supported for this compiler." - #endif -#else - #define SEGGER_RTT_PUT_SECTION(Var, Section) Var -#endif - - -#if SEGGER_RTT_ALIGNMENT - #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) -#else - #define SEGGER_RTT_CB_ALIGN(Var) Var -#endif - -#if SEGGER_RTT_BUFFER_ALIGNMENT - #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) -#else - #define SEGGER_RTT_BUFFER_ALIGN(Var) Var -#endif - - -#if defined(SEGGER_RTT_SECTION) - #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) -#else - #define SEGGER_RTT_PUT_CB_SECTION(Var) Var -#endif - -#if defined(SEGGER_RTT_BUFFER_SECTION) - #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) -#else - #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var -#endif - -/********************************************************************* -* -* Static const data -* -********************************************************************** -*/ - -static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - -/********************************************************************* -* -* Static data -* -********************************************************************** -*/ -// -// RTT Control Block and allocate buffers for channel 0 -// -SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); - -SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); -SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); - -static char _ActiveTerminal; - -/********************************************************************* -* -* Static functions -* -********************************************************************** -*/ - -/********************************************************************* -* -* _DoInit() -* -* Function description -* Initializes the control block an buffers. -* May only be called via INIT() to avoid overriding settings. -* -*/ -#define INIT() do { \ - if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ - } while (0) -static void _DoInit(void) { - SEGGER_RTT_CB* p; - // - // Initialize control block - // - p = &_SEGGER_RTT; - p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; - p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; - // - // Initialize up buffer 0 - // - p->aUp[0].sName = "Terminal"; - p->aUp[0].pBuffer = _acUpBuffer; - p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); - p->aUp[0].RdOff = 0u; - p->aUp[0].WrOff = 0u; - p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Initialize down buffer 0 - // - p->aDown[0].sName = "Terminal"; - p->aDown[0].pBuffer = _acDownBuffer; - p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); - p->aDown[0].RdOff = 0u; - p->aDown[0].WrOff = 0u; - p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Finish initialization of the control block. - // Copy Id string in three steps to make sure "SEGGER RTT" is not found - // in initializer memory (usually flash) by J-Link - // - strcpy(&p->acID[7], "RTT"); - strcpy(&p->acID[0], "SEGGER"); - p->acID[6] = ' '; -} - -/********************************************************************* -* -* _WriteBlocking() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* The caller is responsible for managing the write chunk sizes as -* _WriteBlocking() will block until all data has been posted successfully. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* >= 0 - Number of bytes written into buffer. -*/ -static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { - unsigned NumBytesToWrite; - unsigned NumBytesWritten; - unsigned RdOff; - unsigned WrOff; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - // - // Write data to buffer and handle wrap-around if necessary - // - NumBytesWritten = 0u; - WrOff = pRing->WrOff; - do { - RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime - if (RdOff > WrOff) { - NumBytesToWrite = RdOff - WrOff - 1u; - } else { - NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); - } - NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around - NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - NumBytesWritten += NumBytesToWrite; - NumBytes -= NumBytesToWrite; - WrOff += NumBytesToWrite; - while (NumBytesToWrite--) { - *pDst++ = *pBuffer++; - }; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); - NumBytesWritten += NumBytesToWrite; - pBuffer += NumBytesToWrite; - NumBytes -= NumBytesToWrite; - WrOff += NumBytesToWrite; -#endif - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0u; - } - pRing->WrOff = WrOff; - } while (NumBytes); - // - return NumBytesWritten; -} - -/********************************************************************* -* -* _WriteNoCheck() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* It is callers responsibility to make sure data actually fits in buffer. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking -*/ -static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { - unsigned NumBytesAtOnce; - unsigned WrOff; - unsigned Rem; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - - WrOff = pRing->WrOff; - Rem = pRing->SizeOfBuffer - WrOff; - if (Rem > NumBytes) { - // - // All data fits before wrap around - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - WrOff += NumBytes; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff = WrOff; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; -#endif - } else { - // - // We reach the end of the buffer, so need to wrap around - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - NumBytesAtOnce = Rem; - while (NumBytesAtOnce--) { - *pDst++ = *pData++; - }; - pDst = pRing->pBuffer; - NumBytesAtOnce = NumBytes - Rem; - while (NumBytesAtOnce--) { - *pDst++ = *pData++; - }; - pRing->WrOff = NumBytes - Rem; -#else - NumBytesAtOnce = Rem; - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); - NumBytesAtOnce = NumBytes - Rem; - SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce); - pRing->WrOff = NumBytesAtOnce; -#endif - } -} - -/********************************************************************* -* -* _PostTerminalSwitch() -* -* Function description -* Switch terminal to the given terminal ID. It is the caller's -* responsibility to ensure the terminal ID is correct and there is -* enough space in the buffer for this to complete successfully. -* -* Parameters -* pRing Ring buffer to post to. -* TerminalId Terminal ID to switch to. -*/ -static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { - unsigned char ac[2]; - - ac[0] = 0xFFu; - ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit - _WriteBlocking(pRing, (const char*)ac, 2u); -} - -/********************************************************************* -* -* _GetAvailWriteSpace() -* -* Function description -* Returns the number of bytes that can be written to the ring -* buffer without blocking. -* -* Parameters -* pRing Ring buffer to check. -* -* Return value -* Number of bytes that are free in the buffer. -*/ -static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { - unsigned RdOff; - unsigned WrOff; - unsigned r; - // - // Avoid warnings regarding volatile access order. It's not a problem - // in this case, but dampen compiler enthusiasm. - // - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - if (RdOff <= WrOff) { - r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; - } else { - r = RdOff - WrOff - 1u; - } - return r; -} - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ -/********************************************************************* -* -* SEGGER_RTT_ReadNoLock() -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* Do not lock against interrupts and multiple access. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - unsigned NumBytesRem; - unsigned NumBytesRead; - unsigned RdOff; - unsigned WrOff; - unsigned char* pBuffer; - SEGGER_RTT_BUFFER_DOWN* pRing; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - const char* pSrc; -#endif - // - INIT(); - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - pBuffer = (unsigned char*)pData; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - NumBytesRead = 0u; - // - // Read from current read position to wrap-around of buffer, first - // - if (RdOff > WrOff) { - NumBytesRem = pRing->SizeOfBuffer - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - // - // Handle wrap-around of buffer - // - if (RdOff == pRing->SizeOfBuffer) { - RdOff = 0u; - } - } - // - // Read remaining items of buffer - // - NumBytesRem = WrOff - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - if (NumBytesRem > 0u) { -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - } - if (NumBytesRead) { - pRing->RdOff = RdOff; - } - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_Read -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { - unsigned NumBytesRead; - // - SEGGER_RTT_LOCK(); - // - // Call the non-locking read function - // - NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteWithOverwriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block. -* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application -* and overwrites data if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, data is overwritten. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link -* connection reads RTT data. -*/ -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Check if we will overwrite data and need to adjust the RdOff. - // - if (pRing->WrOff == pRing->RdOff) { - Avail = pRing->SizeOfBuffer - 1u; - } else if ( pRing->WrOff < pRing->RdOff) { - Avail = pRing->RdOff - pRing->WrOff - 1u; - } else { - Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; - } - if (NumBytes > Avail) { - pRing->RdOff += (NumBytes - Avail); - while (pRing->RdOff >= pRing->SizeOfBuffer) { - pRing->RdOff -= pRing->SizeOfBuffer; - } - } - // - // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds - // - Avail = pRing->SizeOfBuffer - pRing->WrOff; - do { - if (Avail > NumBytes) { - // - // Last round - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + pRing->WrOff; - Avail = NumBytes; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff += Avail; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes); - pRing->WrOff += NumBytes; -#endif - break; - } else { - // - // Wrap-around necessary, write until wrap-around and reset WrOff - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + pRing->WrOff; - NumBytes -= Avail; - while (Avail--) { - *pDst++ = *pData++; - }; - pRing->WrOff = 0; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail); - pData += Avail; - pRing->WrOff = 0; - NumBytes -= Avail; -#endif - Avail = (pRing->SizeOfBuffer - 1); - } - } while (NumBytes); -} - -/********************************************************************* -* -* SEGGER_RTT_WriteSkipNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteSkipNoLock does not lock the application and -* skips all data, if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, all data is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - unsigned RdOff; - unsigned WrOff; - unsigned Rem; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - // - // Handle the most common cases fastest. - // Which is: - // RdOff <= WrOff -> Space until wrap around is free. - // AND - // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. - // - // OR - // - // RdOff > WrOff -> Space until RdOff - 1 is free. - // AND - // WrOff + NumBytes < RdOff -> Data fits into buffer - // - if (RdOff <= WrOff) { - // - // Get space until WrOff will be at wrap around. - // - Avail = pRing->SizeOfBuffer - 1u - WrOff ; - if (Avail >= NumBytes) { -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - WrOff += NumBytes; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff = WrOff; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; -#endif - return 1; - } - // - // If data did not fit into space until wrap around calculate complete space in buffer. - // - Avail += RdOff; - // - // If there is still no space for the whole of this output, don't bother. - // - if (Avail >= NumBytes) { - // - // OK, we have enough space in buffer. Copy in one or 2 chunks - // - Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer - if (Rem > NumBytes) { -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - WrOff += NumBytes; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff = WrOff; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; -#endif - } else { - // - // We reach the end of the buffer, so need to wrap around - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - NumBytes -= Rem; - WrOff = NumBytes; - do { - *pDst++ = *pData++; - } while (--Rem); - pDst = pRing->pBuffer; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff = WrOff; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, Rem); - SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytes - Rem); - pRing->WrOff = NumBytes - Rem; -#endif - } - return 1; - } - } else { - Avail = RdOff - WrOff - 1u; - if (Avail >= NumBytes) { -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - WrOff += NumBytes; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff = WrOff; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; -#endif - return 1; - } - } - // - // If we reach this point no data has been written - // - return 0; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteNoLock does not lock the application. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - unsigned Avail; - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // How we output depends upon the mode... - // - switch (pRing->Flags) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother. - // - Avail = _GetAvailWriteSpace(pRing); - if (Avail < NumBytes) { - Status = 0u; - } else { - Status = NumBytes; - _WriteNoCheck(pRing, pData, NumBytes); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode, trim to what we can output without blocking. - // - Avail = _GetAvailWriteSpace(pRing); - Status = Avail < NumBytes ? Avail : NumBytes; - _WriteNoCheck(pRing, pData, Status); - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - Status = _WriteBlocking(pRing, pData, NumBytes); - break; - default: - Status = 0u; - break; - } - // - // Finish up. - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_Write -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -*/ -unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Call the non-locking write function - // - Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteString -* -* Function description -* Stores string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* s Pointer to string. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* (2) String passed to this function has to be \0 terminated -* (3) \0 termination character is *not* stored in RTT buffer -*/ -unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { - unsigned Len; - - Len = STRLEN(s); - return SEGGER_RTT_Write(BufferIndex, s, Len); -} - -/********************************************************************* -* -* SEGGER_RTT_PutCharSkipNoLock -* -* Function description -* Stores a single character/byte in SEGGER RTT buffer. -* SEGGER_RTT_PutCharSkipNoLock does not lock the application and -* skips the byte, if it does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* c Byte to be stored. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, the character is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ - -unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned WrOff; - unsigned Status; - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Get write position and handle wrap-around if necessary - // - WrOff = pRing->WrOff + 1; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0; - } - // - // Output byte if free space is available - // - if (WrOff != pRing->RdOff) { - pRing->pBuffer[pRing->WrOff] = c; - pRing->WrOff = WrOff; - Status = 1; - } else { - Status = 0; - } - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_PutCharSkip -* -* Function description -* Stores a single character/byte in SEGGER RTT buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* c Byte to be stored. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, the character is dropped. -*/ - -unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned WrOff; - unsigned Status; - // - // Prepare - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Get write position and handle wrap-around if necessary - // - WrOff = pRing->WrOff + 1; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0; - } - // - // Output byte if free space is available - // - if (WrOff != pRing->RdOff) { - pRing->pBuffer[pRing->WrOff] = c; - pRing->WrOff = WrOff; - Status = 1; - } else { - Status = 0; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - - /********************************************************************* -* -* SEGGER_RTT_PutChar -* -* Function description -* Stores a single character/byte in SEGGER RTT buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* c Byte to be stored. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -*/ - -unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned WrOff; - unsigned Status; - // - // Prepare - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Get write position and handle wrap-around if necessary - // - WrOff = pRing->WrOff + 1; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0; - } - // - // Wait for free space if mode is set to blocking - // - if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { - while (WrOff == pRing->RdOff) { - ; - } - } - // - // Output byte if free space is available - // - if (WrOff != pRing->RdOff) { - pRing->pBuffer[pRing->WrOff] = c; - pRing->WrOff = WrOff; - Status = 1; - } else { - Status = 0; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_GetKey -* -* Function description -* Reads one character from the SEGGER RTT buffer. -* Host has previously stored data there. -* -* Return value -* < 0 - No character available (buffer empty). -* >= 0 - Character which has been read. (Possible values: 0 - 255) -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0. -*/ -int SEGGER_RTT_GetKey(void) { - char c; - int r; - - r = (int)SEGGER_RTT_Read(0u, &c, 1u); - if (r == 1) { - r = (int)(unsigned char)c; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_WaitKey -* -* Function description -* Waits until at least one character is avaible in the SEGGER RTT buffer. -* Once a character is available, it is read and this function returns. -* -* Return value -* >=0 - Character which has been read. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -* (2) This function is blocking if no character is present in RTT buffer -*/ -int SEGGER_RTT_WaitKey(void) { - int r; - - do { - r = SEGGER_RTT_GetKey(); - } while (r < 0); - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasKey -* -* Function description -* Checks if at least one character for reading is available in the SEGGER RTT buffer. -* -* Return value -* == 0 - No characters are available to read. -* == 1 - At least one character is available. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -*/ -int SEGGER_RTT_HasKey(void) { - unsigned RdOff; - int r; - - INIT(); - RdOff = _SEGGER_RTT.aDown[0].RdOff; - if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { - r = 1; - } else { - r = 0; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasData -* -* Function description -* Check if there is data from the host in the given buffer. -* -* Return value: -* ==0: No data -* !=0: Data in buffer -* -*/ -unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { - SEGGER_RTT_BUFFER_DOWN* pRing; - unsigned v; - - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - v = pRing->WrOff; - return v - pRing->RdOff; -} - -/********************************************************************* -* -* SEGGER_RTT_HasDataUp -* -* Function description -* Check if there is data remaining to be sent in the given buffer. -* -* Return value: -* ==0: No data -* !=0: Data in buffer -* -*/ -unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned v; - - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - v = pRing->RdOff; - return pRing->WrOff - v; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocDownBuffer -* -* Function description -* Run-time configuration of the next down-buffer (H->T). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocUpBuffer -* -* Function description -* Run-time configuration of the next up-buffer (T->H). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer (T->H). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. -* < 0 - Error -* -* Additional information -* Buffer 0 is configured on compile-time. -* May only be called once per buffer. -* Buffer name and flags can be reconfigured using the appropriate functions. -*/ -int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigDownBuffer -* -* Function description -* Run-time configuration of a specific down-buffer (H->T). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 O.K. -* < 0 Error -* -* Additional information -* Buffer 0 is configured on compile-time. -* May only be called once per buffer. -* Buffer name and flags can be reconfigured using the appropriate functions. -*/ -int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameDownBuffer -* -* Function description -* Run-time configuration of a specific Down-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetFlagsUpBuffer -* -* Function description -* Run-time configuration of specific up-buffer flags (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer. -* Flags Flags to set for the buffer. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetFlagsDownBuffer -* -* Function description -* Run-time configuration of specific Down-buffer flags (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* Flags Flags to set for the buffer. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_Init -* -* Function description -* Initializes the RTT Control Block. -* Should be used in RAM targets, at start of the application. -* -*/ -void SEGGER_RTT_Init (void) { - _DoInit(); -} - -/********************************************************************* -* -* SEGGER_RTT_SetTerminal -* -* Function description -* Sets the terminal to be used for output on channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* -* Return value -* >= 0 O.K. -* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) -*/ -int SEGGER_RTT_SetTerminal (char TerminalId) { - unsigned char ac[2]; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - int r; - // - INIT(); - // - r = 0; - ac[0] = 0xFFu; - if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels - ac[1] = _aTerminalId[(unsigned char)TerminalId]; - pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed - SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing - if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { - _ActiveTerminal = TerminalId; - _WriteBlocking(pRing, (const char*)ac, 2u); - } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes - Avail = _GetAvailWriteSpace(pRing); - if (Avail >= 2) { - _ActiveTerminal = TerminalId; // Only change active terminal in case of success - _WriteNoCheck(pRing, (const char*)ac, 2u); - } else { - r = -1; - } - } - SEGGER_RTT_UNLOCK(); - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_TerminalOut -* -* Function description -* Writes a string to the given terminal -* without changing the terminal for channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* s String to be printed on the terminal. -* -* Return value -* >= 0 - Number of bytes written. -* < 0 - Error. -* -*/ -int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { - int Status; - unsigned FragLen; - unsigned Avail; - SEGGER_RTT_BUFFER_UP* pRing; - // - INIT(); - // - // Validate terminal ID. - // - if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[0]; - // - // Need to be able to change terminal, write data, change back. - // Compute the fixed and variable sizes. - // - FragLen = STRLEN(s); - // - // How we output depends upon the mode... - // - SEGGER_RTT_LOCK(); - Avail = _GetAvailWriteSpace(pRing); - switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother switching terminals at all. - // - if (Avail < (FragLen + 4u)) { - Status = 0; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode and there is not enough space for everything, - // trim the output but always include the terminal switch. If no room - // for terminal switch, skip that totally. - // - if (Avail < 4u) { - Status = -1; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - break; - default: - Status = -1; - break; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - } else { - Status = -1; - } - return Status; -} - - -/*************************** End of file ****************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.c +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +Revision: $Rev: 12804 $ + +Additional information: + Type "int" is assumed to be 32-bits in size + H->T Host to target communication + T->H Target to host communication + + RTT channel 0 is always present and reserved for Terminal usage. + Name is fixed to "Terminal" + + Effective buffer size: SizeOfBuffer - 1 + + WrOff == RdOff: Buffer is empty + WrOff == (RdOff - 1): Buffer is full + WrOff > RdOff: Free space includes wrap-around + WrOff < RdOff: Used space includes wrap-around + (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): + Buffer full and wrap-around after next byte + + +---------------------------------------------------------------------- +*/ + +#include "SEGGER_RTT.h" + +#include // for memcpy + +/********************************************************************* +* +* Configuration, default values +* +********************************************************************** +*/ + +#ifndef BUFFER_SIZE_UP + #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host +#endif + +#ifndef BUFFER_SIZE_DOWN + #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) +#endif + +#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS + #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target +#endif + +#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS + #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target +#endif + +#ifndef SEGGER_RTT_BUFFER_SECTION + #if defined(SEGGER_RTT_SECTION) + #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION + #endif +#endif + +#ifndef SEGGER_RTT_ALIGNMENT + #define SEGGER_RTT_ALIGNMENT 0 +#endif + +#ifndef SEGGER_RTT_BUFFER_ALIGNMENT + #define SEGGER_RTT_BUFFER_ALIGNMENT 0 +#endif + +#ifndef SEGGER_RTT_MODE_DEFAULT + #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP +#endif + +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() +#endif + +#ifndef STRLEN + #define STRLEN(a) strlen((a)) +#endif + +#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP + #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 +#endif + +#ifndef SEGGER_RTT_MEMCPY + #ifdef MEMCPY + #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) + #else + #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) + #endif +#endif + +#ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +// +// For some environments, NULL may not be defined until certain headers are included +// +#ifndef NULL + #define NULL 0 +#endif + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ +#if (defined __ICCARM__) || (defined __ICCRX__) + #define RTT_PRAGMA(P) _Pragma(#P) +#endif + +#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT + #if (defined __GNUC__) + #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) + #elif (defined __ICCARM__) || (defined __ICCRX__) + #define PRAGMA(A) _Pragma(#A) +#define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ + Var + #elif (defined __CC_ARM) + #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) + #else + #error "Alignment not supported for this compiler." + #endif +#else + #define SEGGER_RTT_ALIGN(Var, Alignment) Var +#endif + +#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) + #if (defined __GNUC__) + #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var + #elif (defined __ICCARM__) || (defined __ICCRX__) +#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ + Var + #elif (defined __CC_ARM) + #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var + #else + #error "Section placement not supported for this compiler." + #endif +#else + #define SEGGER_RTT_PUT_SECTION(Var, Section) Var +#endif + + +#if SEGGER_RTT_ALIGNMENT + #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) +#else + #define SEGGER_RTT_CB_ALIGN(Var) Var +#endif + +#if SEGGER_RTT_BUFFER_ALIGNMENT + #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) +#else + #define SEGGER_RTT_BUFFER_ALIGN(Var) Var +#endif + + +#if defined(SEGGER_RTT_SECTION) + #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) +#else + #define SEGGER_RTT_PUT_CB_SECTION(Var) Var +#endif + +#if defined(SEGGER_RTT_BUFFER_SECTION) + #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) +#else + #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var +#endif + +/********************************************************************* +* +* Static const data +* +********************************************************************** +*/ + +static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +/********************************************************************* +* +* Static data +* +********************************************************************** +*/ +// +// RTT Control Block and allocate buffers for channel 0 +// +SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); + +SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); +SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); + +static char _ActiveTerminal; + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _DoInit() +* +* Function description +* Initializes the control block an buffers. +* May only be called via INIT() to avoid overriding settings. +* +*/ +#define INIT() do { \ + if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ + } while (0) +static void _DoInit(void) { + SEGGER_RTT_CB* p; + // + // Initialize control block + // + p = &_SEGGER_RTT; + p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; + p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; + // + // Initialize up buffer 0 + // + p->aUp[0].sName = "Terminal"; + p->aUp[0].pBuffer = _acUpBuffer; + p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); + p->aUp[0].RdOff = 0u; + p->aUp[0].WrOff = 0u; + p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Initialize down buffer 0 + // + p->aDown[0].sName = "Terminal"; + p->aDown[0].pBuffer = _acDownBuffer; + p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); + p->aDown[0].RdOff = 0u; + p->aDown[0].WrOff = 0u; + p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Finish initialization of the control block. + // Copy Id string in three steps to make sure "SEGGER RTT" is not found + // in initializer memory (usually flash) by J-Link + // + strcpy(&p->acID[7], "RTT"); + strcpy(&p->acID[0], "SEGGER"); + p->acID[6] = ' '; +} + +/********************************************************************* +* +* _WriteBlocking() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* The caller is responsible for managing the write chunk sizes as +* _WriteBlocking() will block until all data has been posted successfully. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* >= 0 - Number of bytes written into buffer. +*/ +static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { + unsigned NumBytesToWrite; + unsigned NumBytesWritten; + unsigned RdOff; + unsigned WrOff; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + // + // Write data to buffer and handle wrap-around if necessary + // + NumBytesWritten = 0u; + WrOff = pRing->WrOff; + do { + RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime + if (RdOff > WrOff) { + NumBytesToWrite = RdOff - WrOff - 1u; + } else { + NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); + } + NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around + NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + NumBytesWritten += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; + while (NumBytesToWrite--) { + *pDst++ = *pBuffer++; + }; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); + NumBytesWritten += NumBytesToWrite; + pBuffer += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; +#endif + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0u; + } + pRing->WrOff = WrOff; + } while (NumBytes); + // + return NumBytesWritten; +} + +/********************************************************************* +* +* _WriteNoCheck() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* It is callers responsibility to make sure data actually fits in buffer. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking +*/ +static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { + unsigned NumBytesAtOnce; + unsigned WrOff; + unsigned Rem; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + + WrOff = pRing->WrOff; + Rem = pRing->SizeOfBuffer - WrOff; + if (Rem > NumBytes) { + // + // All data fits before wrap around + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + } else { + // + // We reach the end of the buffer, so need to wrap around + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + NumBytesAtOnce = Rem; + while (NumBytesAtOnce--) { + *pDst++ = *pData++; + }; + pDst = pRing->pBuffer; + NumBytesAtOnce = NumBytes - Rem; + while (NumBytesAtOnce--) { + *pDst++ = *pData++; + }; + pRing->WrOff = NumBytes - Rem; +#else + NumBytesAtOnce = Rem; + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); + NumBytesAtOnce = NumBytes - Rem; + SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce); + pRing->WrOff = NumBytesAtOnce; +#endif + } +} + +/********************************************************************* +* +* _PostTerminalSwitch() +* +* Function description +* Switch terminal to the given terminal ID. It is the caller's +* responsibility to ensure the terminal ID is correct and there is +* enough space in the buffer for this to complete successfully. +* +* Parameters +* pRing Ring buffer to post to. +* TerminalId Terminal ID to switch to. +*/ +static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { + unsigned char ac[2]; + + ac[0] = 0xFFu; + ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit + _WriteBlocking(pRing, (const char*)ac, 2u); +} + +/********************************************************************* +* +* _GetAvailWriteSpace() +* +* Function description +* Returns the number of bytes that can be written to the ring +* buffer without blocking. +* +* Parameters +* pRing Ring buffer to check. +* +* Return value +* Number of bytes that are free in the buffer. +*/ +static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { + unsigned RdOff; + unsigned WrOff; + unsigned r; + // + // Avoid warnings regarding volatile access order. It's not a problem + // in this case, but dampen compiler enthusiasm. + // + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + if (RdOff <= WrOff) { + r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; + } else { + r = RdOff - WrOff - 1u; + } + return r; +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_ReadNoLock() +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* Do not lock against interrupts and multiple access. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { + unsigned NumBytesRem; + unsigned NumBytesRead; + unsigned RdOff; + unsigned WrOff; + unsigned char* pBuffer; + SEGGER_RTT_BUFFER_DOWN* pRing; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + const char* pSrc; +#endif + // + INIT(); + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + pBuffer = (unsigned char*)pData; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + NumBytesRead = 0u; + // + // Read from current read position to wrap-around of buffer, first + // + if (RdOff > WrOff) { + NumBytesRem = pRing->SizeOfBuffer - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pSrc = pRing->pBuffer + RdOff; + NumBytesRead += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + while (NumBytesRem--) { + *pBuffer++ = *pSrc++; + }; +#else + SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; +#endif + // + // Handle wrap-around of buffer + // + if (RdOff == pRing->SizeOfBuffer) { + RdOff = 0u; + } + } + // + // Read remaining items of buffer + // + NumBytesRem = WrOff - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + if (NumBytesRem > 0u) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pSrc = pRing->pBuffer + RdOff; + NumBytesRead += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + while (NumBytesRem--) { + *pBuffer++ = *pSrc++; + }; +#else + SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; +#endif + } + if (NumBytesRead) { + pRing->RdOff = RdOff; + } + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_Read +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { + unsigned NumBytesRead; + // + SEGGER_RTT_LOCK(); + // + // Call the non-locking read function + // + NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteWithOverwriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block. +* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application +* and overwrites data if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, data is overwritten. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link +* connection reads RTT data. +*/ +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Check if we will overwrite data and need to adjust the RdOff. + // + if (pRing->WrOff == pRing->RdOff) { + Avail = pRing->SizeOfBuffer - 1u; + } else if ( pRing->WrOff < pRing->RdOff) { + Avail = pRing->RdOff - pRing->WrOff - 1u; + } else { + Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; + } + if (NumBytes > Avail) { + pRing->RdOff += (NumBytes - Avail); + while (pRing->RdOff >= pRing->SizeOfBuffer) { + pRing->RdOff -= pRing->SizeOfBuffer; + } + } + // + // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds + // + Avail = pRing->SizeOfBuffer - pRing->WrOff; + do { + if (Avail > NumBytes) { + // + // Last round + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + pRing->WrOff; + Avail = NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff += Avail; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes); + pRing->WrOff += NumBytes; +#endif + break; + } else { + // + // Wrap-around necessary, write until wrap-around and reset WrOff + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + pRing->WrOff; + NumBytes -= Avail; + while (Avail--) { + *pDst++ = *pData++; + }; + pRing->WrOff = 0; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail); + pData += Avail; + pRing->WrOff = 0; + NumBytes -= Avail; +#endif + Avail = (pRing->SizeOfBuffer - 1); + } + } while (NumBytes); +} + +/********************************************************************* +* +* SEGGER_RTT_WriteSkipNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteSkipNoLock does not lock the application and +* skips all data, if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, all data is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + unsigned RdOff; + unsigned WrOff; + unsigned Rem; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + // + // Handle the most common cases fastest. + // Which is: + // RdOff <= WrOff -> Space until wrap around is free. + // AND + // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. + // + // OR + // + // RdOff > WrOff -> Space until RdOff - 1 is free. + // AND + // WrOff + NumBytes < RdOff -> Data fits into buffer + // + if (RdOff <= WrOff) { + // + // Get space until WrOff will be at wrap around. + // + Avail = pRing->SizeOfBuffer - 1u - WrOff ; + if (Avail >= NumBytes) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + return 1; + } + // + // If data did not fit into space until wrap around calculate complete space in buffer. + // + Avail += RdOff; + // + // If there is still no space for the whole of this output, don't bother. + // + if (Avail >= NumBytes) { + // + // OK, we have enough space in buffer. Copy in one or 2 chunks + // + Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer + if (Rem > NumBytes) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + } else { + // + // We reach the end of the buffer, so need to wrap around + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + NumBytes -= Rem; + WrOff = NumBytes; + do { + *pDst++ = *pData++; + } while (--Rem); + pDst = pRing->pBuffer; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, Rem); + SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytes - Rem); + pRing->WrOff = NumBytes - Rem; +#endif + } + return 1; + } + } else { + Avail = RdOff - WrOff - 1u; + if (Avail >= NumBytes) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + return 1; + } + } + // + // If we reach this point no data has been written + // + return 0; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteNoLock does not lock the application. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + unsigned Avail; + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // How we output depends upon the mode... + // + switch (pRing->Flags) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother. + // + Avail = _GetAvailWriteSpace(pRing); + if (Avail < NumBytes) { + Status = 0u; + } else { + Status = NumBytes; + _WriteNoCheck(pRing, pData, NumBytes); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode, trim to what we can output without blocking. + // + Avail = _GetAvailWriteSpace(pRing); + Status = Avail < NumBytes ? Avail : NumBytes; + _WriteNoCheck(pRing, pData, Status); + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + Status = _WriteBlocking(pRing, pData, NumBytes); + break; + default: + Status = 0u; + break; + } + // + // Finish up. + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_Write +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +*/ +unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Call the non-locking write function + // + Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteString +* +* Function description +* Stores string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* s Pointer to string. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +* (2) String passed to this function has to be \0 terminated +* (3) \0 termination character is *not* stored in RTT buffer +*/ +unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { + unsigned Len; + + Len = STRLEN(s); + return SEGGER_RTT_Write(BufferIndex, s, Len); +} + +/********************************************************************* +* +* SEGGER_RTT_PutCharSkipNoLock +* +* Function description +* Stores a single character/byte in SEGGER RTT buffer. +* SEGGER_RTT_PutCharSkipNoLock does not lock the application and +* skips the byte, if it does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* c Byte to be stored. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, the character is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ + +unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned WrOff; + unsigned Status; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Get write position and handle wrap-around if necessary + // + WrOff = pRing->WrOff + 1; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0; + } + // + // Output byte if free space is available + // + if (WrOff != pRing->RdOff) { + pRing->pBuffer[pRing->WrOff] = c; + pRing->WrOff = WrOff; + Status = 1; + } else { + Status = 0; + } + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_PutCharSkip +* +* Function description +* Stores a single character/byte in SEGGER RTT buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* c Byte to be stored. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, the character is dropped. +*/ + +unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned WrOff; + unsigned Status; + // + // Prepare + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Get write position and handle wrap-around if necessary + // + WrOff = pRing->WrOff + 1; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0; + } + // + // Output byte if free space is available + // + if (WrOff != pRing->RdOff) { + pRing->pBuffer[pRing->WrOff] = c; + pRing->WrOff = WrOff; + Status = 1; + } else { + Status = 0; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + + /********************************************************************* +* +* SEGGER_RTT_PutChar +* +* Function description +* Stores a single character/byte in SEGGER RTT buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* c Byte to be stored. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +*/ + +unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned WrOff; + unsigned Status; + // + // Prepare + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Get write position and handle wrap-around if necessary + // + WrOff = pRing->WrOff + 1; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0; + } + // + // Wait for free space if mode is set to blocking + // + if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + while (WrOff == pRing->RdOff) { + ; + } + } + // + // Output byte if free space is available + // + if (WrOff != pRing->RdOff) { + pRing->pBuffer[pRing->WrOff] = c; + pRing->WrOff = WrOff; + Status = 1; + } else { + Status = 0; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_GetKey +* +* Function description +* Reads one character from the SEGGER RTT buffer. +* Host has previously stored data there. +* +* Return value +* < 0 - No character available (buffer empty). +* >= 0 - Character which has been read. (Possible values: 0 - 255) +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0. +*/ +int SEGGER_RTT_GetKey(void) { + char c; + int r; + + r = (int)SEGGER_RTT_Read(0u, &c, 1u); + if (r == 1) { + r = (int)(unsigned char)c; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_WaitKey +* +* Function description +* Waits until at least one character is avaible in the SEGGER RTT buffer. +* Once a character is available, it is read and this function returns. +* +* Return value +* >=0 - Character which has been read. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +* (2) This function is blocking if no character is present in RTT buffer +*/ +int SEGGER_RTT_WaitKey(void) { + int r; + + do { + r = SEGGER_RTT_GetKey(); + } while (r < 0); + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasKey +* +* Function description +* Checks if at least one character for reading is available in the SEGGER RTT buffer. +* +* Return value +* == 0 - No characters are available to read. +* == 1 - At least one character is available. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +*/ +int SEGGER_RTT_HasKey(void) { + unsigned RdOff; + int r; + + INIT(); + RdOff = _SEGGER_RTT.aDown[0].RdOff; + if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { + r = 1; + } else { + r = 0; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasData +* +* Function description +* Check if there is data from the host in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { + SEGGER_RTT_BUFFER_DOWN* pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + v = pRing->WrOff; + return v - pRing->RdOff; +} + +/********************************************************************* +* +* SEGGER_RTT_HasDataUp +* +* Function description +* Check if there is data remaining to be sent in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + v = pRing->RdOff; + return pRing->WrOff - v; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocDownBuffer +* +* Function description +* Run-time configuration of the next down-buffer (H->T). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocUpBuffer +* +* Function description +* Run-time configuration of the next up-buffer (T->H). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer (T->H). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. +* < 0 - Error +* +* Additional information +* Buffer 0 is configured on compile-time. +* May only be called once per buffer. +* Buffer name and flags can be reconfigured using the appropriate functions. +*/ +int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigDownBuffer +* +* Function description +* Run-time configuration of a specific down-buffer (H->T). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 O.K. +* < 0 Error +* +* Additional information +* Buffer 0 is configured on compile-time. +* May only be called once per buffer. +* Buffer name and flags can be reconfigured using the appropriate functions. +*/ +int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameDownBuffer +* +* Function description +* Run-time configuration of a specific Down-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetFlagsUpBuffer +* +* Function description +* Run-time configuration of specific up-buffer flags (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer. +* Flags Flags to set for the buffer. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetFlagsDownBuffer +* +* Function description +* Run-time configuration of specific Down-buffer flags (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* Flags Flags to set for the buffer. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_Init +* +* Function description +* Initializes the RTT Control Block. +* Should be used in RAM targets, at start of the application. +* +*/ +void SEGGER_RTT_Init (void) { + _DoInit(); +} + +/********************************************************************* +* +* SEGGER_RTT_SetTerminal +* +* Function description +* Sets the terminal to be used for output on channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* +* Return value +* >= 0 O.K. +* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) +*/ +int SEGGER_RTT_SetTerminal (char TerminalId) { + unsigned char ac[2]; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + int r; + // + INIT(); + // + r = 0; + ac[0] = 0xFFu; + if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels + ac[1] = _aTerminalId[(unsigned char)TerminalId]; + pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed + SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing + if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + _ActiveTerminal = TerminalId; + _WriteBlocking(pRing, (const char*)ac, 2u); + } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes + Avail = _GetAvailWriteSpace(pRing); + if (Avail >= 2) { + _ActiveTerminal = TerminalId; // Only change active terminal in case of success + _WriteNoCheck(pRing, (const char*)ac, 2u); + } else { + r = -1; + } + } + SEGGER_RTT_UNLOCK(); + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_TerminalOut +* +* Function description +* Writes a string to the given terminal +* without changing the terminal for channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* s String to be printed on the terminal. +* +* Return value +* >= 0 - Number of bytes written. +* < 0 - Error. +* +*/ +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { + int Status; + unsigned FragLen; + unsigned Avail; + SEGGER_RTT_BUFFER_UP* pRing; + // + INIT(); + // + // Validate terminal ID. + // + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[0]; + // + // Need to be able to change terminal, write data, change back. + // Compute the fixed and variable sizes. + // + FragLen = STRLEN(s); + // + // How we output depends upon the mode... + // + SEGGER_RTT_LOCK(); + Avail = _GetAvailWriteSpace(pRing); + switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother switching terminals at all. + // + if (Avail < (FragLen + 4u)) { + Status = 0; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode and there is not enough space for everything, + // trim the output but always include the terminal switch. If no room + // for terminal switch, skip that totally. + // + if (Avail < 4u) { + Status = -1; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + break; + default: + Status = -1; + break; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + } else { + Status = -1; + } + return Status; +} + + +/*************************** End of file ****************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.h b/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.h index 35ac87017..7c6a0a930 100644 --- a/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.h +++ b/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT.h @@ -1,260 +1,260 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* conditions are met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* o Redistributions in binary form must reproduce the above * -* copyright notice, this list of conditions and the following * -* disclaimer in the documentation and/or other materials provided * -* with the distribution. * -* * -* o Neither the name of SEGGER Microcontroller GmbH * -* nor the names of its contributors may be used to endorse or * -* promote products derived from this software without specific * -* prior written permission. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.h -Purpose : Implementation of SEGGER real-time transfer which allows - real-time communication on targets which support debugger - memory accesses while the CPU is running. -Revision: $Rev: 12826 $ ----------------------------------------------------------------------- -*/ - -#ifndef SEGGER_RTT_H -#define SEGGER_RTT_H - -#ifdef SEGGER_RTT_CONFIG_H -#include SEGGER_RTT_CONFIG_H -#else -#include "SEGGER_RTT_Conf.h" -#endif - -#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file -#include -#include - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as up-buffer (T->H) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - unsigned WrOff; // Position of next item to be written by either target. - volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_UP; - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as down-buffer (H->T) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. - unsigned RdOff; // Position of next item to be read by target (down-buffer). - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_DOWN; - -// -// RTT control block which describes the number of buffers available -// as well as the configuration for each buffer -// -// -typedef struct { - char acID[16]; // Initialized to "SEGGER RTT" - int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) - int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) - SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host - SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target -} SEGGER_RTT_CB; - -/********************************************************************* -* -* Global data -* -********************************************************************** -*/ -extern SEGGER_RTT_CB _SEGGER_RTT; - -/********************************************************************* -* -* RTT API functions -* -********************************************************************** -*/ -#ifdef __cplusplus - extern "C" { -#endif -int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_GetKey (void); -unsigned SEGGER_RTT_HasData (unsigned BufferIndex); -int SEGGER_RTT_HasKey (void); -unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); -void SEGGER_RTT_Init (void); -unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); -int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); -int SEGGER_RTT_WaitKey (void); -unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); -// -// Function macro for performance optimization -// -#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) - -/********************************************************************* -* -* RTT "Terminal" API functions -* -********************************************************************** -*/ -int SEGGER_RTT_SetTerminal (char TerminalId); -int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); - -/********************************************************************* -* -* RTT printf functions (require SEGGER_RTT_printf.c) -* -********************************************************************** -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); - -#ifdef __cplusplus - } -#endif - -#endif // SEGGER_RTT_ASM - -/********************************************************************* -* -* Defines -* -********************************************************************** -*/ - -// -// Operating modes. Define behavior if buffer is full (not enough space for entire message) -// -#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) -#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. -#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. -#define SEGGER_RTT_MODE_MASK (3) - -// -// Control sequences, based on ANSI. -// Can be used to control color, and clear the screen -// -#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors -#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left - -#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" -#define RTT_CTRL_TEXT_RED "\x1B[2;31m" -#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" -#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" -#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" -#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" -#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" -#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" - -#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" -#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" -#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" -#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" -#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" -#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" -#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" -#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" - -#define RTT_CTRL_BG_BLACK "\x1B[24;40m" -#define RTT_CTRL_BG_RED "\x1B[24;41m" -#define RTT_CTRL_BG_GREEN "\x1B[24;42m" -#define RTT_CTRL_BG_YELLOW "\x1B[24;43m" -#define RTT_CTRL_BG_BLUE "\x1B[24;44m" -#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" -#define RTT_CTRL_BG_CYAN "\x1B[24;46m" -#define RTT_CTRL_BG_WHITE "\x1B[24;47m" - -#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" -#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" -#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" -#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" -#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" -#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" -#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" -#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" - - -#endif - -/*************************** End of file ****************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.h +Purpose : Implementation of SEGGER real-time transfer which allows + real-time communication on targets which support debugger + memory accesses while the CPU is running. +Revision: $Rev: 12826 $ +---------------------------------------------------------------------- +*/ + +#ifndef SEGGER_RTT_H +#define SEGGER_RTT_H + +#ifdef SEGGER_RTT_CONFIG_H +#include SEGGER_RTT_CONFIG_H +#else +#include "SEGGER_RTT_Conf.h" +#endif + +#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file +#include +#include + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as up-buffer (T->H) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + unsigned WrOff; // Position of next item to be written by either target. + volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_UP; + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as down-buffer (H->T) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. + unsigned RdOff; // Position of next item to be read by target (down-buffer). + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_DOWN; + +// +// RTT control block which describes the number of buffers available +// as well as the configuration for each buffer +// +// +typedef struct { + char acID[16]; // Initialized to "SEGGER RTT" + int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) + int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) + SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host + SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target +} SEGGER_RTT_CB; + +/********************************************************************* +* +* Global data +* +********************************************************************** +*/ +extern SEGGER_RTT_CB _SEGGER_RTT; + +/********************************************************************* +* +* RTT API functions +* +********************************************************************** +*/ +#ifdef __cplusplus + extern "C" { +#endif +int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_GetKey (void); +unsigned SEGGER_RTT_HasData (unsigned BufferIndex); +int SEGGER_RTT_HasKey (void); +unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); +void SEGGER_RTT_Init (void); +unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); +unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); +int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); +int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); +int SEGGER_RTT_WaitKey (void); +unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); +unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); +unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); +// +// Function macro for performance optimization +// +#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) + +/********************************************************************* +* +* RTT "Terminal" API functions +* +********************************************************************** +*/ +int SEGGER_RTT_SetTerminal (char TerminalId); +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); + +/********************************************************************* +* +* RTT printf functions (require SEGGER_RTT_printf.c) +* +********************************************************************** +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +#ifdef __cplusplus + } +#endif + +#endif // SEGGER_RTT_ASM + +/********************************************************************* +* +* Defines +* +********************************************************************** +*/ + +// +// Operating modes. Define behavior if buffer is full (not enough space for entire message) +// +#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) +#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. +#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. +#define SEGGER_RTT_MODE_MASK (3) + +// +// Control sequences, based on ANSI. +// Can be used to control color, and clear the screen +// +#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors +#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left + +#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" +#define RTT_CTRL_TEXT_RED "\x1B[2;31m" +#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" +#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" +#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" +#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" +#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" +#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" + +#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" +#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" +#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" +#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" +#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" +#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" +#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" +#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" + +#define RTT_CTRL_BG_BLACK "\x1B[24;40m" +#define RTT_CTRL_BG_RED "\x1B[24;41m" +#define RTT_CTRL_BG_GREEN "\x1B[24;42m" +#define RTT_CTRL_BG_YELLOW "\x1B[24;43m" +#define RTT_CTRL_BG_BLUE "\x1B[24;44m" +#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" +#define RTT_CTRL_BG_CYAN "\x1B[24;46m" +#define RTT_CTRL_BG_WHITE "\x1B[24;47m" + +#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" +#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" +#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" +#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" +#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" +#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" +#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" +#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" + + +#endif + +/*************************** End of file ****************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT_Conf.h b/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT_Conf.h index d8112ac38..d1ccfdd02 100644 --- a/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT_Conf.h +++ b/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT_Conf.h @@ -1,340 +1,340 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* conditions are met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* o Redistributions in binary form must reproduce the above * -* copyright notice, this list of conditions and the following * -* disclaimer in the documentation and/or other materials provided * -* with the distribution. * -* * -* o Neither the name of SEGGER Microcontroller GmbH * -* nor the names of its contributors may be used to endorse or * -* promote products derived from this software without specific * -* prior written permission. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Conf.h -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. -Revision: $Rev: 12847 $ - -*/ - -#ifndef SEGGER_RTT_CONF_H -#define SEGGER_RTT_CONF_H - -#ifdef __IAR_SYSTEMS_ICC__ - #include -#endif - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3) -#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3) - -#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) -#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) - -#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) - -#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) - -#define USE_RTT_ASM (0) // Use assembler version of SEGGER_RTT.c when 1 - -/********************************************************************* -* -* RTT memcpy configuration -* -* memcpy() is good for large amounts of data, -* but the overhead is big for small amounts, which are usually stored via RTT. -* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. -* -* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. -* This is may be required with memory access restrictions, -* such as on Cortex-A devices with MMU. -*/ -#define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop -// -// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets -// -//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) -// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) -//#endif - -// -// Target is not allowed to perform other RTT operations while string still has not been stored completely. -// Otherwise we would probably end up with a mixed string in the buffer. -// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. -// -// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. -// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. -// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. -// (Higher priority = lower priority number) -// Default value for embOS: 128u -// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC -// or define SEGGER_RTT_LOCK() to completely disable interrupts. -// - -#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) - -/********************************************************************* -* -* RTT lock configuration for SEGGER Embedded Studio, -* Rowley CrossStudio and GCC -*/ -#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) || (defined __clang__) - #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, primask \n\t" \ - "movs r1, $1 \n\t" \ - "msr primask, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, basepri \n\t" \ - "mov r1, %1 \n\t" \ - "msr basepri, r1 \n\t" \ - : "=r" (LockState) \ - : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - - #elif defined(__ARM_ARCH_7A__) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs r1, CPSR \n\t" \ - "mov %0, r1 \n\t" \ - "orr r1, r1, #0xC0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ - "mrs r1, CPSR \n\t" \ - "bic r1, r1, #0xC0 \n\t" \ - "and r0, r0, #0xC0 \n\t" \ - "orr r1, r1, r0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : \ - : "r" (LockState) \ - : "r0", "r1" \ - ); \ - } -#else - #define SEGGER_RTT_LOCK() - #define SEGGER_RTT_UNLOCK() - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR EWARM -*/ -#ifdef __ICCARM__ - #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ - } - #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__))) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_BASEPRI(); \ - __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR RX -*/ -#ifdef __ICCRX__ - #define SEGGER_RTT_LOCK() { \ - unsigned long LockState; \ - LockState = __get_interrupt_state(); \ - __disable_interrupt(); - - #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR RL78 -*/ -#ifdef __ICCRL78__ - #define SEGGER_RTT_LOCK() { \ - __istate_t LockState; \ - LockState = __get_interrupt_state(); \ - __disable_interrupt(); - - #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for KEIL ARM -*/ -#ifdef __CC_ARM - #if (defined __TARGET_ARCH_6S_M) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char PRIMASK __asm( "primask"); \ - LockState = PRIMASK; \ - PRIMASK = 1u; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ - __schedule_barrier(); \ - } - #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char BASEPRI __asm( "basepri"); \ - LockState = BASEPRI; \ - BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ - __schedule_barrier(); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for TI ARM -*/ -#ifdef __TI_ARM__ - #if defined (__TI_ARM_V6M0__) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ - } - #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for CCRX -*/ -#ifdef __RX - #define SEGGER_RTT_LOCK() { \ - unsigned long LockState; \ - LockState = get_psw() & 0x010000; \ - clrpsw_i(); - - #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration fallback -*/ -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) -#endif - -#endif -/*************************** End of file ****************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Conf.h +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +Revision: $Rev: 12847 $ + +*/ + +#ifndef SEGGER_RTT_CONF_H +#define SEGGER_RTT_CONF_H + +#ifdef __IAR_SYSTEMS_ICC__ + #include +#endif + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3) +#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3) + +#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) +#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) + +#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) + +#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) + +#define USE_RTT_ASM (0) // Use assembler version of SEGGER_RTT.c when 1 + +/********************************************************************* +* +* RTT memcpy configuration +* +* memcpy() is good for large amounts of data, +* but the overhead is big for small amounts, which are usually stored via RTT. +* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. +* +* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. +* This is may be required with memory access restrictions, +* such as on Cortex-A devices with MMU. +*/ +#define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop +// +// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets +// +//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) +// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) +//#endif + +// +// Target is not allowed to perform other RTT operations while string still has not been stored completely. +// Otherwise we would probably end up with a mixed string in the buffer. +// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. +// +// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. +// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. +// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. +// (Higher priority = lower priority number) +// Default value for embOS: 128u +// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC +// or define SEGGER_RTT_LOCK() to completely disable interrupts. +// + +#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) + +/********************************************************************* +* +* RTT lock configuration for SEGGER Embedded Studio, +* Rowley CrossStudio and GCC +*/ +#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) || (defined __clang__) + #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, primask \n\t" \ + "movs r1, $1 \n\t" \ + "msr primask, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, basepri \n\t" \ + "mov r1, %1 \n\t" \ + "msr basepri, r1 \n\t" \ + : "=r" (LockState) \ + : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + + #elif defined(__ARM_ARCH_7A__) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs r1, CPSR \n\t" \ + "mov %0, r1 \n\t" \ + "orr r1, r1, #0xC0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ + "mrs r1, CPSR \n\t" \ + "bic r1, r1, #0xC0 \n\t" \ + "and r0, r0, #0xC0 \n\t" \ + "orr r1, r1, r0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : \ + : "r" (LockState) \ + : "r0", "r1" \ + ); \ + } +#else + #define SEGGER_RTT_LOCK() + #define SEGGER_RTT_UNLOCK() + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR EWARM +*/ +#ifdef __ICCARM__ + #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_PRIMASK(); \ + __set_PRIMASK(1); + + #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ + } + #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__))) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_BASEPRI(); \ + __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); + + #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR RX +*/ +#ifdef __ICCRX__ + #define SEGGER_RTT_LOCK() { \ + unsigned long LockState; \ + LockState = __get_interrupt_state(); \ + __disable_interrupt(); + + #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ + } +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR RL78 +*/ +#ifdef __ICCRL78__ + #define SEGGER_RTT_LOCK() { \ + __istate_t LockState; \ + LockState = __get_interrupt_state(); \ + __disable_interrupt(); + + #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ + } +#endif + +/********************************************************************* +* +* RTT lock configuration for KEIL ARM +*/ +#ifdef __CC_ARM + #if (defined __TARGET_ARCH_6S_M) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char PRIMASK __asm( "primask"); \ + LockState = PRIMASK; \ + PRIMASK = 1u; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ + __schedule_barrier(); \ + } + #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char BASEPRI __asm( "basepri"); \ + LockState = BASEPRI; \ + BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ + __schedule_barrier(); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for TI ARM +*/ +#ifdef __TI_ARM__ + #if defined (__TI_ARM_V6M0__) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_PRIMASK(); \ + __set_PRIMASK(1); + + #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ + } + #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); + + #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(LockState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for CCRX +*/ +#ifdef __RX + #define SEGGER_RTT_LOCK() { \ + unsigned long LockState; \ + LockState = get_psw() & 0x010000; \ + clrpsw_i(); + + #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | LockState); \ + } +#endif + +/********************************************************************* +* +* RTT lock configuration fallback +*/ +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT_printf.c b/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT_printf.c index bb90b4c0c..75082f019 100644 --- a/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT_printf.c +++ b/third_party/jlink/SEGGER_RTT_V640/RTT/SEGGER_RTT_printf.c @@ -1,510 +1,510 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* conditions are met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* o Redistributions in binary form must reproduce the above * -* copyright notice, this list of conditions and the following * -* disclaimer in the documentation and/or other materials provided * -* with the distribution. * -* * -* o Neither the name of SEGGER Microcontroller GmbH * -* nor the names of its contributors may be used to endorse or * -* promote products derived from this software without specific * -* prior written permission. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_printf.c -Purpose : Replacement for printf to write formatted data via RTT -Revision: $Rev: 12360 $ ----------------------------------------------------------------------- -*/ -#include "SEGGER_RTT.h" -#include "SEGGER_RTT_Conf.h" - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE - #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) -#endif - -#include -#include - - -#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) -#define FORMAT_FLAG_PAD_ZERO (1u << 1) -#define FORMAT_FLAG_PRINT_SIGN (1u << 2) -#define FORMAT_FLAG_ALTERNATE (1u << 3) - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -typedef struct { - char* pBuffer; - unsigned BufferSize; - unsigned Cnt; - - int ReturnValue; - - unsigned RTTBufferIndex; -} SEGGER_RTT_PRINTF_DESC; - -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ - -/********************************************************************* -* -* Static code -* -********************************************************************** -*/ -/********************************************************************* -* -* _StoreChar -*/ -static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { - unsigned Cnt; - - Cnt = p->Cnt; - if ((Cnt + 1u) <= p->BufferSize) { - *(p->pBuffer + Cnt) = c; - p->Cnt = Cnt + 1u; - p->ReturnValue++; - } - // - // Write part of string, when the buffer is full - // - if (p->Cnt == p->BufferSize) { - if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { - p->ReturnValue = -1; - } else { - p->Cnt = 0u; - } - } -} - -/********************************************************************* -* -* _PrintUnsigned -*/ -static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { - static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - unsigned Div; - unsigned Digit; - unsigned Number; - unsigned Width; - char c; - - Number = v; - Digit = 1u; - // - // Get actual field width - // - Width = 1u; - while (Number >= Base) { - Number = (Number / Base); - Width++; - } - if (NumDigits > Width) { - Width = NumDigits; - } - // - // Print leading chars if necessary - // - if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { - if (FieldWidth != 0u) { - if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { - c = '0'; - } else { - c = ' '; - } - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, c); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - if (pBufferDesc->ReturnValue >= 0) { - // - // Compute Digit. - // Loop until Digit has the value of the highest digit required. - // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. - // - while (1) { - if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) - NumDigits--; - } else { - Div = v / Digit; - if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done - break; - } - } - Digit *= Base; - } - // - // Output digits - // - do { - Div = v / Digit; - v -= Div * Digit; - _StoreChar(pBufferDesc, _aV2C[Div]); - if (pBufferDesc->ReturnValue < 0) { - break; - } - Digit /= Base; - } while (Digit); - // - // Print trailing spaces if necessary - // - if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, ' '); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - } -} - -/********************************************************************* -* -* _PrintInt -*/ -static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { - unsigned Width; - int Number; - - Number = (v < 0) ? -v : v; - - // - // Get actual field width - // - Width = 1u; - while (Number >= (int)Base) { - Number = (Number / (int)Base); - Width++; - } - if (NumDigits > Width) { - Width = NumDigits; - } - if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { - FieldWidth--; - } - - // - // Print leading spaces if necessary - // - if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, ' '); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - // - // Print sign if necessary - // - if (pBufferDesc->ReturnValue >= 0) { - if (v < 0) { - v = -v; - _StoreChar(pBufferDesc, '-'); - } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { - _StoreChar(pBufferDesc, '+'); - } else { - - } - if (pBufferDesc->ReturnValue >= 0) { - // - // Print leading zeros if necessary - // - if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, '0'); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - if (pBufferDesc->ReturnValue >= 0) { - // - // Print number without sign - // - _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); - } - } - } -} - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ -/********************************************************************* -* -* SEGGER_RTT_vprintf -* -* Function description -* Stores a formatted string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") -* sFormat Pointer to format string -* pParamList Pointer to the list of arguments for the format string -* -* Return values -* >= 0: Number of bytes which have been stored in the "Up"-buffer. -* < 0: Error -*/ -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { - char c; - SEGGER_RTT_PRINTF_DESC BufferDesc; - int v; - unsigned NumDigits; - unsigned FormatFlags; - unsigned FieldWidth; - char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; - - BufferDesc.pBuffer = acBuffer; - BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; - BufferDesc.Cnt = 0u; - BufferDesc.RTTBufferIndex = BufferIndex; - BufferDesc.ReturnValue = 0; - - do { - c = *sFormat; - sFormat++; - if (c == 0u) { - break; - } - if (c == '%') { - // - // Filter out flags - // - FormatFlags = 0u; - v = 1; - do { - c = *sFormat; - switch (c) { - case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; - case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; - case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; - case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; - default: v = 0; break; - } - } while (v); - // - // filter out field with - // - FieldWidth = 0u; - do { - c = *sFormat; - if ((c < '0') || (c > '9')) { - break; - } - sFormat++; - FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); - } while (1); - - // - // Filter out precision (number of digits to display) - // - NumDigits = 0u; - c = *sFormat; - if (c == '.') { - sFormat++; - do { - c = *sFormat; - if ((c < '0') || (c > '9')) { - break; - } - sFormat++; - NumDigits = NumDigits * 10u + ((unsigned)c - '0'); - } while (1); - } - // - // Filter out length modifier - // - c = *sFormat; - do { - if ((c == 'l') || (c == 'h')) { - sFormat++; - c = *sFormat; - } else { - break; - } - } while (1); - // - // Handle specifiers - // - switch (c) { - case 'c': { - char c0; - v = va_arg(*pParamList, int); - c0 = (char)v; - _StoreChar(&BufferDesc, c0); - break; - } - case 'd': - v = va_arg(*pParamList, int); - _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); - break; - case 'u': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); - break; - case 'x': - case 'X': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); - break; - case 's': - { - const char * s = va_arg(*pParamList, const char *); - do { - c = *s; - s++; - if (c == '\0') { - break; - } - _StoreChar(&BufferDesc, c); - } while (BufferDesc.ReturnValue >= 0); - } - break; - case 'p': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); - break; - case '%': - _StoreChar(&BufferDesc, '%'); - break; - default: - break; - } - sFormat++; - } else { - _StoreChar(&BufferDesc, c); - } - } while (BufferDesc.ReturnValue >= 0); - - if (BufferDesc.ReturnValue > 0) { - // - // Write remaining data, if any - // - if (BufferDesc.Cnt != 0u) { - SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); - } - BufferDesc.ReturnValue += (int)BufferDesc.Cnt; - } - return BufferDesc.ReturnValue; -} - -/********************************************************************* -* -* SEGGER_RTT_printf -* -* Function description -* Stores a formatted string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") -* sFormat Pointer to format string, followed by the arguments for conversion -* -* Return values -* >= 0: Number of bytes which have been stored in the "Up"-buffer. -* < 0: Error -* -* Notes -* (1) Conversion specifications have following syntax: -* %[flags][FieldWidth][.Precision]ConversionSpecifier -* (2) Supported flags: -* -: Left justify within the field width -* +: Always print sign extension for signed conversions -* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision -* Supported conversion specifiers: -* c: Print the argument as one char -* d: Print the argument as a signed integer -* u: Print the argument as an unsigned integer -* x: Print the argument as an hexadecimal integer -* s: Print the string pointed to by the argument -* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { - int r; - va_list ParamList; - - va_start(ParamList, sFormat); - r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); - va_end(ParamList); - return r; -} -/*************************** End of file ****************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_printf.c +Purpose : Replacement for printf to write formatted data via RTT +Revision: $Rev: 12360 $ +---------------------------------------------------------------------- +*/ +#include "SEGGER_RTT.h" +#include "SEGGER_RTT_Conf.h" + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE + #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) +#endif + +#include +#include + + +#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) +#define FORMAT_FLAG_PAD_ZERO (1u << 1) +#define FORMAT_FLAG_PRINT_SIGN (1u << 2) +#define FORMAT_FLAG_ALTERNATE (1u << 3) + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +typedef struct { + char* pBuffer; + unsigned BufferSize; + unsigned Cnt; + + int ReturnValue; + + unsigned RTTBufferIndex; +} SEGGER_RTT_PRINTF_DESC; + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ + +/********************************************************************* +* +* Static code +* +********************************************************************** +*/ +/********************************************************************* +* +* _StoreChar +*/ +static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { + unsigned Cnt; + + Cnt = p->Cnt; + if ((Cnt + 1u) <= p->BufferSize) { + *(p->pBuffer + Cnt) = c; + p->Cnt = Cnt + 1u; + p->ReturnValue++; + } + // + // Write part of string, when the buffer is full + // + if (p->Cnt == p->BufferSize) { + if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { + p->ReturnValue = -1; + } else { + p->Cnt = 0u; + } + } +} + +/********************************************************************* +* +* _PrintUnsigned +*/ +static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + unsigned Div; + unsigned Digit; + unsigned Number; + unsigned Width; + char c; + + Number = v; + Digit = 1u; + // + // Get actual field width + // + Width = 1u; + while (Number >= Base) { + Number = (Number / Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + // + // Print leading chars if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { + if (FieldWidth != 0u) { + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { + c = '0'; + } else { + c = ' '; + } + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, c); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Compute Digit. + // Loop until Digit has the value of the highest digit required. + // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. + // + while (1) { + if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) + NumDigits--; + } else { + Div = v / Digit; + if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done + break; + } + } + Digit *= Base; + } + // + // Output digits + // + do { + Div = v / Digit; + v -= Div * Digit; + _StoreChar(pBufferDesc, _aV2C[Div]); + if (pBufferDesc->ReturnValue < 0) { + break; + } + Digit /= Base; + } while (Digit); + // + // Print trailing spaces if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + } +} + +/********************************************************************* +* +* _PrintInt +*/ +static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + unsigned Width; + int Number; + + Number = (v < 0) ? -v : v; + + // + // Get actual field width + // + Width = 1u; + while (Number >= (int)Base) { + Number = (Number / (int)Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { + FieldWidth--; + } + + // + // Print leading spaces if necessary + // + if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + // + // Print sign if necessary + // + if (pBufferDesc->ReturnValue >= 0) { + if (v < 0) { + v = -v; + _StoreChar(pBufferDesc, '-'); + } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { + _StoreChar(pBufferDesc, '+'); + } else { + + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print leading zeros if necessary + // + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, '0'); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print number without sign + // + _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); + } + } + } +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_vprintf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string +* pParamList Pointer to the list of arguments for the format string +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { + char c; + SEGGER_RTT_PRINTF_DESC BufferDesc; + int v; + unsigned NumDigits; + unsigned FormatFlags; + unsigned FieldWidth; + char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; + + BufferDesc.pBuffer = acBuffer; + BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; + BufferDesc.Cnt = 0u; + BufferDesc.RTTBufferIndex = BufferIndex; + BufferDesc.ReturnValue = 0; + + do { + c = *sFormat; + sFormat++; + if (c == 0u) { + break; + } + if (c == '%') { + // + // Filter out flags + // + FormatFlags = 0u; + v = 1; + do { + c = *sFormat; + switch (c) { + case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; + case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; + case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; + case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; + default: v = 0; break; + } + } while (v); + // + // filter out field with + // + FieldWidth = 0u; + do { + c = *sFormat; + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); + } while (1); + + // + // Filter out precision (number of digits to display) + // + NumDigits = 0u; + c = *sFormat; + if (c == '.') { + sFormat++; + do { + c = *sFormat; + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + NumDigits = NumDigits * 10u + ((unsigned)c - '0'); + } while (1); + } + // + // Filter out length modifier + // + c = *sFormat; + do { + if ((c == 'l') || (c == 'h')) { + sFormat++; + c = *sFormat; + } else { + break; + } + } while (1); + // + // Handle specifiers + // + switch (c) { + case 'c': { + char c0; + v = va_arg(*pParamList, int); + c0 = (char)v; + _StoreChar(&BufferDesc, c0); + break; + } + case 'd': + v = va_arg(*pParamList, int); + _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'u': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'x': + case 'X': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); + break; + case 's': + { + const char * s = va_arg(*pParamList, const char *); + do { + c = *s; + s++; + if (c == '\0') { + break; + } + _StoreChar(&BufferDesc, c); + } while (BufferDesc.ReturnValue >= 0); + } + break; + case 'p': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); + break; + case '%': + _StoreChar(&BufferDesc, '%'); + break; + default: + break; + } + sFormat++; + } else { + _StoreChar(&BufferDesc, c); + } + } while (BufferDesc.ReturnValue >= 0); + + if (BufferDesc.ReturnValue > 0) { + // + // Write remaining data, if any + // + if (BufferDesc.Cnt != 0u) { + SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); + } + BufferDesc.ReturnValue += (int)BufferDesc.Cnt; + } + return BufferDesc.ReturnValue; +} + +/********************************************************************* +* +* SEGGER_RTT_printf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string, followed by the arguments for conversion +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +* +* Notes +* (1) Conversion specifications have following syntax: +* %[flags][FieldWidth][.Precision]ConversionSpecifier +* (2) Supported flags: +* -: Left justify within the field width +* +: Always print sign extension for signed conversions +* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision +* Supported conversion specifiers: +* c: Print the argument as one char +* d: Print the argument as a signed integer +* u: Print the argument as an unsigned integer +* x: Print the argument as an hexadecimal integer +* s: Print the string pointed to by the argument +* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { + int r; + va_list ParamList; + + va_start(ParamList, sFormat); + r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); + va_end(ParamList); + return r; +} +/*************************** End of file ****************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_GCC.c b/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_GCC.c index 51de2b113..b0b6ca36f 100644 --- a/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_GCC.c +++ b/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_GCC.c @@ -1,130 +1,130 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* conditions are met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* o Redistributions in binary form must reproduce the above * -* copyright notice, this list of conditions and the following * -* disclaimer in the documentation and/or other materials provided * -* with the distribution. * -* * -* o Neither the name of SEGGER Microcontroller GmbH * -* nor the names of its contributors may be used to endorse or * -* promote products derived from this software without specific * -* prior written permission. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Syscalls_GCC.c -Purpose : Low-level functions for using printf() via RTT in GCC. - To use RTT for printf output, include this file in your - application. -Revision: $Rev: 9599 $ ----------------------------------------------------------------------- -*/ -#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) - -#include // required for _write_r -#include "SEGGER_RTT.h" - - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ -// -// If necessary define the _reent struct -// to match the one passed by the used standard library. -// -struct _reent; - -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ -int _write(int file, char *ptr, int len); -int _write_r(struct _reent *r, int file, const void *ptr, int len); - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ - -/********************************************************************* -* -* _write() -* -* Function description -* Low-level write function. -* libc subroutines will use this system routine for output to all files, -* including stdout. -* Write data via RTT. -*/ -int _write(int file, char *ptr, int len) { - (void) file; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, ptr, len); - return len; -} - -/********************************************************************* -* -* _write_r() -* -* Function description -* Low-level reentrant write function. -* libc subroutines will use this system routine for output to all files, -* including stdout. -* Write data via RTT. -*/ -int _write_r(struct _reent *r, int file, const void *ptr, int len) { - (void) file; /* Not used, avoid warning */ - (void) r; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, ptr, len); - return len; -} - -#endif -/****** End Of File *************************************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Syscalls_GCC.c +Purpose : Low-level functions for using printf() via RTT in GCC. + To use RTT for printf output, include this file in your + application. +Revision: $Rev: 9599 $ +---------------------------------------------------------------------- +*/ +#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) + +#include // required for _write_r +#include "SEGGER_RTT.h" + + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ +// +// If necessary define the _reent struct +// to match the one passed by the used standard library. +// +struct _reent; + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int _write(int file, char *ptr, int len); +int _write_r(struct _reent *r, int file, const void *ptr, int len); + +/********************************************************************* +* +* Global functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _write() +* +* Function description +* Low-level write function. +* libc subroutines will use this system routine for output to all files, +* including stdout. +* Write data via RTT. +*/ +int _write(int file, char *ptr, int len) { + (void) file; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, ptr, len); + return len; +} + +/********************************************************************* +* +* _write_r() +* +* Function description +* Low-level reentrant write function. +* libc subroutines will use this system routine for output to all files, +* including stdout. +* Write data via RTT. +*/ +int _write_r(struct _reent *r, int file, const void *ptr, int len) { + (void) file; /* Not used, avoid warning */ + (void) r; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, ptr, len); + return len; +} + +#endif +/****** End Of File *************************************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_IAR.c b/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_IAR.c index f5372e0fe..f8baf6909 100644 --- a/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_IAR.c +++ b/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_IAR.c @@ -1,124 +1,124 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* conditions are met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* o Redistributions in binary form must reproduce the above * -* copyright notice, this list of conditions and the following * -* disclaimer in the documentation and/or other materials provided * -* with the distribution. * -* * -* o Neither the name of SEGGER Microcontroller GmbH * -* nor the names of its contributors may be used to endorse or * -* promote products derived from this software without specific * -* prior written permission. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Syscalls_IAR.c -Purpose : Low-level functions for using printf() via RTT in IAR. - To use RTT for printf output, include this file in your - application and set the Library Configuration to Normal. -Revision: $Rev: 12303 $ ----------------------------------------------------------------------- -*/ -#ifdef __IAR_SYSTEMS_ICC__ - -// -// Since IAR EWARM V8 yfuns.h is considered as deprecated and LowLevelIOInterface.h shall be used instead -// To not break any compatibility with older compiler versions, we have a version check in here -// -#if __VER__ >= 8000000 - #include -#else - #include -#endif - -#include "SEGGER_RTT.h" -#pragma module_name = "?__write" - -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ -size_t __write(int handle, const unsigned char * buffer, size_t size); - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ -/********************************************************************* -* -* __write() -* -* Function description -* Low-level write function. -* Standard library subroutines will use this system routine -* for output to all files, including stdout. -* Write data via RTT. -*/ -size_t __write(int handle, const unsigned char * buffer, size_t size) { - (void) handle; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, (const char*)buffer, size); - return size; -} - -/********************************************************************* -* -* __write_buffered() -* -* Function description -* Low-level write function. -* Standard library subroutines will use this system routine -* for output to all files, including stdout. -* Write data via RTT. -*/ -size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) { - (void) handle; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, (const char*)buffer, size); - return size; -} - -#endif -/****** End Of File *************************************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Syscalls_IAR.c +Purpose : Low-level functions for using printf() via RTT in IAR. + To use RTT for printf output, include this file in your + application and set the Library Configuration to Normal. +Revision: $Rev: 12303 $ +---------------------------------------------------------------------- +*/ +#ifdef __IAR_SYSTEMS_ICC__ + +// +// Since IAR EWARM V8 yfuns.h is considered as deprecated and LowLevelIOInterface.h shall be used instead +// To not break any compatibility with older compiler versions, we have a version check in here +// +#if __VER__ >= 8000000 + #include +#else + #include +#endif + +#include "SEGGER_RTT.h" +#pragma module_name = "?__write" + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +size_t __write(int handle, const unsigned char * buffer, size_t size); + +/********************************************************************* +* +* Global functions +* +********************************************************************** +*/ +/********************************************************************* +* +* __write() +* +* Function description +* Low-level write function. +* Standard library subroutines will use this system routine +* for output to all files, including stdout. +* Write data via RTT. +*/ +size_t __write(int handle, const unsigned char * buffer, size_t size) { + (void) handle; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, (const char*)buffer, size); + return size; +} + +/********************************************************************* +* +* __write_buffered() +* +* Function description +* Low-level write function. +* Standard library subroutines will use this system routine +* for output to all files, including stdout. +* Write data via RTT. +*/ +size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) { + (void) handle; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, (const char*)buffer, size); + return size; +} + +#endif +/****** End Of File *************************************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_KEIL.c b/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_KEIL.c index 2502cf54a..50d38c1a1 100644 --- a/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_KEIL.c +++ b/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_KEIL.c @@ -1,374 +1,374 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* conditions are met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* o Redistributions in binary form must reproduce the above * -* copyright notice, this list of conditions and the following * -* disclaimer in the documentation and/or other materials provided * -* with the distribution. * -* * -* o Neither the name of SEGGER Microcontroller GmbH * -* nor the names of its contributors may be used to endorse or * -* promote products derived from this software without specific * -* prior written permission. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : RTT_Syscalls_KEIL.c -Purpose : Retargeting module for KEIL MDK-CM3. - Low-level functions for using printf() via RTT -Revision: $Rev: 9599 $ ----------------------------------------------------------------------- -*/ -#ifdef __CC_ARM - -#include -#include -#include -#include -#include - -#include "SEGGER_RTT.h" -/********************************************************************* -* -* #pragmas -* -********************************************************************** -*/ -#pragma import(__use_no_semihosting) - -#ifdef _MICROLIB - #pragma import(__use_full_stdio) -#endif - -/********************************************************************* -* -* Defines non-configurable -* -********************************************************************** -*/ - -/* Standard IO device handles - arbitrary, but any real file system handles must be - less than 0x8000. */ -#define STDIN 0x8001 // Standard Input Stream -#define STDOUT 0x8002 // Standard Output Stream -#define STDERR 0x8003 // Standard Error Stream - -/********************************************************************* -* -* Public const -* -********************************************************************** -*/ -//const char __stdin_name[] = "STDIN"; -const char __stdout_name[] = "STDOUT"; -const char __stderr_name[] = "STDERR"; - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ - -/********************************************************************* -* -* _ttywrch -* -* Function description: -* Outputs a character to the console -* -* Parameters: -* c - character to output -* -*/ -void _ttywrch(int c) { - fputc(c, stdout); // stdout - fflush(stdout); -} - -/********************************************************************* -* -* _sys_open -* -* Function description: -* Opens the device/file in order to do read/write operations -* -* Parameters: -* sName - sName of the device/file to open -* OpenMode - This parameter is currently ignored -* -* Return value: -* != 0 - Handle to the object to open, otherwise -* == 0 -"device" is not handled by this module -* -*/ -FILEHANDLE _sys_open(const char * sName, int OpenMode) { - (void)OpenMode; - // Register standard Input Output devices. - if (strcmp(sName, __stdout_name) == 0) { - return (STDOUT); - } else if (strcmp(sName, __stderr_name) == 0) { - return (STDERR); - } else - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_close -* -* Function description: -* Closes the handle to the open device/file -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* 0 - device/file closed -* -*/ -int _sys_close(FILEHANDLE hFile) { - (void)hFile; - return 0; // Not implemented -} - -/********************************************************************* -* -* _sys_write -* -* Function description: -* Writes the data to an open handle. -* Currently this function only outputs data to the console -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* pBuffer - Pointer to the data that shall be written -* NumBytes - Number of bytes to write -* Mode - The Mode that shall be used -* -* Return value: -* Number of bytes *not* written to the file/device -* -*/ -int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) { - int r = 0; - - (void)Mode; - if (hFile == STDOUT) { - return NumBytes - SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes); - } - return r; -} - -/********************************************************************* -* -* _sys_read -* -* Function description: -* Reads data from an open handle. -* Currently this modules does nothing. -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* pBuffer - Pointer to buffer to store the read data -* NumBytes - Number of bytes to read -* Mode - The Mode that shall be used -* -* Return value: -* Number of bytes read from the file/device -* -*/ -int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) { - (void)hFile; - (void)pBuffer; - (void)NumBytes; - (void)Mode; - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_istty -* -* Function description: -* This function shall return whether the opened file -* is a console device or not. -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* 1 - Device is a console -* 0 - Device is not a console -* -*/ -int _sys_istty(FILEHANDLE hFile) { - if (hFile > 0x8000) { - return (1); - } - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_seek -* -* Function description: -* Seeks via the file to a specific position -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* Pos - -* -* Return value: -* int - -* -*/ -int _sys_seek(FILEHANDLE hFile, long Pos) { - (void)hFile; - (void)Pos; - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_ensure -* -* Function description: -* -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* int - -* -*/ -int _sys_ensure(FILEHANDLE hFile) { - (void)hFile; - return (-1); // Not implemented -} - -/********************************************************************* -* -* _sys_flen -* -* Function description: -* Returns the length of the opened file handle -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* Length of the file -* -*/ -long _sys_flen(FILEHANDLE hFile) { - (void)hFile; - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_tmpnam -* -* Function description: -* This function converts the file number fileno for a temporary -* file to a unique filename, for example, tmp0001. -* -* Parameters: -* pBuffer - Pointer to a buffer to store the name -* FileNum - file number to convert -* MaxLen - Size of the buffer -* -* Return value: -* 1 - Error -* 0 - Success -* -*/ -int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) { - (void)pBuffer; - (void)FileNum; - (void)MaxLen; - return (1); // Not implemented -} - -/********************************************************************* -* -* _sys_command_string -* -* Function description: -* This function shall execute a system command. -* -* Parameters: -* cmd - Pointer to the command string -* len - Length of the string -* -* Return value: -* == NULL - Command was not successfully executed -* == sCmd - Command was passed successfully -* -*/ -char * _sys_command_string(char * cmd, int len) { - (void)len; - return cmd; // Not implemented -} - -/********************************************************************* -* -* _sys_exit -* -* Function description: -* This function is called when the application returns from main -* -* Parameters: -* ReturnCode - Return code from the main function -* -* -*/ -void _sys_exit(int ReturnCode) { - (void)ReturnCode; - while (1); // Not implemented -} - -#endif -/*************************** End of file ****************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : RTT_Syscalls_KEIL.c +Purpose : Retargeting module for KEIL MDK-CM3. + Low-level functions for using printf() via RTT +Revision: $Rev: 9599 $ +---------------------------------------------------------------------- +*/ +#ifdef __CC_ARM + +#include +#include +#include +#include +#include + +#include "SEGGER_RTT.h" +/********************************************************************* +* +* #pragmas +* +********************************************************************** +*/ +#pragma import(__use_no_semihosting) + +#ifdef _MICROLIB + #pragma import(__use_full_stdio) +#endif + +/********************************************************************* +* +* Defines non-configurable +* +********************************************************************** +*/ + +/* Standard IO device handles - arbitrary, but any real file system handles must be + less than 0x8000. */ +#define STDIN 0x8001 // Standard Input Stream +#define STDOUT 0x8002 // Standard Output Stream +#define STDERR 0x8003 // Standard Error Stream + +/********************************************************************* +* +* Public const +* +********************************************************************** +*/ +//const char __stdin_name[] = "STDIN"; +const char __stdout_name[] = "STDOUT"; +const char __stderr_name[] = "STDERR"; + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ + +/********************************************************************* +* +* _ttywrch +* +* Function description: +* Outputs a character to the console +* +* Parameters: +* c - character to output +* +*/ +void _ttywrch(int c) { + fputc(c, stdout); // stdout + fflush(stdout); +} + +/********************************************************************* +* +* _sys_open +* +* Function description: +* Opens the device/file in order to do read/write operations +* +* Parameters: +* sName - sName of the device/file to open +* OpenMode - This parameter is currently ignored +* +* Return value: +* != 0 - Handle to the object to open, otherwise +* == 0 -"device" is not handled by this module +* +*/ +FILEHANDLE _sys_open(const char * sName, int OpenMode) { + (void)OpenMode; + // Register standard Input Output devices. + if (strcmp(sName, __stdout_name) == 0) { + return (STDOUT); + } else if (strcmp(sName, __stderr_name) == 0) { + return (STDERR); + } else + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_close +* +* Function description: +* Closes the handle to the open device/file +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* 0 - device/file closed +* +*/ +int _sys_close(FILEHANDLE hFile) { + (void)hFile; + return 0; // Not implemented +} + +/********************************************************************* +* +* _sys_write +* +* Function description: +* Writes the data to an open handle. +* Currently this function only outputs data to the console +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* pBuffer - Pointer to the data that shall be written +* NumBytes - Number of bytes to write +* Mode - The Mode that shall be used +* +* Return value: +* Number of bytes *not* written to the file/device +* +*/ +int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) { + int r = 0; + + (void)Mode; + if (hFile == STDOUT) { + return NumBytes - SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes); + } + return r; +} + +/********************************************************************* +* +* _sys_read +* +* Function description: +* Reads data from an open handle. +* Currently this modules does nothing. +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* pBuffer - Pointer to buffer to store the read data +* NumBytes - Number of bytes to read +* Mode - The Mode that shall be used +* +* Return value: +* Number of bytes read from the file/device +* +*/ +int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) { + (void)hFile; + (void)pBuffer; + (void)NumBytes; + (void)Mode; + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_istty +* +* Function description: +* This function shall return whether the opened file +* is a console device or not. +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* 1 - Device is a console +* 0 - Device is not a console +* +*/ +int _sys_istty(FILEHANDLE hFile) { + if (hFile > 0x8000) { + return (1); + } + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_seek +* +* Function description: +* Seeks via the file to a specific position +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* Pos - +* +* Return value: +* int - +* +*/ +int _sys_seek(FILEHANDLE hFile, long Pos) { + (void)hFile; + (void)Pos; + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_ensure +* +* Function description: +* +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* int - +* +*/ +int _sys_ensure(FILEHANDLE hFile) { + (void)hFile; + return (-1); // Not implemented +} + +/********************************************************************* +* +* _sys_flen +* +* Function description: +* Returns the length of the opened file handle +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* Length of the file +* +*/ +long _sys_flen(FILEHANDLE hFile) { + (void)hFile; + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_tmpnam +* +* Function description: +* This function converts the file number fileno for a temporary +* file to a unique filename, for example, tmp0001. +* +* Parameters: +* pBuffer - Pointer to a buffer to store the name +* FileNum - file number to convert +* MaxLen - Size of the buffer +* +* Return value: +* 1 - Error +* 0 - Success +* +*/ +int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) { + (void)pBuffer; + (void)FileNum; + (void)MaxLen; + return (1); // Not implemented +} + +/********************************************************************* +* +* _sys_command_string +* +* Function description: +* This function shall execute a system command. +* +* Parameters: +* cmd - Pointer to the command string +* len - Length of the string +* +* Return value: +* == NULL - Command was not successfully executed +* == sCmd - Command was passed successfully +* +*/ +char * _sys_command_string(char * cmd, int len) { + (void)len; + return cmd; // Not implemented +} + +/********************************************************************* +* +* _sys_exit +* +* Function description: +* This function is called when the application returns from main +* +* Parameters: +* ReturnCode - Return code from the main function +* +* +*/ +void _sys_exit(int ReturnCode) { + (void)ReturnCode; + while (1); // Not implemented +} + +#endif +/*************************** End of file ****************************/ diff --git a/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_SES.c b/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_SES.c index 452f2d2ef..48609e48c 100644 --- a/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_SES.c +++ b/third_party/jlink/SEGGER_RTT_V640/Syscalls/SEGGER_RTT_Syscalls_SES.c @@ -1,257 +1,257 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2018 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* conditions are met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* o Redistributions in binary form must reproduce the above * -* copyright notice, this list of conditions and the following * -* disclaimer in the documentation and/or other materials provided * -* with the distribution. * -* * -* o Neither the name of SEGGER Microcontroller GmbH * -* nor the names of its contributors may be used to endorse or * -* promote products derived from this software without specific * -* prior written permission. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Syscalls_SES.c -Purpose : Reimplementation of printf, puts and __getchar using RTT - in SEGGER Embedded Studio. - To use RTT for printf output, include this file in your - application. -Revision: $Rev: 12804 $ ----------------------------------------------------------------------- -*/ -#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) - -#include "SEGGER_RTT.h" -#include -#include -#include "limits.h" -#include "__libc.h" -#include "__vfprintf.h" - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ -// -// Select string formatting implementation. -// -// RTT printf formatting -// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h) -// - No maximum string length. -// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c) -// Standard library printf formatting -// - Configurable formatting capabilities. -// - Full conversion specifier and flag support. -// - Maximum string length has to be known or (slightly) slower character-wise output. -// -// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting -// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting -// -#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING - #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 -#endif -// -// If using standard library formatting, -// select maximum output string buffer size or character-wise output. -// -// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output -// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length -// -#ifndef PRINTF_BUFFER_SIZE - #define PRINTF_BUFFER_SIZE 128 -#endif - -#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); - -/********************************************************************* -* -* Global functions, printf -* -********************************************************************** -*/ -/********************************************************************* -* -* printf() -* -* Function description -* print a formatted string using RTT and SEGGER RTT formatting. -*/ -int printf(const char *fmt,...) { - int n; - va_list args; - - va_start (args, fmt); - n = SEGGER_RTT_vprintf(0, fmt, &args); - va_end(args); - return n; -} - -#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output - -/********************************************************************* -* -* Static functions -* -********************************************************************** -*/ -static int _putchar(int x, __printf_tag_ptr ctx) { - (void)ctx; - SEGGER_RTT_Write(0, (char *)&x, 1); - return x; -} - -/********************************************************************* -* -* Global functions, printf -* -********************************************************************** -*/ -/********************************************************************* -* -* printf() -* -* Function description -* print a formatted string character-wise, using RTT and standard -* library formatting. -*/ -int printf(const char *fmt, ...) { - int n; - va_list args; - __printf_t iod; - - va_start(args, fmt); - iod.string = 0; - iod.maxchars = INT_MAX; - iod.output_fn = _putchar; - SEGGER_RTT_LOCK(); - n = __vfprintf(&iod, fmt, args); - SEGGER_RTT_UNLOCK(); - va_end(args); - return n; -} - -#else // Use standard library formatting with static buffer - -/********************************************************************* -* -* Global functions, printf -* -********************************************************************** -*/ -/********************************************************************* -* -* printf() -* -* Function description -* print a formatted string using RTT and standard library formatting. -*/ -int printf(const char *fmt,...) { - int n; - char aBuffer[PRINTF_BUFFER_SIZE]; - va_list args; - - va_start (args, fmt); - n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args); - if (n > (int)sizeof(aBuffer)) { - SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer)); - } else if (n > 0) { - SEGGER_RTT_Write(0, aBuffer, n); - } - va_end(args); - return n; -} -#endif - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ -/********************************************************************* -* -* puts() -* -* Function description -* print a string using RTT. -*/ -int puts(const char *s) { - return SEGGER_RTT_WriteString(0, s); -} - -/********************************************************************* -* -* __putchar() -* -* Function description -* Write one character via RTT. -*/ -int __putchar(int x, __printf_tag_ptr ctx) { - (void)ctx; - SEGGER_RTT_Write(0, (char *)&x, 1); - return x; -} - -/********************************************************************* -* -* __getchar() -* -* Function description -* Wait for and get a character via RTT. -*/ -int __getchar() { - return SEGGER_RTT_WaitKey(); -} - -#endif -/****** End Of File *************************************************/ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2018 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Syscalls_SES.c +Purpose : Reimplementation of printf, puts and __getchar using RTT + in SEGGER Embedded Studio. + To use RTT for printf output, include this file in your + application. +Revision: $Rev: 12804 $ +---------------------------------------------------------------------- +*/ +#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) + +#include "SEGGER_RTT.h" +#include +#include +#include "limits.h" +#include "__libc.h" +#include "__vfprintf.h" + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ +// +// Select string formatting implementation. +// +// RTT printf formatting +// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h) +// - No maximum string length. +// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c) +// Standard library printf formatting +// - Configurable formatting capabilities. +// - Full conversion specifier and flag support. +// - Maximum string length has to be known or (slightly) slower character-wise output. +// +// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting +// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting +// +#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING + #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 +#endif +// +// If using standard library formatting, +// select maximum output string buffer size or character-wise output. +// +// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output +// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length +// +#ifndef PRINTF_BUFFER_SIZE + #define PRINTF_BUFFER_SIZE 128 +#endif + +#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +/********************************************************************* +* +* Global functions, printf +* +********************************************************************** +*/ +/********************************************************************* +* +* printf() +* +* Function description +* print a formatted string using RTT and SEGGER RTT formatting. +*/ +int printf(const char *fmt,...) { + int n; + va_list args; + + va_start (args, fmt); + n = SEGGER_RTT_vprintf(0, fmt, &args); + va_end(args); + return n; +} + +#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ +static int _putchar(int x, __printf_tag_ptr ctx) { + (void)ctx; + SEGGER_RTT_Write(0, (char *)&x, 1); + return x; +} + +/********************************************************************* +* +* Global functions, printf +* +********************************************************************** +*/ +/********************************************************************* +* +* printf() +* +* Function description +* print a formatted string character-wise, using RTT and standard +* library formatting. +*/ +int printf(const char *fmt, ...) { + int n; + va_list args; + __printf_t iod; + + va_start(args, fmt); + iod.string = 0; + iod.maxchars = INT_MAX; + iod.output_fn = _putchar; + SEGGER_RTT_LOCK(); + n = __vfprintf(&iod, fmt, args); + SEGGER_RTT_UNLOCK(); + va_end(args); + return n; +} + +#else // Use standard library formatting with static buffer + +/********************************************************************* +* +* Global functions, printf +* +********************************************************************** +*/ +/********************************************************************* +* +* printf() +* +* Function description +* print a formatted string using RTT and standard library formatting. +*/ +int printf(const char *fmt,...) { + int n; + char aBuffer[PRINTF_BUFFER_SIZE]; + va_list args; + + va_start (args, fmt); + n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args); + if (n > (int)sizeof(aBuffer)) { + SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer)); + } else if (n > 0) { + SEGGER_RTT_Write(0, aBuffer, n); + } + va_end(args); + return n; +} +#endif + +/********************************************************************* +* +* Global functions +* +********************************************************************** +*/ +/********************************************************************* +* +* puts() +* +* Function description +* print a string using RTT. +*/ +int puts(const char *s) { + return SEGGER_RTT_WriteString(0, s); +} + +/********************************************************************* +* +* __putchar() +* +* Function description +* Write one character via RTT. +*/ +int __putchar(int x, __printf_tag_ptr ctx) { + (void)ctx; + SEGGER_RTT_Write(0, (char *)&x, 1); + return x; +} + +/********************************************************************* +* +* __getchar() +* +* Function description +* Wait for and get a character via RTT. +*/ +int __getchar() { + return SEGGER_RTT_WaitKey(); +} + +#endif +/****** End Of File *************************************************/