Initial commit of firmware

This commit is contained in:
2025-04-12 13:30:57 +01:00
commit 264a3462e0
374 changed files with 332649 additions and 0 deletions

View File

@@ -0,0 +1,283 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler generic header file
* @version V5.1.0
* @date 09. October 2018
******************************************************************************/
/*
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* Arm Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* Arm Compiler 6.6 LTM (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100)
#include "cmsis_armclang_ltm.h"
/*
* Arm Compiler above 6.10.1 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
#include "cmsis_armclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#include <cmsis_iccarm.h>
/*
* TI Arm Compiler
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed))
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
/*
* 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.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION @packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,352 @@
/******************************************************************************
* @file mpu_armv8.h
* @brief CMSIS MPU API for Armv8-M and Armv8.1-M MPU
* @version V5.1.3
* @date 03. February 2021
******************************************************************************/
/*
* Copyright (c) 2017-2021 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef ARM_MPU_ARMV8_H
#define ARM_MPU_ARMV8_H
/** \brief Attribute for device memory (outer only) */
#define ARM_MPU_ATTR_DEVICE ( 0U )
/** \brief Attribute for non-cacheable, normal memory */
#define ARM_MPU_ATTR_NON_CACHEABLE ( 4U )
/** \brief Attribute for normal memory (outer and inner)
* \param NT Non-Transient: Set to 1 for non-transient data.
* \param WB Write-Back: Set to 1 to use write-back update policy.
* \param RA Read Allocation: Set to 1 to use cache allocation on read miss.
* \param WA Write Allocation: Set to 1 to use cache allocation on write miss.
*/
#define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA) \
((((NT) & 1U) << 3U) | (((WB) & 1U) << 2U) | (((RA) & 1U) << 1U) | ((WA) & 1U))
/** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */
#define ARM_MPU_ATTR_DEVICE_nGnRnE (0U)
/** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */
#define ARM_MPU_ATTR_DEVICE_nGnRE (1U)
/** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */
#define ARM_MPU_ATTR_DEVICE_nGRE (2U)
/** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */
#define ARM_MPU_ATTR_DEVICE_GRE (3U)
/** \brief Memory Attribute
* \param O Outer memory attributes
* \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes
*/
#define ARM_MPU_ATTR(O, I) ((((O) & 0xFU) << 4U) | ((((O) & 0xFU) != 0U) ? ((I) & 0xFU) : (((I) & 0x3U) << 2U)))
/** \brief Normal memory non-shareable */
#define ARM_MPU_SH_NON (0U)
/** \brief Normal memory outer shareable */
#define ARM_MPU_SH_OUTER (2U)
/** \brief Normal memory inner shareable */
#define ARM_MPU_SH_INNER (3U)
/** \brief Memory access permissions
* \param RO Read-Only: Set to 1 for read-only memory.
* \param NP Non-Privileged: Set to 1 for non-privileged memory.
*/
#define ARM_MPU_AP_(RO, NP) ((((RO) & 1U) << 1U) | ((NP) & 1U))
/** \brief Region Base Address Register value
* \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned.
* \param SH Defines the Shareability domain for this memory region.
* \param RO Read-Only: Set to 1 for a read-only memory region.
* \param NP Non-Privileged: Set to 1 for a non-privileged memory region.
* \oaram XN eXecute Never: Set to 1 for a non-executable memory region.
*/
#define ARM_MPU_RBAR(BASE, SH, RO, NP, XN) \
(((BASE) & MPU_RBAR_BASE_Msk) | \
(((SH) << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk) | \
((ARM_MPU_AP_(RO, NP) << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk) | \
(((XN) << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk))
/** \brief Region Limit Address Register value
* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended.
* \param IDX The attribute index to be associated with this memory region.
*/
#define ARM_MPU_RLAR(LIMIT, IDX) \
(((LIMIT) & MPU_RLAR_LIMIT_Msk) | \
(((IDX) << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \
(MPU_RLAR_EN_Msk))
#if defined(MPU_RLAR_PXN_Pos)
/** \brief Region Limit Address Register with PXN value
* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended.
* \param PXN Privileged execute never. Defines whether code can be executed from this privileged region.
* \param IDX The attribute index to be associated with this memory region.
*/
#define ARM_MPU_RLAR_PXN(LIMIT, PXN, IDX) \
(((LIMIT) & MPU_RLAR_LIMIT_Msk) | \
(((PXN) << MPU_RLAR_PXN_Pos) & MPU_RLAR_PXN_Msk) | \
(((IDX) << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \
(MPU_RLAR_EN_Msk))
#endif
/**
* Struct for a single MPU Region
*/
typedef struct {
uint32_t RBAR; /*!< Region Base Address Register value */
uint32_t RLAR; /*!< Region Limit Address Register value */
} ARM_MPU_Region_t;
/** Enable the MPU.
* \param MPU_Control Default access permissions for unconfigured regions.
*/
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
{
__DMB();
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
#endif
__DSB();
__ISB();
}
/** Disable the MPU.
*/
__STATIC_INLINE void ARM_MPU_Disable(void)
{
__DMB();
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
#endif
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
__DSB();
__ISB();
}
#ifdef MPU_NS
/** Enable the Non-secure MPU.
* \param MPU_Control Default access permissions for unconfigured regions.
*/
__STATIC_INLINE void ARM_MPU_Enable_NS(uint32_t MPU_Control)
{
__DMB();
MPU_NS->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
#endif
__DSB();
__ISB();
}
/** Disable the Non-secure MPU.
*/
__STATIC_INLINE void ARM_MPU_Disable_NS(void)
{
__DMB();
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
#endif
MPU_NS->CTRL &= ~MPU_CTRL_ENABLE_Msk;
__DSB();
__ISB();
}
#endif
/** Set the memory attribute encoding to the given MPU.
* \param mpu Pointer to the MPU to be configured.
* \param idx The attribute index to be set [0-7]
* \param attr The attribute value to be set.
*/
__STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr)
{
const uint8_t reg = idx / 4U;
const uint32_t pos = ((idx % 4U) * 8U);
const uint32_t mask = 0xFFU << pos;
if (reg >= (sizeof(mpu->MAIR) / sizeof(mpu->MAIR[0]))) {
return; // invalid index
}
mpu->MAIR[reg] = ((mpu->MAIR[reg] & ~mask) | ((attr << pos) & mask));
}
/** Set the memory attribute encoding.
* \param idx The attribute index to be set [0-7]
* \param attr The attribute value to be set.
*/
__STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr)
{
ARM_MPU_SetMemAttrEx(MPU, idx, attr);
}
#ifdef MPU_NS
/** Set the memory attribute encoding to the Non-secure MPU.
* \param idx The attribute index to be set [0-7]
* \param attr The attribute value to be set.
*/
__STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr)
{
ARM_MPU_SetMemAttrEx(MPU_NS, idx, attr);
}
#endif
/** Clear and disable the given MPU region of the given MPU.
* \param mpu Pointer to MPU to be used.
* \param rnr Region number to be cleared.
*/
__STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr)
{
mpu->RNR = rnr;
mpu->RLAR = 0U;
}
/** Clear and disable the given MPU region.
* \param rnr Region number to be cleared.
*/
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
{
ARM_MPU_ClrRegionEx(MPU, rnr);
}
#ifdef MPU_NS
/** Clear and disable the given Non-secure MPU region.
* \param rnr Region number to be cleared.
*/
__STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr)
{
ARM_MPU_ClrRegionEx(MPU_NS, rnr);
}
#endif
/** Configure the given MPU region of the given MPU.
* \param mpu Pointer to MPU to be used.
* \param rnr Region number to be configured.
* \param rbar Value for RBAR register.
* \param rlar Value for RLAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar)
{
mpu->RNR = rnr;
mpu->RBAR = rbar;
mpu->RLAR = rlar;
}
/** Configure the given MPU region.
* \param rnr Region number to be configured.
* \param rbar Value for RBAR register.
* \param rlar Value for RLAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar)
{
ARM_MPU_SetRegionEx(MPU, rnr, rbar, rlar);
}
#ifdef MPU_NS
/** Configure the given Non-secure MPU region.
* \param rnr Region number to be configured.
* \param rbar Value for RBAR register.
* \param rlar Value for RLAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar)
{
ARM_MPU_SetRegionEx(MPU_NS, rnr, rbar, rlar);
}
#endif
/** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_LoadEx()
* \param dst Destination data is copied to.
* \param src Source data is copied from.
* \param len Amount of data words to be copied.
*/
__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
{
uint32_t i;
for (i = 0U; i < len; ++i)
{
dst[i] = src[i];
}
}
/** Load the given number of MPU regions from a table to the given MPU.
* \param mpu Pointer to the MPU registers to be used.
* \param rnr First region number to be configured.
* \param table Pointer to the MPU configuration table.
* \param cnt Amount of regions to be configured.
*/
__STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
{
const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
if (cnt == 1U) {
mpu->RNR = rnr;
ARM_MPU_OrderedMemcpy(&(mpu->RBAR), &(table->RBAR), rowWordSize);
} else {
uint32_t rnrBase = rnr & ~(MPU_TYPE_RALIASES-1U);
uint32_t rnrOffset = rnr % MPU_TYPE_RALIASES;
mpu->RNR = rnrBase;
while ((rnrOffset + cnt) > MPU_TYPE_RALIASES) {
uint32_t c = MPU_TYPE_RALIASES - rnrOffset;
ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), c*rowWordSize);
table += c;
cnt -= c;
rnrOffset = 0U;
rnrBase += MPU_TYPE_RALIASES;
mpu->RNR = rnrBase;
}
ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), cnt*rowWordSize);
}
}
/** Load the given number of MPU regions from a table.
* \param rnr First region number to be configured.
* \param table Pointer to the MPU configuration table.
* \param cnt Amount of regions to be configured.
*/
__STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
{
ARM_MPU_LoadEx(MPU, rnr, table, cnt);
}
#ifdef MPU_NS
/** Load the given number of MPU regions from a table to the Non-secure MPU.
* \param rnr First region number to be configured.
* \param table Pointer to the MPU configuration table.
* \param cnt Amount of regions to be configured.
*/
__STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
{
ARM_MPU_LoadEx(MPU_NS, rnr, table, cnt);
}
#endif
#endif

View File

@@ -0,0 +1,70 @@
/******************************************************************************
* @file tz_context.h
* @brief Context Management for Armv8-M TrustZone
* @version V1.0.1
* @date 10. January 2018
******************************************************************************/
/*
* Copyright (c) 2017-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef TZ_CONTEXT_H
#define TZ_CONTEXT_H
#include <stdint.h>
#ifndef TZ_MODULEID_T
#define TZ_MODULEID_T
/// \details Data type that identifies secure software modules called by a process.
typedef uint32_t TZ_ModuleId_t;
#endif
/// \details TZ Memory ID identifies an allocated memory slot.
typedef uint32_t TZ_MemoryId_t;
/// Initialize secure context memory system
/// \return execution status (1: success, 0: error)
uint32_t TZ_InitContextSystem_S (void);
/// Allocate context memory for calling secure software modules in TrustZone
/// \param[in] module identifies software modules called from non-secure mode
/// \return value != 0 id TrustZone memory slot identifier
/// \return value 0 no memory available or internal error
TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module);
/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id);
/// Load secure context (called on RTOS thread context switch)
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
uint32_t TZ_LoadContext_S (TZ_MemoryId_t id);
/// Store secure context (called on RTOS thread context switch)
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
uint32_t TZ_StoreContext_S (TZ_MemoryId_t id);
#endif // TZ_CONTEXT_H

View File

@@ -0,0 +1,759 @@
/*
* Copyright (c) 2013-2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 12. June 2020
* $Revision: V2.1.3
*
* Project: CMSIS-RTOS2 API
* Title: cmsis_os2.h header file
*
* Version 2.1.3
* Additional functions allowed to be called from Interrupt Service Routines:
* - osThreadGetId
* Version 2.1.2
* Additional functions allowed to be called from Interrupt Service Routines:
* - osKernelGetInfo, osKernelGetState
* Version 2.1.1
* Additional functions allowed to be called from Interrupt Service Routines:
* - osKernelGetTickCount, osKernelGetTickFreq
* Changed Kernel Tick type to uint32_t:
* - updated: osKernelGetTickCount, osDelayUntil
* Version 2.1.0
* Support for critical and uncritical sections (nesting safe):
* - updated: osKernelLock, osKernelUnlock
* - added: osKernelRestoreLock
* Updated Thread and Event Flags:
* - changed flags parameter and return type from int32_t to uint32_t
* Version 2.0.0
* Initial Release
*---------------------------------------------------------------------------*/
#ifndef CMSIS_OS2_H_
#define CMSIS_OS2_H_
#ifndef __NO_RETURN
#if defined(__CC_ARM)
#define __NO_RETURN __declspec(noreturn)
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#define __NO_RETURN __attribute__((__noreturn__))
#elif defined(__GNUC__)
#define __NO_RETURN __attribute__((__noreturn__))
#elif defined(__ICCARM__)
#define __NO_RETURN __noreturn
#else
#define __NO_RETURN
#endif
#endif
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
// ==== Enumerations, structures, defines ====
/// Version information.
typedef struct {
uint32_t api; ///< API version (major.minor.rev: mmnnnrrrr dec).
uint32_t kernel; ///< Kernel version (major.minor.rev: mmnnnrrrr dec).
} osVersion_t;
/// Kernel state.
typedef enum {
osKernelInactive = 0, ///< Inactive.
osKernelReady = 1, ///< Ready.
osKernelRunning = 2, ///< Running.
osKernelLocked = 3, ///< Locked.
osKernelSuspended = 4, ///< Suspended.
osKernelError = -1, ///< Error.
osKernelReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osKernelState_t;
/// Thread state.
typedef enum {
osThreadInactive = 0, ///< Inactive.
osThreadReady = 1, ///< Ready.
osThreadRunning = 2, ///< Running.
osThreadBlocked = 3, ///< Blocked.
osThreadTerminated = 4, ///< Terminated.
osThreadError = -1, ///< Error.
osThreadReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osThreadState_t;
/// Priority values.
typedef enum {
osPriorityNone = 0, ///< No priority (not initialized).
osPriorityIdle = 1, ///< Reserved for Idle thread.
osPriorityLow = 8, ///< Priority: low
osPriorityLow1 = 8+1, ///< Priority: low + 1
osPriorityLow2 = 8+2, ///< Priority: low + 2
osPriorityLow3 = 8+3, ///< Priority: low + 3
osPriorityLow4 = 8+4, ///< Priority: low + 4
osPriorityLow5 = 8+5, ///< Priority: low + 5
osPriorityLow6 = 8+6, ///< Priority: low + 6
osPriorityLow7 = 8+7, ///< Priority: low + 7
osPriorityBelowNormal = 16, ///< Priority: below normal
osPriorityBelowNormal1 = 16+1, ///< Priority: below normal + 1
osPriorityBelowNormal2 = 16+2, ///< Priority: below normal + 2
osPriorityBelowNormal3 = 16+3, ///< Priority: below normal + 3
osPriorityBelowNormal4 = 16+4, ///< Priority: below normal + 4
osPriorityBelowNormal5 = 16+5, ///< Priority: below normal + 5
osPriorityBelowNormal6 = 16+6, ///< Priority: below normal + 6
osPriorityBelowNormal7 = 16+7, ///< Priority: below normal + 7
osPriorityNormal = 24, ///< Priority: normal
osPriorityNormal1 = 24+1, ///< Priority: normal + 1
osPriorityNormal2 = 24+2, ///< Priority: normal + 2
osPriorityNormal3 = 24+3, ///< Priority: normal + 3
osPriorityNormal4 = 24+4, ///< Priority: normal + 4
osPriorityNormal5 = 24+5, ///< Priority: normal + 5
osPriorityNormal6 = 24+6, ///< Priority: normal + 6
osPriorityNormal7 = 24+7, ///< Priority: normal + 7
osPriorityAboveNormal = 32, ///< Priority: above normal
osPriorityAboveNormal1 = 32+1, ///< Priority: above normal + 1
osPriorityAboveNormal2 = 32+2, ///< Priority: above normal + 2
osPriorityAboveNormal3 = 32+3, ///< Priority: above normal + 3
osPriorityAboveNormal4 = 32+4, ///< Priority: above normal + 4
osPriorityAboveNormal5 = 32+5, ///< Priority: above normal + 5
osPriorityAboveNormal6 = 32+6, ///< Priority: above normal + 6
osPriorityAboveNormal7 = 32+7, ///< Priority: above normal + 7
osPriorityHigh = 40, ///< Priority: high
osPriorityHigh1 = 40+1, ///< Priority: high + 1
osPriorityHigh2 = 40+2, ///< Priority: high + 2
osPriorityHigh3 = 40+3, ///< Priority: high + 3
osPriorityHigh4 = 40+4, ///< Priority: high + 4
osPriorityHigh5 = 40+5, ///< Priority: high + 5
osPriorityHigh6 = 40+6, ///< Priority: high + 6
osPriorityHigh7 = 40+7, ///< Priority: high + 7
osPriorityRealtime = 48, ///< Priority: realtime
osPriorityRealtime1 = 48+1, ///< Priority: realtime + 1
osPriorityRealtime2 = 48+2, ///< Priority: realtime + 2
osPriorityRealtime3 = 48+3, ///< Priority: realtime + 3
osPriorityRealtime4 = 48+4, ///< Priority: realtime + 4
osPriorityRealtime5 = 48+5, ///< Priority: realtime + 5
osPriorityRealtime6 = 48+6, ///< Priority: realtime + 6
osPriorityRealtime7 = 48+7, ///< Priority: realtime + 7
osPriorityISR = 56, ///< Reserved for ISR deferred thread.
osPriorityError = -1, ///< System cannot determine priority or illegal priority.
osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osPriority_t;
// Minimum number of priorities required by CMSIS-RTOS2
#define osMinNumPriority 56
/// Entry point of a thread.
typedef void (*osThreadFunc_t) (void *argument);
/// Timer callback function.
typedef void (*osTimerFunc_t) (void *argument);
/// Timer type.
typedef enum {
osTimerOnce = 0, ///< One-shot timer.
osTimerPeriodic = 1 ///< Repeating timer.
} osTimerType_t;
// Timeout value.
#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
// Flags options (\ref osThreadFlagsWait and \ref osEventFlagsWait).
#define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default).
#define osFlagsWaitAll 0x00000001U ///< Wait for all flags.
#define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for.
// Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx).
#define osFlagsError 0x80000000U ///< Error indicator.
#define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1).
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
#define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3).
#define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4).
#define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6).
// Thread attributes (attr_bits in \ref osThreadAttr_t).
#define osThreadDetached 0x00000000U ///< Thread created in detached mode (default)
#define osThreadJoinable 0x00000001U ///< Thread created in joinable mode
// Mutex attributes (attr_bits in \ref osMutexAttr_t).
#define osMutexRecursive 0x00000001U ///< Recursive mutex.
#define osMutexPrioInherit 0x00000002U ///< Priority inherit protocol.
#define osMutexRobust 0x00000008U ///< Robust mutex.
/// Status code values returned by CMSIS-RTOS functions.
typedef enum {
osOK = 0, ///< Operation completed successfully.
osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits.
osErrorTimeout = -2, ///< Operation not completed within the timeout period.
osErrorResource = -3, ///< Resource not available.
osErrorParameter = -4, ///< Parameter error.
osErrorNoMemory = -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation.
osErrorISR = -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines.
osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osStatus_t;
/// \details Thread ID identifies the thread.
typedef void *osThreadId_t;
/// \details Timer ID identifies the timer.
typedef void *osTimerId_t;
/// \details Event Flags ID identifies the event flags.
typedef void *osEventFlagsId_t;
/// \details Mutex ID identifies the mutex.
typedef void *osMutexId_t;
/// \details Semaphore ID identifies the semaphore.
typedef void *osSemaphoreId_t;
/// \details Memory Pool ID identifies the memory pool.
typedef void *osMemoryPoolId_t;
/// \details Message Queue ID identifies the message queue.
typedef void *osMessageQueueId_t;
#ifndef TZ_MODULEID_T
#define TZ_MODULEID_T
/// \details Data type that identifies secure software modules called by a process.
typedef uint32_t TZ_ModuleId_t;
#endif
/// Attributes structure for thread.
typedef struct {
const char *name; ///< name of the thread
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
void *stack_mem; ///< memory for stack
uint32_t stack_size; ///< size of stack
osPriority_t priority; ///< initial thread priority (default: osPriorityNormal)
TZ_ModuleId_t tz_module; ///< TrustZone module identifier
uint32_t reserved; ///< reserved (must be 0)
} osThreadAttr_t;
/// Attributes structure for timer.
typedef struct {
const char *name; ///< name of the timer
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
} osTimerAttr_t;
/// Attributes structure for event flags.
typedef struct {
const char *name; ///< name of the event flags
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
} osEventFlagsAttr_t;
/// Attributes structure for mutex.
typedef struct {
const char *name; ///< name of the mutex
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
} osMutexAttr_t;
/// Attributes structure for semaphore.
typedef struct {
const char *name; ///< name of the semaphore
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
} osSemaphoreAttr_t;
/// Attributes structure for memory pool.
typedef struct {
const char *name; ///< name of the memory pool
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
void *mp_mem; ///< memory for data storage
uint32_t mp_size; ///< size of provided memory for data storage
} osMemoryPoolAttr_t;
/// Attributes structure for message queue.
typedef struct {
const char *name; ///< name of the message queue
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
void *mq_mem; ///< memory for data storage
uint32_t mq_size; ///< size of provided memory for data storage
} osMessageQueueAttr_t;
// ==== Kernel Management Functions ====
/// Initialize the RTOS Kernel.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelInitialize (void);
/// Get RTOS Kernel Information.
/// \param[out] version pointer to buffer for retrieving version information.
/// \param[out] id_buf pointer to buffer for retrieving kernel identification string.
/// \param[in] id_size size of buffer for kernel identification string.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size);
/// Get the current RTOS Kernel state.
/// \return current RTOS Kernel state.
osKernelState_t osKernelGetState (void);
/// Start the RTOS Kernel scheduler.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelStart (void);
/// Lock the RTOS Kernel scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelLock (void);
/// Unlock the RTOS Kernel scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelUnlock (void);
/// Restore the RTOS Kernel scheduler lock state.
/// \param[in] lock lock state obtained by \ref osKernelLock or \ref osKernelUnlock.
/// \return new lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelRestoreLock (int32_t lock);
/// Suspend the RTOS Kernel scheduler.
/// \return time in ticks, for how long the system can sleep or power-down.
uint32_t osKernelSuspend (void);
/// Resume the RTOS Kernel scheduler.
/// \param[in] sleep_ticks time in ticks for how long the system was in sleep or power-down mode.
void osKernelResume (uint32_t sleep_ticks);
/// Get the RTOS kernel tick count.
/// \return RTOS kernel current tick count.
uint32_t osKernelGetTickCount (void);
/// Get the RTOS kernel tick frequency.
/// \return frequency of the kernel tick in hertz, i.e. kernel ticks per second.
uint32_t osKernelGetTickFreq (void);
/// Get the RTOS kernel system timer count.
/// \return RTOS kernel current system timer count as 32-bit value.
uint32_t osKernelGetSysTimerCount (void);
/// Get the RTOS kernel system timer frequency.
/// \return frequency of the system timer in hertz, i.e. timer ticks per second.
uint32_t osKernelGetSysTimerFreq (void);
// ==== Thread Management Functions ====
/// Create a thread and add it to Active Threads.
/// \param[in] func thread function.
/// \param[in] argument pointer that is passed to the thread function as start argument.
/// \param[in] attr thread attributes; NULL: default values.
/// \return thread ID for reference by other functions or NULL in case of error.
osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
/// Get name of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return name as null-terminated string.
const char *osThreadGetName (osThreadId_t thread_id);
/// Return the thread ID of the current running thread.
/// \return thread ID for reference by other functions or NULL in case of error.
osThreadId_t osThreadGetId (void);
/// Get current thread state of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return current thread state of the specified thread.
osThreadState_t osThreadGetState (osThreadId_t thread_id);
/// Get stack size of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return stack size in bytes.
uint32_t osThreadGetStackSize (osThreadId_t thread_id);
/// Get available stack space of a thread based on stack watermark recording during execution.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return remaining stack space in bytes.
uint32_t osThreadGetStackSpace (osThreadId_t thread_id);
/// Change priority of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \param[in] priority new priority value for the thread function.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority);
/// Get current priority of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return current priority value of the specified thread.
osPriority_t osThreadGetPriority (osThreadId_t thread_id);
/// Pass control to next thread that is in state \b READY.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadYield (void);
/// Suspend execution of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSuspend (osThreadId_t thread_id);
/// Resume execution of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadResume (osThreadId_t thread_id);
/// Detach a thread (thread storage can be reclaimed when thread terminates).
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadDetach (osThreadId_t thread_id);
/// Wait for specified thread to terminate.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadJoin (osThreadId_t thread_id);
/// Terminate execution of current running thread.
__NO_RETURN void osThreadExit (void);
/// Terminate execution of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadTerminate (osThreadId_t thread_id);
/// Get number of active threads.
/// \return number of active threads.
uint32_t osThreadGetCount (void);
/// Enumerate active threads.
/// \param[out] thread_array pointer to array for retrieving thread IDs.
/// \param[in] array_items maximum number of items in array for retrieving thread IDs.
/// \return number of enumerated threads.
uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items);
// ==== Thread Flags Functions ====
/// Set the specified Thread Flags of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \param[in] flags specifies the flags of the thread that shall be set.
/// \return thread flags after setting or error code if highest bit set.
uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags);
/// Clear the specified Thread Flags of current running thread.
/// \param[in] flags specifies the flags of the thread that shall be cleared.
/// \return thread flags before clearing or error code if highest bit set.
uint32_t osThreadFlagsClear (uint32_t flags);
/// Get the current Thread Flags of current running thread.
/// \return current thread flags.
uint32_t osThreadFlagsGet (void);
/// Wait for one or more Thread Flags of the current running thread to become signaled.
/// \param[in] flags specifies the flags to wait for.
/// \param[in] options specifies flags options (osFlagsXxxx).
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return thread flags before clearing or error code if highest bit set.
uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout);
// ==== Generic Wait Functions ====
/// Wait for Timeout (Time Delay).
/// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value
/// \return status code that indicates the execution status of the function.
osStatus_t osDelay (uint32_t ticks);
/// Wait until specified time.
/// \param[in] ticks absolute time in ticks
/// \return status code that indicates the execution status of the function.
osStatus_t osDelayUntil (uint32_t ticks);
// ==== Timer Management Functions ====
/// Create and Initialize a timer.
/// \param[in] func function pointer to callback function.
/// \param[in] type \ref osTimerOnce for one-shot or \ref osTimerPeriodic for periodic behavior.
/// \param[in] argument argument to the timer callback function.
/// \param[in] attr timer attributes; NULL: default values.
/// \return timer ID for reference by other functions or NULL in case of error.
osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr);
/// Get name of a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \return name as null-terminated string.
const char *osTimerGetName (osTimerId_t timer_id);
/// Start or restart a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer.
/// \return status code that indicates the execution status of the function.
osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks);
/// Stop a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osTimerStop (osTimerId_t timer_id);
/// Check if a timer is running.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \return 0 not running, 1 running.
uint32_t osTimerIsRunning (osTimerId_t timer_id);
/// Delete a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osTimerDelete (osTimerId_t timer_id);
// ==== Event Flags Management Functions ====
/// Create and Initialize an Event Flags object.
/// \param[in] attr event flags attributes; NULL: default values.
/// \return event flags ID for reference by other functions or NULL in case of error.
osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr);
/// Get name of an Event Flags object.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \return name as null-terminated string.
const char *osEventFlagsGetName (osEventFlagsId_t ef_id);
/// Set the specified Event Flags.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \param[in] flags specifies the flags that shall be set.
/// \return event flags after setting or error code if highest bit set.
uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags);
/// Clear the specified Event Flags.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \param[in] flags specifies the flags that shall be cleared.
/// \return event flags before clearing or error code if highest bit set.
uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags);
/// Get the current Event Flags.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \return current event flags.
uint32_t osEventFlagsGet (osEventFlagsId_t ef_id);
/// Wait for one or more Event Flags to become signaled.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \param[in] flags specifies the flags to wait for.
/// \param[in] options specifies flags options (osFlagsXxxx).
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return event flags before clearing or error code if highest bit set.
uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout);
/// Delete an Event Flags object.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id);
// ==== Mutex Management Functions ====
/// Create and Initialize a Mutex object.
/// \param[in] attr mutex attributes; NULL: default values.
/// \return mutex ID for reference by other functions or NULL in case of error.
osMutexId_t osMutexNew (const osMutexAttr_t *attr);
/// Get name of a Mutex object.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \return name as null-terminated string.
const char *osMutexGetName (osMutexId_t mutex_id);
/// Acquire a Mutex or timeout if it is locked.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout);
/// Release a Mutex that was acquired by \ref osMutexAcquire.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexRelease (osMutexId_t mutex_id);
/// Get Thread which owns a Mutex object.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \return thread ID of owner thread or NULL when mutex was not acquired.
osThreadId_t osMutexGetOwner (osMutexId_t mutex_id);
/// Delete a Mutex object.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexDelete (osMutexId_t mutex_id);
// ==== Semaphore Management Functions ====
/// Create and Initialize a Semaphore object.
/// \param[in] max_count maximum number of available tokens.
/// \param[in] initial_count initial number of available tokens.
/// \param[in] attr semaphore attributes; NULL: default values.
/// \return semaphore ID for reference by other functions or NULL in case of error.
osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
/// Get name of a Semaphore object.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \return name as null-terminated string.
const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id);
/// Acquire a Semaphore token or timeout if no tokens are available.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout);
/// Release a Semaphore token up to the initial maximum count.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id);
/// Get current Semaphore token count.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \return number of tokens available.
uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id);
/// Delete a Semaphore object.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id);
// ==== Memory Pool Management Functions ====
/// Create and Initialize a Memory Pool object.
/// \param[in] block_count maximum number of memory blocks in memory pool.
/// \param[in] block_size memory block size in bytes.
/// \param[in] attr memory pool attributes; NULL: default values.
/// \return memory pool ID for reference by other functions or NULL in case of error.
osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr);
/// Get name of a Memory Pool object.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return name as null-terminated string.
const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id);
/// Allocate a memory block from a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return address of the allocated memory block or NULL in case of no memory is available.
void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout);
/// Return an allocated memory block back to a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \param[in] block address of the allocated memory block to be returned to the memory pool.
/// \return status code that indicates the execution status of the function.
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block);
/// Get maximum number of memory blocks in a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return maximum number of memory blocks.
uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id);
/// Get memory block size in a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return memory block size in bytes.
uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id);
/// Get number of memory blocks used in a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return number of memory blocks used.
uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id);
/// Get number of memory blocks available in a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return number of memory blocks available.
uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id);
/// Delete a Memory Pool object.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id);
// ==== Message Queue Management Functions ====
/// Create and Initialize a Message Queue object.
/// \param[in] msg_count maximum number of messages in queue.
/// \param[in] msg_size maximum message size in bytes.
/// \param[in] attr message queue attributes; NULL: default values.
/// \return message queue ID for reference by other functions or NULL in case of error.
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr);
/// Get name of a Message Queue object.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return name as null-terminated string.
const char *osMessageQueueGetName (osMessageQueueId_t mq_id);
/// Put a Message into a Queue or timeout if Queue is full.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \param[in] msg_ptr pointer to buffer with message to put into a queue.
/// \param[in] msg_prio message priority.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
/// Get a Message from a Queue or timeout if Queue is empty.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \param[out] msg_ptr pointer to buffer for message to get from a queue.
/// \param[out] msg_prio pointer to buffer for message priority or NULL.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);
/// Get maximum number of messages in a Message Queue.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return maximum number of messages.
uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id);
/// Get maximum message size in a Message Queue.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return maximum message size in bytes.
uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id);
/// Get number of queued messages in a Message Queue.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return number of queued messages.
uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id);
/// Get number of available slots for messages in a Message Queue.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return number of available slots for messages.
uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id);
/// Reset a Message Queue to initial empty state.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id);
/// Delete a Message Queue object.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id);
#ifdef __cplusplus
}
#endif
#endif // CMSIS_OS2_H_

View File

@@ -0,0 +1,80 @@
/**************************************************************************//**
* @file os_tick.h
* @brief CMSIS OS Tick header file
* @version V1.0.2
* @date 19. March 2021
******************************************************************************/
/*
* Copyright (c) 2017-2021 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OS_TICK_H
#define OS_TICK_H
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/// IRQ Handler.
#ifndef IRQHANDLER_T
#define IRQHANDLER_T
typedef void (*IRQHandler_t) (void);
#endif
/// Setup OS Tick timer to generate periodic RTOS Kernel Ticks
/// \param[in] freq tick frequency in Hz
/// \param[in] handler tick IRQ handler
/// \return 0 on success, -1 on error.
int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler);
/// Enable OS Tick timer interrupt
void OS_Tick_Enable (void);
/// Disable OS Tick timer interrupt
void OS_Tick_Disable (void);
/// Acknowledge execution of OS Tick timer interrupt
void OS_Tick_AcknowledgeIRQ (void);
/// Get OS Tick timer IRQ number
/// \return OS Tick IRQ number
int32_t OS_Tick_GetIRQn (void);
/// Get OS Tick timer clock frequency
/// \return OS Tick timer clock frequency in Hz
uint32_t OS_Tick_GetClock (void);
/// Get OS Tick timer interval reload value
/// \return OS Tick timer interval reload value
uint32_t OS_Tick_GetInterval (void);
/// Get OS Tick timer counter value
/// \return OS Tick timer counter value
uint32_t OS_Tick_GetCount (void);
/// Get OS Tick timer overflow status
/// \return OS Tick overflow status (1 - overflow, 0 - no overflow).
uint32_t OS_Tick_GetOverflow (void);
#ifdef __cplusplus
}
#endif
#endif /* OS_TICK_H */

View File

@@ -0,0 +1,133 @@
/**************************************************************************//**
* @file os_systick.c
* @brief CMSIS OS Tick SysTick implementation
* @version V1.0.3
* @date 19. March 2021
******************************************************************************/
/*
* Copyright (c) 2017-2021 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "os_tick.h"
//lint -emacro((923,9078),SCB,SysTick) "cast from unsigned long to pointer"
#include "RTE_Components.h"
#include CMSIS_device_header
#ifdef SysTick
#ifndef SYSTICK_IRQ_PRIORITY
#define SYSTICK_IRQ_PRIORITY 0xFFU
#endif
static uint8_t PendST __attribute__((section(".bss.os")));
// Setup OS Tick.
__WEAK int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) {
uint32_t load;
(void)handler;
if (freq == 0U) {
//lint -e{904} "Return statement before end of function"
return (-1);
}
load = (SystemCoreClock / freq) - 1U;
if (load > 0x00FFFFFFU) {
//lint -e{904} "Return statement before end of function"
return (-1);
}
// Set SysTick Interrupt Priority
#if ((defined(__ARM_ARCH_8M_MAIN__) && (__ARM_ARCH_8M_MAIN__ != 0)) || \
(defined(__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ != 0)) || \
(defined(__CORTEX_M) && (__CORTEX_M == 7U)))
SCB->SHPR[11] = SYSTICK_IRQ_PRIORITY;
#elif (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
SCB->SHPR[1] |= ((uint32_t)SYSTICK_IRQ_PRIORITY << 24);
#elif ((defined(__ARM_ARCH_7M__) && (__ARM_ARCH_7M__ != 0)) || \
(defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ != 0)))
SCB->SHP[11] = SYSTICK_IRQ_PRIORITY;
#elif (defined(__ARM_ARCH_6M__) && (__ARM_ARCH_6M__ != 0))
SCB->SHP[1] |= ((uint32_t)SYSTICK_IRQ_PRIORITY << 24);
#else
#error "Unknown ARM Core!"
#endif
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk;
SysTick->LOAD = load;
SysTick->VAL = 0U;
PendST = 0U;
return (0);
}
/// Enable OS Tick.
__WEAK void OS_Tick_Enable (void) {
if (PendST != 0U) {
PendST = 0U;
SCB->ICSR = SCB_ICSR_PENDSTSET_Msk;
}
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
/// Disable OS Tick.
__WEAK void OS_Tick_Disable (void) {
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
if ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) != 0U) {
SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk;
PendST = 1U;
}
}
// Acknowledge OS Tick IRQ.
__WEAK void OS_Tick_AcknowledgeIRQ (void) {
(void)SysTick->CTRL;
}
// Get OS Tick IRQ number.
__WEAK int32_t OS_Tick_GetIRQn (void) {
return ((int32_t)SysTick_IRQn);
}
// Get OS Tick clock.
__WEAK uint32_t OS_Tick_GetClock (void) {
return (SystemCoreClock);
}
// Get OS Tick interval.
__WEAK uint32_t OS_Tick_GetInterval (void) {
return (SysTick->LOAD + 1U);
}
// Get OS Tick count value.
__WEAK uint32_t OS_Tick_GetCount (void) {
uint32_t load = SysTick->LOAD;
return (load - SysTick->VAL);
}
// Get OS Tick overflow status.
__WEAK uint32_t OS_Tick_GetOverflow (void) {
return ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) >> SCB_ICSR_PENDSTSET_Pos);
}
#endif // SysTick

View File

@@ -0,0 +1,63 @@
/* --------------------------------------------------------------------------
* Copyright (c) 2013-2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Name: freertos_mpool.h
* Purpose: CMSIS RTOS2 wrapper for FreeRTOS
*
*---------------------------------------------------------------------------*/
#ifndef FREERTOS_MPOOL_H_
#define FREERTOS_MPOOL_H_
#include <stdint.h>
#include "FreeRTOS.h"
#include "semphr.h"
/* Memory Pool implementation definitions */
#define MPOOL_STATUS 0x5EED0000U
/* Memory Block header */
typedef struct {
void *next; /* Pointer to next block */
} MemPoolBlock_t;
/* Memory Pool control block */
typedef struct MemPoolDef_t {
MemPoolBlock_t *head; /* Pointer to head block */
SemaphoreHandle_t sem; /* Pool semaphore handle */
uint8_t *mem_arr; /* Pool memory array */
uint32_t mem_sz; /* Pool memory array size */
const char *name; /* Pointer to name string */
uint32_t bl_sz; /* Size of a single block */
uint32_t bl_cnt; /* Number of blocks */
uint32_t n; /* Block allocation index */
volatile uint32_t status; /* Object status flags */
#if (configSUPPORT_STATIC_ALLOCATION == 1)
StaticSemaphore_t mem_sem; /* Semaphore object memory */
#endif
} MemPool_t;
/* No need to hide static object type, just align to coding style */
#define StaticMemPool_t MemPool_t
/* Define memory pool control block size */
#define MEMPOOL_CB_SIZE (sizeof(StaticMemPool_t))
/* Define size of the byte array required to create count of blocks of given size */
#define MEMPOOL_ARR_SIZE(bl_count, bl_size) (((((bl_size) + (4 - 1)) / 4) * 4)*(bl_count))
#endif /* FREERTOS_MPOOL_H_ */

View File

@@ -0,0 +1,336 @@
/* --------------------------------------------------------------------------
* Copyright (c) 2013-2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Name: freertos_os2.h
* Purpose: CMSIS RTOS2 wrapper for FreeRTOS
*
*---------------------------------------------------------------------------*/
#ifndef FREERTOS_OS2_H_
#define FREERTOS_OS2_H_
#include <string.h>
#include <stdint.h>
#include "FreeRTOS.h" // ARM.FreeRTOS::RTOS:Core
#if defined(_RTE_)
#include "RTE_Components.h" // Component selection
#include CMSIS_device_header
/* Configuration and component setup check */
#if defined(RTE_Compiler_EventRecorder)
#if !defined(EVR_FREERTOS_DISABLE)
#define USE_TRACE_EVENT_RECORDER
/*
FreeRTOS provides functions and hooks to support execution tracing. This
functionality is only enabled if configUSE_TRACE_FACILITY == 1.
Set #define configUSE_TRACE_FACILITY 1 in FreeRTOSConfig.h to enable trace events.
*/
#if (configUSE_TRACE_FACILITY == 0)
#error "Definition configUSE_TRACE_FACILITY must equal 1 to enable FreeRTOS trace events."
#endif
#endif
#endif
#if defined(RTE_RTOS_FreeRTOS_HEAP_1)
#define USE_FreeRTOS_HEAP_1
#endif
#if defined(RTE_RTOS_FreeRTOS_HEAP_5)
#define USE_FreeRTOS_HEAP_5
#endif
#endif /* _RTE_ */
/*
CMSIS-RTOS2 FreeRTOS image size optimization definitions.
Note: Definitions configUSE_OS2 can be used to optimize FreeRTOS image size when
certain functionality is not required when using CMSIS-RTOS2 API.
In general optimization decisions are left to the tool chain but in cases
when coding style prevents it to optimize the code following optional
definitions can be used.
*/
/*
Option to exclude CMSIS-RTOS2 functions osThreadSuspend and osThreadResume from
the application image.
*/
#ifndef configUSE_OS2_THREAD_SUSPEND_RESUME
#define configUSE_OS2_THREAD_SUSPEND_RESUME 1
#endif
/*
Option to exclude CMSIS-RTOS2 function osThreadEnumerate from the application image.
*/
#ifndef configUSE_OS2_THREAD_ENUMERATE
#define configUSE_OS2_THREAD_ENUMERATE 1
#endif
/*
Option to disable CMSIS-RTOS2 function osEventFlagsSet and osEventFlagsClear
operation from ISR.
*/
#ifndef configUSE_OS2_EVENTFLAGS_FROM_ISR
#define configUSE_OS2_EVENTFLAGS_FROM_ISR 1
#endif
/*
Option to exclude CMSIS-RTOS2 Thread Flags API functions from the application image.
*/
#ifndef configUSE_OS2_THREAD_FLAGS
#define configUSE_OS2_THREAD_FLAGS configUSE_TASK_NOTIFICATIONS
#endif
/*
Option to exclude CMSIS-RTOS2 Timer API functions from the application image.
*/
#ifndef configUSE_OS2_TIMER
#define configUSE_OS2_TIMER configUSE_TIMERS
#endif
/*
Option to exclude CMSIS-RTOS2 Mutex API functions from the application image.
*/
#ifndef configUSE_OS2_MUTEX
#define configUSE_OS2_MUTEX configUSE_MUTEXES
#endif
/*
CMSIS-RTOS2 FreeRTOS configuration check (FreeRTOSConfig.h).
Note: CMSIS-RTOS API requires functions included by using following definitions.
In case if certain API function is not used compiler will optimize it away.
*/
#if (INCLUDE_xSemaphoreGetMutexHolder == 0)
/*
CMSIS-RTOS2 function osMutexGetOwner uses FreeRTOS function xSemaphoreGetMutexHolder. In case if
osMutexGetOwner is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_xSemaphoreGetMutexHolder 1 to fix this error.
*/
#error "Definition INCLUDE_xSemaphoreGetMutexHolder must equal 1 to implement Mutex Management API."
#endif
#if (INCLUDE_vTaskDelay == 0)
/*
CMSIS-RTOS2 function osDelay uses FreeRTOS function vTaskDelay. In case if
osDelay is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_vTaskDelay 1 to fix this error.
*/
#error "Definition INCLUDE_vTaskDelay must equal 1 to implement Generic Wait Functions API."
#endif
#if (INCLUDE_vTaskDelayUntil == 0)
/*
CMSIS-RTOS2 function osDelayUntil uses FreeRTOS function vTaskDelayUntil. In case if
osDelayUntil is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_vTaskDelayUntil 1 to fix this error.
*/
#error "Definition INCLUDE_vTaskDelayUntil must equal 1 to implement Generic Wait Functions API."
#endif
#if (INCLUDE_vTaskDelete == 0)
/*
CMSIS-RTOS2 function osThreadTerminate and osThreadExit uses FreeRTOS function
vTaskDelete. In case if they are not used in the application image, compiler
will optimize them away.
Set #define INCLUDE_vTaskDelete 1 to fix this error.
*/
#error "Definition INCLUDE_vTaskDelete must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_xTaskGetCurrentTaskHandle == 0)
/*
CMSIS-RTOS2 API uses FreeRTOS function xTaskGetCurrentTaskHandle to implement
functions osThreadGetId, osThreadFlagsClear and osThreadFlagsGet. In case if these
functions are not used in the application image, compiler will optimize them away.
Set #define INCLUDE_xTaskGetCurrentTaskHandle 1 to fix this error.
*/
#error "Definition INCLUDE_xTaskGetCurrentTaskHandle must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_xTaskGetSchedulerState == 0)
/*
CMSIS-RTOS2 API uses FreeRTOS function xTaskGetSchedulerState to implement Kernel
tick handling and therefore it is vital that xTaskGetSchedulerState is included into
the application image.
Set #define INCLUDE_xTaskGetSchedulerState 1 to fix this error.
*/
#error "Definition INCLUDE_xTaskGetSchedulerState must equal 1 to implement Kernel Information and Control API."
#endif
#if (INCLUDE_uxTaskGetStackHighWaterMark == 0)
/*
CMSIS-RTOS2 function osThreadGetStackSpace uses FreeRTOS function uxTaskGetStackHighWaterMark.
In case if osThreadGetStackSpace is not used in the application image, compiler will
optimize it away.
Set #define INCLUDE_uxTaskGetStackHighWaterMark 1 to fix this error.
*/
#error "Definition INCLUDE_uxTaskGetStackHighWaterMark must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_uxTaskPriorityGet == 0)
/*
CMSIS-RTOS2 function osThreadGetPriority uses FreeRTOS function uxTaskPriorityGet. In case if
osThreadGetPriority is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_uxTaskPriorityGet 1 to fix this error.
*/
#error "Definition INCLUDE_uxTaskPriorityGet must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_vTaskPrioritySet == 0)
/*
CMSIS-RTOS2 function osThreadSetPriority uses FreeRTOS function vTaskPrioritySet. In case if
osThreadSetPriority is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_vTaskPrioritySet 1 to fix this error.
*/
#error "Definition INCLUDE_vTaskPrioritySet must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_eTaskGetState == 0)
/*
CMSIS-RTOS2 API uses FreeRTOS function vTaskDelayUntil to implement functions osThreadGetState
and osThreadTerminate. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define INCLUDE_eTaskGetState 1 to fix this error.
*/
#error "Definition INCLUDE_eTaskGetState must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_vTaskSuspend == 0)
/*
CMSIS-RTOS2 API uses FreeRTOS functions vTaskSuspend and vTaskResume to implement
functions osThreadSuspend and osThreadResume. In case if these functions are not
used in the application image, compiler will optimize them away.
Set #define INCLUDE_vTaskSuspend 1 to fix this error.
Alternatively, if the application does not use osThreadSuspend and
osThreadResume they can be excluded from the image code by setting:
#define configUSE_OS2_THREAD_SUSPEND_RESUME 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_THREAD_SUSPEND_RESUME == 1)
#error "Definition INCLUDE_vTaskSuspend must equal 1 to implement Kernel Information and Control API."
#endif
#endif
#if (INCLUDE_xTimerPendFunctionCall == 0)
/*
CMSIS-RTOS2 function osEventFlagsSet and osEventFlagsClear, when called from
the ISR, call FreeRTOS functions xEventGroupSetBitsFromISR and
xEventGroupClearBitsFromISR which are only enabled if timers are operational and
xTimerPendFunctionCall in enabled.
Set #define INCLUDE_xTimerPendFunctionCall 1 and #define configUSE_TIMERS 1
to fix this error.
Alternatively, if the application does not use osEventFlagsSet and osEventFlagsClear
from the ISR their operation from ISR can be restricted by setting:
#define configUSE_OS2_EVENTFLAGS_FROM_ISR 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 1)
#error "Definition INCLUDE_xTimerPendFunctionCall must equal 1 to implement Event Flags API."
#endif
#endif
#if (configUSE_TIMERS == 0)
/*
CMSIS-RTOS2 Timer Management API functions use FreeRTOS timer functions to implement
timer management. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define configUSE_TIMERS 1 to fix this error.
Alternatively, if the application does not use timer functions they can be
excluded from the image code by setting:
#define configUSE_OS2_TIMER 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_TIMER == 1)
#error "Definition configUSE_TIMERS must equal 1 to implement Timer Management API."
#endif
#endif
#if (configUSE_MUTEXES == 0)
/*
CMSIS-RTOS2 Mutex Management API functions use FreeRTOS mutex functions to implement
mutex management. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define configUSE_MUTEXES 1 to fix this error.
Alternatively, if the application does not use mutex functions they can be
excluded from the image code by setting:
#define configUSE_OS2_MUTEX 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_MUTEX == 1)
#error "Definition configUSE_MUTEXES must equal 1 to implement Mutex Management API."
#endif
#endif
#if (configUSE_COUNTING_SEMAPHORES == 0)
/*
CMSIS-RTOS2 Memory Pool functions use FreeRTOS function xSemaphoreCreateCounting
to implement memory pools. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define configUSE_COUNTING_SEMAPHORES 1 to fix this error.
*/
#error "Definition configUSE_COUNTING_SEMAPHORES must equal 1 to implement Memory Pool API."
#endif
#if (configUSE_TASK_NOTIFICATIONS == 0)
/*
CMSIS-RTOS2 Thread Flags API functions use FreeRTOS Task Notification functions to implement
thread flag management. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define configUSE_TASK_NOTIFICATIONS 1 to fix this error.
Alternatively, if the application does not use thread flags functions they can be
excluded from the image code by setting:
#define configUSE_OS2_THREAD_FLAGS 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_THREAD_FLAGS == 1)
#error "Definition configUSE_TASK_NOTIFICATIONS must equal 1 to implement Thread Flags API."
#endif
#endif
#if (configUSE_TRACE_FACILITY == 0)
/*
CMSIS-RTOS2 function osThreadEnumerate requires FreeRTOS function uxTaskGetSystemState
which is only enabled if configUSE_TRACE_FACILITY == 1.
Set #define configUSE_TRACE_FACILITY 1 to fix this error.
Alternatively, if the application does not use osThreadEnumerate it can be
excluded from the image code by setting:
#define configUSE_OS2_THREAD_ENUMERATE 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_THREAD_ENUMERATE == 1)
#error "Definition configUSE_TRACE_FACILITY must equal 1 to implement osThreadEnumerate."
#endif
#endif
#if (configUSE_16_BIT_TICKS == 1)
/*
CMSIS-RTOS2 wrapper for FreeRTOS relies on 32-bit tick timer which is also optimal on
a 32-bit CPU architectures.
Set #define configUSE_16_BIT_TICKS 0 to fix this error.
*/
#error "Definition configUSE_16_BIT_TICKS must be zero to implement CMSIS-RTOS2 API."
#endif
#if (configMAX_PRIORITIES != 56)
/*
CMSIS-RTOS2 defines 56 different priorities (see osPriority_t) and portable CMSIS-RTOS2
implementation should implement the same number of priorities.
Set #define configMAX_PRIORITIES 56 to fix this error.
*/
#error "Definition configMAX_PRIORITIES must equal 56 to implement Thread Management API."
#endif
#if (configUSE_PORT_OPTIMISED_TASK_SELECTION != 0)
/*
CMSIS-RTOS2 requires handling of 56 different priorities (see osPriority_t) while FreeRTOS port
optimised selection for Cortex core only handles 32 different priorities.
Set #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 to fix this error.
*/
#error "Definition configUSE_PORT_OPTIMISED_TASK_SELECTION must be zero to implement Thread Management API."
#endif
#endif /* FREERTOS_OS2_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,374 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"
/* Remove the whole file is co-routines are not being used. */
#if ( configUSE_CO_ROUTINES != 0 )
/*
* Some kernel aware debuggers require data to be viewed to be global, rather
* than file scope.
*/
#ifdef portREMOVE_STATIC_QUALIFIER
#define static
#endif
/* Lists for ready and blocked co-routines. --------------------*/
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */
static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
static List_t * pxDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used. */
static List_t * pxOverflowDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
/* Other file private variables. --------------------------------*/
CRCB_t * pxCurrentCoRoutine = NULL;
static UBaseType_t uxTopCoRoutineReadyPriority = 0;
static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
/* The initial state of the co-routine when it is created. */
#define corINITIAL_STATE ( 0 )
/*
* Place the co-routine represented by pxCRCB into the appropriate ready queue
* for the priority. It is inserted at the end of the list.
*
* This macro accesses the co-routine ready lists and therefore must not be
* used from within an ISR.
*/
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \
{ \
if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
{ \
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
} \
vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
}
/*
* Utility to ready all the lists used by the scheduler. This is called
* automatically upon the creation of the first co-routine.
*/
static void prvInitialiseCoRoutineLists( void );
/*
* Co-routines that are readied by an interrupt cannot be placed directly into
* the ready lists (there is no mutual exclusion). Instead they are placed in
* in the pending ready list in order that they can later be moved to the ready
* list by the co-routine scheduler.
*/
static void prvCheckPendingReadyList( void );
/*
* Macro that looks at the list of co-routines that are currently delayed to
* see if any require waking.
*
* Co-routines are stored in the queue in the order of their wake time -
* meaning once one co-routine has been found whose timer has not expired
* we need not look any further down the list.
*/
static void prvCheckDelayedList( void );
/*-----------------------------------------------------------*/
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
UBaseType_t uxPriority,
UBaseType_t uxIndex )
{
BaseType_t xReturn;
CRCB_t * pxCoRoutine;
/* Allocate the memory that will store the co-routine control block. */
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
if( pxCoRoutine )
{
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
* be created and the co-routine data structures need initialising. */
if( pxCurrentCoRoutine == NULL )
{
pxCurrentCoRoutine = pxCoRoutine;
prvInitialiseCoRoutineLists();
}
/* Check the priority is within limits. */
if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
{
uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
}
/* Fill out the co-routine control block from the function parameters. */
pxCoRoutine->uxState = corINITIAL_STATE;
pxCoRoutine->uxPriority = uxPriority;
pxCoRoutine->uxIndex = uxIndex;
pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
/* Initialise all the other co-routine control block parameters. */
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
/* Set the co-routine control block as a link back from the ListItem_t.
* This is so we can get back to the containing CRCB from a generic item
* in a list. */
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
/* Event lists are always in priority order. */
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
/* Now the co-routine has been initialised it can be added to the ready
* list at the correct priority. */
prvAddCoRoutineToReadyQueue( pxCoRoutine );
xReturn = pdPASS;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
return xReturn;
}
/*-----------------------------------------------------------*/
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
List_t * pxEventList )
{
TickType_t xTimeToWake;
/* Calculate the time to wake - this may overflow but this is
* not a problem. */
xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
/* We must remove ourselves from the ready list before adding
* ourselves to the blocked list as the same list item is used for
* both lists. */
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xCoRoutineTickCount )
{
/* Wake time has overflowed. Place this item in the
* overflow list. */
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so we can use the
* current block list. */
vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
}
if( pxEventList )
{
/* Also add the co-routine to an event list. If this is done then the
* function must be called with interrupts disabled. */
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
}
}
/*-----------------------------------------------------------*/
static void prvCheckPendingReadyList( void )
{
/* Are there any co-routines waiting to get moved to the ready list? These
* are co-routines that have been readied by an ISR. The ISR cannot access
* the ready lists itself. */
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
{
CRCB_t * pxUnblockedCRCB;
/* The pending ready list can be accessed by an ISR. */
portDISABLE_INTERRUPTS();
{
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyCoRoutineList ) );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
}
portENABLE_INTERRUPTS();
( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
}
}
/*-----------------------------------------------------------*/
static void prvCheckDelayedList( void )
{
CRCB_t * pxCRCB;
xPassedTicks = xTaskGetTickCount() - xLastTickCount;
while( xPassedTicks )
{
xCoRoutineTickCount++;
xPassedTicks--;
/* If the tick count has overflowed we need to swap the ready lists. */
if( xCoRoutineTickCount == 0 )
{
List_t * pxTemp;
/* Tick count has overflowed so we need to swap the delay lists. If there are
* any items in pxDelayedCoRoutineList here then there is an error! */
pxTemp = pxDelayedCoRoutineList;
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
pxOverflowDelayedCoRoutineList = pxTemp;
}
/* See if this tick has made a timeout expire. */
while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
{
pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
{
/* Timeout not yet expired. */
break;
}
portDISABLE_INTERRUPTS();
{
/* The event could have occurred just before this critical
* section. If this is the case then the generic list item will
* have been moved to the pending ready list and the following
* line is still valid. Also the pvContainer parameter will have
* been set to NULL so the following lines are also valid. */
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
/* Is the co-routine waiting on an event also? */
if( pxCRCB->xEventListItem.pxContainer )
{
( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
}
}
portENABLE_INTERRUPTS();
prvAddCoRoutineToReadyQueue( pxCRCB );
}
}
xLastTickCount = xCoRoutineTickCount;
}
/*-----------------------------------------------------------*/
void vCoRoutineSchedule( void )
{
/* Only run a co-routine after prvInitialiseCoRoutineLists() has been
* called. prvInitialiseCoRoutineLists() is called automatically when a
* co-routine is created. */
if( pxDelayedCoRoutineList != NULL )
{
/* See if any co-routines readied by events need moving to the ready lists. */
prvCheckPendingReadyList();
/* See if any delayed co-routines have timed out. */
prvCheckDelayedList();
/* Find the highest priority queue that contains ready co-routines. */
while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
{
if( uxTopCoRoutineReadyPriority == 0 )
{
/* No more co-routines to check. */
return;
}
--uxTopCoRoutineReadyPriority;
}
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
* of the same priority get an equal share of the processor time. */
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
/* Call the co-routine. */
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
}
}
/*-----------------------------------------------------------*/
static void prvInitialiseCoRoutineLists( void )
{
UBaseType_t uxPriority;
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
{
vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
}
vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
/* Start with pxDelayedCoRoutineList using list1 and the
* pxOverflowDelayedCoRoutineList using list2. */
pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
}
/*-----------------------------------------------------------*/
BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList )
{
CRCB_t * pxUnblockedCRCB;
BaseType_t xReturn;
/* This function is called from within an interrupt. It can only access
* event lists and the pending ready list. This function assumes that a
* check has already been made to ensure pxEventList is not empty. */
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
return xReturn;
}
#endif /* configUSE_CO_ROUTINES == 0 */

View File

@@ -0,0 +1,784 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Standard includes. */
#include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
* all the API functions to use the MPU wrappers. That should only be done when
* task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "event_groups.h"
/* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
* for the header files above, but not in this file, in order to generate the
* correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
/* The following bit fields convey control information in a task's event list
* item value. It is important they don't clash with the
* taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
#if configUSE_16_BIT_TICKS == 1
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
#define eventWAIT_FOR_ALL_BITS 0x0400U
#define eventEVENT_BITS_CONTROL_BYTES 0xff00U
#else
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
#define eventWAIT_FOR_ALL_BITS 0x04000000UL
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
#endif
typedef struct EventGroupDef_t
{
EventBits_t uxEventBits;
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupNumber;
#endif
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
#endif
} EventGroup_t;
/*-----------------------------------------------------------*/
/*
* Test the bits set in uxCurrentEventBits to see if the wait condition is met.
* The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
* pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
* are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
* wait condition is met if any of the bits set in uxBitsToWait for are also set
* in uxCurrentEventBits.
*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
{
EventGroup_t * pxEventBits;
/* A StaticEventGroup_t object must be provided. */
configASSERT( pxEventGroupBuffer );
#if ( configASSERT_DEFINED == 1 )
{
/* Sanity check that the size of the structure used to declare a
* variable of type StaticEventGroup_t equals the size of the real
* event group structure. */
volatile size_t xSize = sizeof( StaticEventGroup_t );
configASSERT( xSize == sizeof( EventGroup_t ) );
} /*lint !e529 xSize is referenced if configASSERT() is defined. */
#endif /* configASSERT_DEFINED */
/* The user has provided a statically allocated event group - use it. */
pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 !e9087 EventGroup_t and StaticEventGroup_t are deliberately aliased for data hiding purposes and guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
if( pxEventBits != NULL )
{
pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{
/* Both static and dynamic allocation can be used, so note that
* this event group was created statically in case the event group
* is later deleted. */
pxEventBits->ucStaticallyAllocated = pdTRUE;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
traceEVENT_GROUP_CREATE( pxEventBits );
}
else
{
/* xEventGroupCreateStatic should only ever be called with
* pxEventGroupBuffer pointing to a pre-allocated (compile time
* allocated) StaticEventGroup_t variable. */
traceEVENT_GROUP_CREATE_FAILED();
}
return pxEventBits;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreate( void )
{
EventGroup_t * pxEventBits;
/* Allocate the event group. Justification for MISRA deviation as
* follows: pvPortMalloc() always ensures returned memory blocks are
* aligned per the requirements of the MCU stack. In this case
* pvPortMalloc() must return a pointer that is guaranteed to meet the
* alignment requirements of the EventGroup_t structure - which (if you
* follow it through) is the alignment requirements of the TickType_t type
* (EventBits_t being of TickType_t itself). Therefore, whenever the
* stack alignment requirements are greater than or equal to the
* TickType_t alignment requirements the cast is safe. In other cases,
* where the natural word size of the architecture is less than
* sizeof( TickType_t ), the TickType_t variables will be accessed in two
* or more reads operations, and the alignment requirements is only that
* of each individual read. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
if( pxEventBits != NULL )
{
pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
{
/* Both static and dynamic allocation can be used, so note this
* event group was allocated statically in case the event group is
* later deleted. */
pxEventBits->ucStaticallyAllocated = pdFALSE;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
traceEVENT_GROUP_CREATE( pxEventBits );
}
else
{
traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */
}
return pxEventBits;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait )
{
EventBits_t uxOriginalBitValue, uxReturn;
EventGroup_t * pxEventBits = xEventGroup;
BaseType_t xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE;
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
vTaskSuspendAll();
{
uxOriginalBitValue = pxEventBits->uxEventBits;
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
/* All the rendezvous bits are now set - no need to block. */
uxReturn = ( uxOriginalBitValue | uxBitsToSet );
/* Rendezvous always clear the bits. They will have been cleared
* already unless this is the only task in the rendezvous. */
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
xTicksToWait = 0;
}
else
{
if( xTicksToWait != ( TickType_t ) 0 )
{
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
/* Store the bits that the calling task is waiting for in the
* task's event list item so the kernel knows when a match is
* found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
/* This assignment is obsolete as uxReturn will get set after
* the task unblocks, but some compilers mistakenly generate a
* warning about uxReturn being returned without being set if the
* assignment is omitted. */
uxReturn = 0;
}
else
{
/* The rendezvous bits were not set, but no block time was
* specified - just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
xTimeoutOccurred = pdTRUE;
}
}
}
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
{
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* The task blocked to wait for its required bits to be set - at this
* point either the required bits were set or the block time expired. If
* the required bits were set they will have been stored in the task's
* event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
/* The task timed out, just return the current event bit value. */
taskENTER_CRITICAL();
{
uxReturn = pxEventBits->uxEventBits;
/* Although the task got here because it timed out before the
* bits it was waiting for were set, it is possible that since it
* unblocked another task has set the bits. If this is the case
* then it needs to clear the bits before exiting. */
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
xTimeoutOccurred = pdTRUE;
}
else
{
/* The task unblocked because the bits were set. */
}
/* Control bits might be set as the task had blocked should not be
* returned. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
}
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
/* Prevent compiler warnings when trace macros are not used. */
( void ) xTimeoutOccurred;
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait )
{
EventGroup_t * pxEventBits = xEventGroup;
EventBits_t uxReturn, uxControlBits = 0;
BaseType_t xWaitConditionMet, xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE;
/* Check the user is not attempting to wait on the bits used by the kernel
* itself, and that at least one bit is being requested. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
vTaskSuspendAll();
{
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
/* Check to see if the wait condition is already met or not. */
xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
if( xWaitConditionMet != pdFALSE )
{
/* The wait condition has already been met so there is no need to
* block. */
uxReturn = uxCurrentEventBits;
xTicksToWait = ( TickType_t ) 0;
/* Clear the wait bits if requested to do so. */
if( xClearOnExit != pdFALSE )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else if( xTicksToWait == ( TickType_t ) 0 )
{
/* The wait condition has not been met, but no block time was
* specified, so just return the current value. */
uxReturn = uxCurrentEventBits;
xTimeoutOccurred = pdTRUE;
}
else
{
/* The task is going to block to wait for its required bits to be
* set. uxControlBits are used to remember the specified behaviour of
* this call to xEventGroupWaitBits() - for use when the event bits
* unblock the task. */
if( xClearOnExit != pdFALSE )
{
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
if( xWaitForAllBits != pdFALSE )
{
uxControlBits |= eventWAIT_FOR_ALL_BITS;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Store the bits that the calling task is waiting for in the
* task's event list item so the kernel knows when a match is
* found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
/* This is obsolete as it will get set after the task unblocks, but
* some compilers mistakenly generate a warning about the variable
* being returned without being set if it is not done. */
uxReturn = 0;
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
}
}
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
{
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* The task blocked to wait for its required bits to be set - at this
* point either the required bits were set or the block time expired. If
* the required bits were set they will have been stored in the task's
* event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
taskENTER_CRITICAL();
{
/* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
/* It is possible that the event bits were updated between this
* task leaving the Blocked state and running again. */
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
{
if( xClearOnExit != pdFALSE )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
xTimeoutOccurred = pdTRUE;
}
taskEXIT_CRITICAL();
}
else
{
/* The task unblocked because the bits were set. */
}
/* The task blocked so control bits may have been set. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
}
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
/* Prevent compiler warnings when trace macros are not used. */
( void ) xTimeoutOccurred;
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear )
{
EventGroup_t * pxEventBits = xEventGroup;
EventBits_t uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel
* itself. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
taskENTER_CRITICAL();
{
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
/* The value returned is the event group value prior to the bits being
* cleared. */
uxReturn = pxEventBits->uxEventBits;
/* Clear the bits. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
taskEXIT_CRITICAL();
return uxReturn;
}
/*-----------------------------------------------------------*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear )
{
BaseType_t xReturn;
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
return xReturn;
}
#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
{
UBaseType_t uxSavedInterruptStatus;
EventGroup_t const * const pxEventBits = xEventGroup;
EventBits_t uxReturn;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
uxReturn = pxEventBits->uxEventBits;
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return uxReturn;
} /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
/*-----------------------------------------------------------*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet )
{
ListItem_t * pxListItem, * pxNext;
ListItem_t const * pxListEnd;
List_t const * pxList;
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
EventGroup_t * pxEventBits = xEventGroup;
BaseType_t xMatchFound = pdFALSE;
/* Check the user is not attempting to set the bits used by the kernel
* itself. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
pxList = &( pxEventBits->xTasksWaitingForBits );
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
vTaskSuspendAll();
{
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
pxListItem = listGET_HEAD_ENTRY( pxList );
/* Set the bits. */
pxEventBits->uxEventBits |= uxBitsToSet;
/* See if the new bit value should unblock any tasks. */
while( pxListItem != pxListEnd )
{
pxNext = listGET_NEXT( pxListItem );
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
xMatchFound = pdFALSE;
/* Split the bits waited for from the control bits. */
uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
{
/* Just looking for single bit being set. */
if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
{
xMatchFound = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
{
/* All bits are set. */
xMatchFound = pdTRUE;
}
else
{
/* Need all bits to be set, but not all the bits were set. */
}
if( xMatchFound != pdFALSE )
{
/* The bits match. Should the bits be cleared on exit? */
if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
{
uxBitsToClear |= uxBitsWaitedFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Store the actual event flag value in the task's event list
* item before removing the task from the event list. The
* eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
* that is was unblocked due to its required bits matching, rather
* than because it timed out. */
vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
}
/* Move onto the next list item. Note pxListItem->pxNext is not
* used here as the list item may have been removed from the event list
* and inserted into the ready/pending reading list. */
pxListItem = pxNext;
}
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
* bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
( void ) xTaskResumeAll();
return pxEventBits->uxEventBits;
}
/*-----------------------------------------------------------*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
{
EventGroup_t * pxEventBits = xEventGroup;
const List_t * pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
vTaskSuspendAll();
{
traceEVENT_GROUP_DELETE( xEventGroup );
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
{
/* Unblock the task, returning 0 as the event list is being deleted
* and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
}
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
{
/* The event group can only have been allocated dynamically - free
* it again. */
vPortFree( pxEventBits );
}
#elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
{
/* The event group could have been allocated statically or
* dynamically, so check before attempting to free the memory. */
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
{
vPortFree( pxEventBits );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
( void ) xTaskResumeAll();
}
/*-----------------------------------------------------------*/
/* For internal use only - execute a 'set bits' command that was pended from
* an interrupt. */
void vEventGroupSetBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToSet )
{
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
}
/*-----------------------------------------------------------*/
/* For internal use only - execute a 'clear bits' command that was pended from
* an interrupt. */
void vEventGroupClearBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToClear )
{
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
}
/*-----------------------------------------------------------*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xWaitForAllBits )
{
BaseType_t xWaitConditionMet = pdFALSE;
if( xWaitForAllBits == pdFALSE )
{
/* Task only has to wait for one bit within uxBitsToWaitFor to be
* set. Is one already set? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
{
xWaitConditionMet = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* Task has to wait for all the bits in uxBitsToWaitFor to be set.
* Are they set already? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
xWaitConditionMet = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
return xWaitConditionMet;
}
/*-----------------------------------------------------------*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t * pxHigherPriorityTaskWoken )
{
BaseType_t xReturn;
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
return xReturn;
}
#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
{
UBaseType_t xReturn;
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
if( xEventGroup == NULL )
{
xReturn = 0;
}
else
{
xReturn = pxEventBits->uxEventGroupNumber;
}
return xReturn;
}
#endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
void vEventGroupSetNumber( void * xEventGroup,
UBaseType_t uxEventGroupNumber )
{
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
}
#endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef _MSC_VER /* Visual Studio doesn't support #warning. */
#warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in future released.
#endif
#include "stack_macros.h"

View File

@@ -0,0 +1,432 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/**
* @file atomic.h
* @brief FreeRTOS atomic operation support.
*
* This file implements atomic functions by disabling interrupts globally.
* Implementations with architecture specific atomic instructions can be
* provided under each compiler directory.
*/
#ifndef ATOMIC_H
#define ATOMIC_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include atomic.h"
#endif
/* Standard includes. */
#include <stdint.h>
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/*
* Port specific definitions -- entering/exiting critical section.
* Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h
*
* Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with
* ATOMIC_ENTER_CRITICAL().
*
*/
#if defined( portSET_INTERRUPT_MASK_FROM_ISR )
/* Nested interrupt scheme is supported in this port. */
#define ATOMIC_ENTER_CRITICAL() \
UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR()
#define ATOMIC_EXIT_CRITICAL() \
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType )
#else
/* Nested interrupt scheme is NOT supported in this port. */
#define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL()
#define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL()
#endif /* portSET_INTERRUPT_MASK_FROM_ISR() */
/*
* Port specific definition -- "always inline".
* Inline is compiler specific, and may not always get inlined depending on your
* optimization level. Also, inline is considered as performance optimization
* for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h,
* instead of resulting error, simply define it away.
*/
#ifndef portFORCE_INLINE
#define portFORCE_INLINE
#endif
#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */
#define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */
/*----------------------------- Swap && CAS ------------------------------*/
/**
* Atomic compare-and-swap
*
* @brief Performs an atomic compare-and-swap operation on the specified values.
*
* @param[in, out] pulDestination Pointer to memory location from where value is
* to be loaded and checked.
* @param[in] ulExchange If condition meets, write this value to memory.
* @param[in] ulComparand Swap condition.
*
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
*
* @note This function only swaps *pulDestination with ulExchange, if previous
* *pulDestination value equals ulComparand.
*/
static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination,
uint32_t ulExchange,
uint32_t ulComparand )
{
uint32_t ulReturnValue;
ATOMIC_ENTER_CRITICAL();
{
if( *pulDestination == ulComparand )
{
*pulDestination = ulExchange;
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
}
else
{
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
}
}
ATOMIC_EXIT_CRITICAL();
return ulReturnValue;
}
/*-----------------------------------------------------------*/
/**
* Atomic swap (pointers)
*
* @brief Atomically sets the address pointed to by *ppvDestination to the value
* of *pvExchange.
*
* @param[in, out] ppvDestination Pointer to memory location from where a pointer
* value is to be loaded and written back to.
* @param[in] pvExchange Pointer value to be written to *ppvDestination.
*
* @return The initial value of *ppvDestination.
*/
static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination,
void * pvExchange )
{
void * pReturnValue;
ATOMIC_ENTER_CRITICAL();
{
pReturnValue = *ppvDestination;
*ppvDestination = pvExchange;
}
ATOMIC_EXIT_CRITICAL();
return pReturnValue;
}
/*-----------------------------------------------------------*/
/**
* Atomic compare-and-swap (pointers)
*
* @brief Performs an atomic compare-and-swap operation on the specified pointer
* values.
*
* @param[in, out] ppvDestination Pointer to memory location from where a pointer
* value is to be loaded and checked.
* @param[in] pvExchange If condition meets, write this value to memory.
* @param[in] pvComparand Swap condition.
*
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
*
* @note This function only swaps *ppvDestination with pvExchange, if previous
* *ppvDestination value equals pvComparand.
*/
static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination,
void * pvExchange,
void * pvComparand )
{
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
ATOMIC_ENTER_CRITICAL();
{
if( *ppvDestination == pvComparand )
{
*ppvDestination = pvExchange;
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
}
}
ATOMIC_EXIT_CRITICAL();
return ulReturnValue;
}
/*----------------------------- Arithmetic ------------------------------*/
/**
* Atomic add
*
* @brief Atomically adds count to the value of the specified pointer points to.
*
* @param[in,out] pulAddend Pointer to memory location from where value is to be
* loaded and written back to.
* @param[in] ulCount Value to be added to *pulAddend.
*
* @return previous *pulAddend value.
*/
static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
uint32_t ulCount )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
{
ulCurrent = *pulAddend;
*pulAddend += ulCount;
}
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/*-----------------------------------------------------------*/
/**
* Atomic subtract
*
* @brief Atomically subtracts count from the value of the specified pointer
* pointers to.
*
* @param[in,out] pulAddend Pointer to memory location from where value is to be
* loaded and written back to.
* @param[in] ulCount Value to be subtract from *pulAddend.
*
* @return previous *pulAddend value.
*/
static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend,
uint32_t ulCount )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
{
ulCurrent = *pulAddend;
*pulAddend -= ulCount;
}
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/*-----------------------------------------------------------*/
/**
* Atomic increment
*
* @brief Atomically increments the value of the specified pointer points to.
*
* @param[in,out] pulAddend Pointer to memory location from where value is to be
* loaded and written back to.
*
* @return *pulAddend value before increment.
*/
static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
{
ulCurrent = *pulAddend;
*pulAddend += 1;
}
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/*-----------------------------------------------------------*/
/**
* Atomic decrement
*
* @brief Atomically decrements the value of the specified pointer points to
*
* @param[in,out] pulAddend Pointer to memory location from where value is to be
* loaded and written back to.
*
* @return *pulAddend value before decrement.
*/
static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
{
ulCurrent = *pulAddend;
*pulAddend -= 1;
}
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/*----------------------------- Bitwise Logical ------------------------------*/
/**
* Atomic OR
*
* @brief Performs an atomic OR operation on the specified values.
*
* @param [in, out] pulDestination Pointer to memory location from where value is
* to be loaded and written back to.
* @param [in] ulValue Value to be ORed with *pulDestination.
*
* @return The original value of *pulDestination.
*/
static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination,
uint32_t ulValue )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
{
ulCurrent = *pulDestination;
*pulDestination |= ulValue;
}
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/*-----------------------------------------------------------*/
/**
* Atomic AND
*
* @brief Performs an atomic AND operation on the specified values.
*
* @param [in, out] pulDestination Pointer to memory location from where value is
* to be loaded and written back to.
* @param [in] ulValue Value to be ANDed with *pulDestination.
*
* @return The original value of *pulDestination.
*/
static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination,
uint32_t ulValue )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
{
ulCurrent = *pulDestination;
*pulDestination &= ulValue;
}
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/*-----------------------------------------------------------*/
/**
* Atomic NAND
*
* @brief Performs an atomic NAND operation on the specified values.
*
* @param [in, out] pulDestination Pointer to memory location from where value is
* to be loaded and written back to.
* @param [in] ulValue Value to be NANDed with *pulDestination.
*
* @return The original value of *pulDestination.
*/
static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination,
uint32_t ulValue )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
{
ulCurrent = *pulDestination;
*pulDestination = ~( ulCurrent & ulValue );
}
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/*-----------------------------------------------------------*/
/**
* Atomic XOR
*
* @brief Performs an atomic XOR operation on the specified values.
*
* @param [in, out] pulDestination Pointer to memory location from where value is
* to be loaded and written back to.
* @param [in] ulValue Value to be XORed with *pulDestination.
*
* @return The original value of *pulDestination.
*/
static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination,
uint32_t ulValue )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
{
ulCurrent = *pulDestination;
*pulDestination ^= ulValue;
}
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ATOMIC_H */

View File

@@ -0,0 +1,764 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef CO_ROUTINE_H
#define CO_ROUTINE_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include croutine.h"
#endif
#include "list.h"
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Used to hide the implementation of the co-routine control block. The
* control block structure however has to be included in the header due to
* the macro implementation of the co-routine functionality. */
typedef void * CoRoutineHandle_t;
/* Defines the prototype to which co-routine functions must conform. */
typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t,
UBaseType_t );
typedef struct corCoRoutineControlBlock
{
crCOROUTINE_CODE pxCoRoutineFunction;
ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */
ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */
UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */
UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
uint16_t uxState; /*< Used internally by the co-routine implementation. */
} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
/**
* croutine. h
* <pre>
* BaseType_t xCoRoutineCreate(
* crCOROUTINE_CODE pxCoRoutineCode,
* UBaseType_t uxPriority,
* UBaseType_t uxIndex
* );
* </pre>
*
* Create a new co-routine and add it to the list of co-routines that are
* ready to run.
*
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
* functions require special syntax - see the co-routine section of the WEB
* documentation for more information.
*
* @param uxPriority The priority with respect to other co-routines at which
* the co-routine will run.
*
* @param uxIndex Used to distinguish between different co-routines that
* execute the same function. See the example below and the co-routine section
* of the WEB documentation for further information.
*
* @return pdPASS if the co-routine was successfully created and added to a ready
* list, otherwise an error code defined with ProjDefs.h.
*
* Example usage:
* <pre>
* // Co-routine to be created.
* void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
* {
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
* // This may not be necessary for const variables.
* static const char cLedToFlash[ 2 ] = { 5, 6 };
* static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
*
* // Must start every co-routine with a call to crSTART();
* crSTART( xHandle );
*
* for( ;; )
* {
* // This co-routine just delays for a fixed period, then toggles
* // an LED. Two co-routines are created using this function, so
* // the uxIndex parameter is used to tell the co-routine which
* // LED to flash and how int32_t to delay. This assumes xQueue has
* // already been created.
* vParTestToggleLED( cLedToFlash[ uxIndex ] );
* crDELAY( xHandle, uxFlashRates[ uxIndex ] );
* }
*
* // Must end every co-routine with a call to crEND();
* crEND();
* }
*
* // Function that creates two co-routines.
* void vOtherFunction( void )
* {
* uint8_t ucParameterToPass;
* TaskHandle_t xHandle;
*
* // Create two co-routines at priority 0. The first is given index 0
* // so (from the code above) toggles LED 5 every 200 ticks. The second
* // is given index 1 so toggles LED 6 every 400 ticks.
* for( uxIndex = 0; uxIndex < 2; uxIndex++ )
* {
* xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
* }
* }
* </pre>
* \defgroup xCoRoutineCreate xCoRoutineCreate
* \ingroup Tasks
*/
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
UBaseType_t uxPriority,
UBaseType_t uxIndex );
/**
* croutine. h
* <pre>
* void vCoRoutineSchedule( void );
* </pre>
*
* Run a co-routine.
*
* vCoRoutineSchedule() executes the highest priority co-routine that is able
* to run. The co-routine will execute until it either blocks, yields or is
* preempted by a task. Co-routines execute cooperatively so one
* co-routine cannot be preempted by another, but can be preempted by a task.
*
* If an application comprises of both tasks and co-routines then
* vCoRoutineSchedule should be called from the idle task (in an idle task
* hook).
*
* Example usage:
* <pre>
* // This idle task hook will schedule a co-routine each time it is called.
* // The rest of the idle task will execute between co-routine calls.
* void vApplicationIdleHook( void )
* {
* vCoRoutineSchedule();
* }
*
* // Alternatively, if you do not require any other part of the idle task to
* // execute, the idle task hook can call vCoRoutineSchedule() within an
* // infinite loop.
* void vApplicationIdleHook( void )
* {
* for( ;; )
* {
* vCoRoutineSchedule();
* }
* }
* </pre>
* \defgroup vCoRoutineSchedule vCoRoutineSchedule
* \ingroup Tasks
*/
void vCoRoutineSchedule( void );
/**
* croutine. h
* <pre>
* crSTART( CoRoutineHandle_t xHandle );
* </pre>
*
* This macro MUST always be called at the start of a co-routine function.
*
* Example usage:
* <pre>
* // Co-routine to be created.
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
* {
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
* static int32_t ulAVariable;
*
* // Must start every co-routine with a call to crSTART();
* crSTART( xHandle );
*
* for( ;; )
* {
* // Co-routine functionality goes here.
* }
*
* // Must end every co-routine with a call to crEND();
* crEND();
* }
* </pre>
* \defgroup crSTART crSTART
* \ingroup Tasks
*/
#define crSTART( pxCRCB ) \
switch( ( ( CRCB_t * ) ( pxCRCB ) )->uxState ) { \
case 0:
/**
* croutine. h
* <pre>
* crEND();
* </pre>
*
* This macro MUST always be called at the end of a co-routine function.
*
* Example usage:
* <pre>
* // Co-routine to be created.
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
* {
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
* static int32_t ulAVariable;
*
* // Must start every co-routine with a call to crSTART();
* crSTART( xHandle );
*
* for( ;; )
* {
* // Co-routine functionality goes here.
* }
*
* // Must end every co-routine with a call to crEND();
* crEND();
* }
* </pre>
* \defgroup crSTART crSTART
* \ingroup Tasks
*/
#define crEND() }
/*
* These macros are intended for internal use by the co-routine implementation
* only. The macros should not be used directly by application writers.
*/
#define crSET_STATE0( xHandle ) \
( ( CRCB_t * ) ( xHandle ) )->uxState = ( __LINE__ * 2 ); return; \
case ( __LINE__ * 2 ):
#define crSET_STATE1( xHandle ) \
( ( CRCB_t * ) ( xHandle ) )->uxState = ( ( __LINE__ * 2 ) + 1 ); return; \
case ( ( __LINE__ * 2 ) + 1 ):
/**
* croutine. h
* <pre>
* crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
* </pre>
*
* Delay a co-routine for a fixed period of time.
*
* crDELAY can only be called from the co-routine function itself - not
* from within a function called by the co-routine function. This is because
* co-routines do not maintain their own stack.
*
* @param xHandle The handle of the co-routine to delay. This is the xHandle
* parameter of the co-routine function.
*
* @param xTickToDelay The number of ticks that the co-routine should delay
* for. The actual amount of time this equates to is defined by
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
* can be used to convert ticks to milliseconds.
*
* Example usage:
* <pre>
* // Co-routine to be created.
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
* {
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
* // This may not be necessary for const variables.
* // We are to delay for 200ms.
* static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
*
* // Must start every co-routine with a call to crSTART();
* crSTART( xHandle );
*
* for( ;; )
* {
* // Delay for 200ms.
* crDELAY( xHandle, xDelayTime );
*
* // Do something here.
* }
*
* // Must end every co-routine with a call to crEND();
* crEND();
* }
* </pre>
* \defgroup crDELAY crDELAY
* \ingroup Tasks
*/
#define crDELAY( xHandle, xTicksToDelay ) \
if( ( xTicksToDelay ) > 0 ) \
{ \
vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
} \
crSET_STATE0( ( xHandle ) );
/**
* <pre>
* crQUEUE_SEND(
* CoRoutineHandle_t xHandle,
* QueueHandle_t pxQueue,
* void *pvItemToQueue,
* TickType_t xTicksToWait,
* BaseType_t *pxResult
* )
* </pre>
*
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
*
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
* xQueueSend() and xQueueReceive() can only be used from tasks.
*
* crQUEUE_SEND can only be called from the co-routine function itself - not
* from within a function called by the co-routine function. This is because
* co-routines do not maintain their own stack.
*
* See the co-routine section of the WEB documentation for information on
* passing data between tasks and co-routines and between ISR's and
* co-routines.
*
* @param xHandle The handle of the calling co-routine. This is the xHandle
* parameter of the co-routine function.
*
* @param pxQueue The handle of the queue on which the data will be posted.
* The handle is obtained as the return value when the queue is created using
* the xQueueCreate() API function.
*
* @param pvItemToQueue A pointer to the data being posted onto the queue.
* The number of bytes of each queued item is specified when the queue is
* created. This number of bytes is copied from pvItemToQueue into the queue
* itself.
*
* @param xTickToDelay The number of ticks that the co-routine should block
* to wait for space to become available on the queue, should space not be
* available immediately. The actual amount of time this equates to is defined
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
* below).
*
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
* data was successfully posted onto the queue, otherwise it will be set to an
* error defined within ProjDefs.h.
*
* Example usage:
* <pre>
* // Co-routine function that blocks for a fixed period then posts a number onto
* // a queue.
* static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
* {
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
* static BaseType_t xNumberToPost = 0;
* static BaseType_t xResult;
*
* // Co-routines must begin with a call to crSTART().
* crSTART( xHandle );
*
* for( ;; )
* {
* // This assumes the queue has already been created.
* crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
*
* if( xResult != pdPASS )
* {
* // The message was not posted!
* }
*
* // Increment the number to be posted onto the queue.
* xNumberToPost++;
*
* // Delay for 100 ticks.
* crDELAY( xHandle, 100 );
* }
*
* // Co-routines must end with a call to crEND().
* crEND();
* }
* </pre>
* \defgroup crQUEUE_SEND crQUEUE_SEND
* \ingroup Tasks
*/
#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
{ \
*( pxResult ) = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), ( xTicksToWait ) ); \
if( *( pxResult ) == errQUEUE_BLOCKED ) \
{ \
crSET_STATE0( ( xHandle ) ); \
*pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \
} \
if( *pxResult == errQUEUE_YIELD ) \
{ \
crSET_STATE1( ( xHandle ) ); \
*pxResult = pdPASS; \
} \
}
/**
* croutine. h
* <pre>
* crQUEUE_RECEIVE(
* CoRoutineHandle_t xHandle,
* QueueHandle_t pxQueue,
* void *pvBuffer,
* TickType_t xTicksToWait,
* BaseType_t *pxResult
* )
* </pre>
*
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
*
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
* xQueueSend() and xQueueReceive() can only be used from tasks.
*
* crQUEUE_RECEIVE can only be called from the co-routine function itself - not
* from within a function called by the co-routine function. This is because
* co-routines do not maintain their own stack.
*
* See the co-routine section of the WEB documentation for information on
* passing data between tasks and co-routines and between ISR's and
* co-routines.
*
* @param xHandle The handle of the calling co-routine. This is the xHandle
* parameter of the co-routine function.
*
* @param pxQueue The handle of the queue from which the data will be received.
* The handle is obtained as the return value when the queue is created using
* the xQueueCreate() API function.
*
* @param pvBuffer The buffer into which the received item is to be copied.
* The number of bytes of each queued item is specified when the queue is
* created. This number of bytes is copied into pvBuffer.
*
* @param xTickToDelay The number of ticks that the co-routine should block
* to wait for data to become available from the queue, should data not be
* available immediately. The actual amount of time this equates to is defined
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
* crQUEUE_SEND example).
*
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
* data was successfully retrieved from the queue, otherwise it will be set to
* an error code as defined within ProjDefs.h.
*
* Example usage:
* <pre>
* // A co-routine receives the number of an LED to flash from a queue. It
* // blocks on the queue until the number is received.
* static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
* {
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
* static BaseType_t xResult;
* static UBaseType_t uxLEDToFlash;
*
* // All co-routines must start with a call to crSTART().
* crSTART( xHandle );
*
* for( ;; )
* {
* // Wait for data to become available on the queue.
* crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
*
* if( xResult == pdPASS )
* {
* // We received the LED to flash - flash it!
* vParTestToggleLED( uxLEDToFlash );
* }
* }
*
* crEND();
* }
* </pre>
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
* \ingroup Tasks
*/
#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
{ \
*( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), ( xTicksToWait ) ); \
if( *( pxResult ) == errQUEUE_BLOCKED ) \
{ \
crSET_STATE0( ( xHandle ) ); \
*( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), 0 ); \
} \
if( *( pxResult ) == errQUEUE_YIELD ) \
{ \
crSET_STATE1( ( xHandle ) ); \
*( pxResult ) = pdPASS; \
} \
}
/**
* croutine. h
* <pre>
* crQUEUE_SEND_FROM_ISR(
* QueueHandle_t pxQueue,
* void *pvItemToQueue,
* BaseType_t xCoRoutinePreviouslyWoken
* )
* </pre>
*
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
* functions used by tasks.
*
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
* xQueueReceiveFromISR() can only be used to pass data between a task and and
* ISR.
*
* crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
* that is being used from within a co-routine.
*
* See the co-routine section of the WEB documentation for information on
* passing data between tasks and co-routines and between ISR's and
* co-routines.
*
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
* queue. The size of the items the queue will hold was defined when the
* queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
* @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
* the same queue multiple times from a single interrupt. The first call
* should always pass in pdFALSE. Subsequent calls should pass in
* the value returned from the previous call.
*
* @return pdTRUE if a co-routine was woken by posting onto the queue. This is
* used by the ISR to determine if a context switch may be required following
* the ISR.
*
* Example usage:
* <pre>
* // A co-routine that blocks on a queue waiting for characters to be received.
* static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
* {
* char cRxedChar;
* BaseType_t xResult;
*
* // All co-routines must start with a call to crSTART().
* crSTART( xHandle );
*
* for( ;; )
* {
* // Wait for data to become available on the queue. This assumes the
* // queue xCommsRxQueue has already been created!
* crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
*
* // Was a character received?
* if( xResult == pdPASS )
* {
* // Process the character here.
* }
* }
*
* // All co-routines must end with a call to crEND().
* crEND();
* }
*
* // An ISR that uses a queue to send characters received on a serial port to
* // a co-routine.
* void vUART_ISR( void )
* {
* char cRxedChar;
* BaseType_t xCRWokenByPost = pdFALSE;
*
* // We loop around reading characters until there are none left in the UART.
* while( UART_RX_REG_NOT_EMPTY() )
* {
* // Obtain the character from the UART.
* cRxedChar = UART_RX_REG;
*
* // Post the character onto a queue. xCRWokenByPost will be pdFALSE
* // the first time around the loop. If the post causes a co-routine
* // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
* // In this manner we can ensure that if more than one co-routine is
* // blocked on the queue only one is woken by this ISR no matter how
* // many characters are posted to the queue.
* xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
* }
* }
* </pre>
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
* \ingroup Tasks
*/
#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) \
xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
/**
* croutine. h
* <pre>
* crQUEUE_SEND_FROM_ISR(
* QueueHandle_t pxQueue,
* void *pvBuffer,
* BaseType_t * pxCoRoutineWoken
* )
* </pre>
*
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
* functions used by tasks.
*
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
* xQueueReceiveFromISR() can only be used to pass data between a task and and
* ISR.
*
* crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
* from a queue that is being used from within a co-routine (a co-routine
* posted to the queue).
*
* See the co-routine section of the WEB documentation for information on
* passing data between tasks and co-routines and between ISR's and
* co-routines.
*
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvBuffer A pointer to a buffer into which the received item will be
* placed. The size of the items the queue will hold was defined when the
* queue was created, so this many bytes will be copied from the queue into
* pvBuffer.
*
* @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
* available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
* co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
* *pxCoRoutineWoken will remain unchanged.
*
* @return pdTRUE an item was successfully received from the queue, otherwise
* pdFALSE.
*
* Example usage:
* <pre>
* // A co-routine that posts a character to a queue then blocks for a fixed
* // period. The character is incremented each time.
* static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
* {
* // cChar holds its value while this co-routine is blocked and must therefore
* // be declared static.
* static char cCharToTx = 'a';
* BaseType_t xResult;
*
* // All co-routines must start with a call to crSTART().
* crSTART( xHandle );
*
* for( ;; )
* {
* // Send the next character to the queue.
* crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
*
* if( xResult == pdPASS )
* {
* // The character was successfully posted to the queue.
* }
* else
* {
* // Could not post the character to the queue.
* }
*
* // Enable the UART Tx interrupt to cause an interrupt in this
* // hypothetical UART. The interrupt will obtain the character
* // from the queue and send it.
* ENABLE_RX_INTERRUPT();
*
* // Increment to the next character then block for a fixed period.
* // cCharToTx will maintain its value across the delay as it is
* // declared static.
* cCharToTx++;
* if( cCharToTx > 'x' )
* {
* cCharToTx = 'a';
* }
* crDELAY( 100 );
* }
*
* // All co-routines must end with a call to crEND().
* crEND();
* }
*
* // An ISR that uses a queue to receive characters to send on a UART.
* void vUART_ISR( void )
* {
* char cCharToTx;
* BaseType_t xCRWokenByPost = pdFALSE;
*
* while( UART_TX_REG_EMPTY() )
* {
* // Are there any characters in the queue waiting to be sent?
* // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
* // is woken by the post - ensuring that only a single co-routine is
* // woken no matter how many times we go around this loop.
* if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
* {
* SEND_CHARACTER( cCharToTx );
* }
* }
* }
* </pre>
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
* \ingroup Tasks
*/
#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) \
xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
/*
* This function is intended for internal use by the co-routine macros only.
* The macro nature of the co-routine implementation requires that the
* prototype appears here. The function should not be used by application
* writers.
*
* Removes the current co-routine from its ready list and places it in the
* appropriate delayed list.
*/
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
List_t * pxEventList );
/*
* This function is intended for internal use by the queue implementation only.
* The function should not be used by application writers.
*
* Removes the highest priority co-routine from the event list and places it in
* the pending ready list.
*/
BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList );
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* CO_ROUTINE_H */

View File

@@ -0,0 +1,292 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef DEPRECATED_DEFINITIONS_H
#define DEPRECATED_DEFINITIONS_H
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
* pre-processor definition was used to ensure the pre-processor found the correct
* portmacro.h file for the port being used. That scheme was deprecated in favour
* of setting the compiler's include path such that it found the correct
* portmacro.h file - removing the need for the constant and allowing the
* portmacro.h file to be located anywhere in relation to the port being used. The
* definitions below remain in the code for backward compatibility only. New
* projects should not use them. */
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
typedef void ( __interrupt __far * pxISR )();
#endif
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
typedef void ( __interrupt __far * pxISR )();
#endif
#ifdef GCC_MEGA_AVR
#include "../portable/GCC/ATMega323/portmacro.h"
#endif
#ifdef IAR_MEGA_AVR
#include "../portable/IAR/ATMega323/portmacro.h"
#endif
#ifdef MPLAB_PIC24_PORT
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif
#ifdef MPLAB_DSPIC_PORT
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif
#ifdef MPLAB_PIC18F_PORT
#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
#endif
#ifdef MPLAB_PIC32MX_PORT
#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
#endif
#ifdef _FEDPICC
#include "libFreeRTOS/Include/portmacro.h"
#endif
#ifdef SDCC_CYGNAL
#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
#endif
#ifdef GCC_ARM7
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
#endif
#ifdef GCC_ARM7_ECLIPSE
#include "portmacro.h"
#endif
#ifdef ROWLEY_LPC23xx
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
#endif
#ifdef IAR_MSP430
#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
#endif
#ifdef GCC_MSP430
#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
#endif
#ifdef ROWLEY_MSP430
#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
#endif
#ifdef ARM7_LPC21xx_KEIL_RVDS
#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
#endif
#ifdef SAM7_GCC
#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
#endif
#ifdef SAM7_IAR
#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
#endif
#ifdef SAM9XE_IAR
#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
#endif
#ifdef LPC2000_IAR
#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
#endif
#ifdef STR71X_IAR
#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
#endif
#ifdef STR75X_IAR
#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
#endif
#ifdef STR75X_GCC
#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
#endif
#ifdef STR91X_IAR
#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
#endif
#ifdef GCC_H8S
#include "../../Source/portable/GCC/H8S2329/portmacro.h"
#endif
#ifdef GCC_AT91FR40008
#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
#endif
#ifdef RVDS_ARMCM3_LM3S102
#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
#endif
#ifdef GCC_ARMCM3_LM3S102
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
#endif
#ifdef GCC_ARMCM3
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
#endif
#ifdef IAR_ARM_CM3
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
#endif
#ifdef IAR_ARMCM3_LM
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
#endif
#ifdef HCS12_CODE_WARRIOR
#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
#endif
#ifdef MICROBLAZE_GCC
#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
#endif
#ifdef TERN_EE
#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
#endif
#ifdef GCC_HCS12
#include "../../Source/portable/GCC/HCS12/portmacro.h"
#endif
#ifdef GCC_MCF5235
#include "../../Source/portable/GCC/MCF5235/portmacro.h"
#endif
#ifdef COLDFIRE_V2_GCC
#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
#endif
#ifdef COLDFIRE_V2_CODEWARRIOR
#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
#endif
#ifdef GCC_PPC405
#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
#endif
#ifdef GCC_PPC440
#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
#endif
#ifdef _16FX_SOFTUNE
#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
#endif
#ifdef BCC_INDUSTRIAL_PC_PORT
/* A short file name has to be used in place of the normal
* FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
typedef void ( __interrupt __far * pxISR )();
#endif
#ifdef BCC_FLASH_LITE_186_PORT
/* A short file name has to be used in place of the normal
* FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
typedef void ( __interrupt __far * pxISR )();
#endif
#ifdef __GNUC__
#ifdef __AVR32_AVR32A__
#include "portmacro.h"
#endif
#endif
#ifdef __ICCAVR32__
#ifdef __CORE__
#if __CORE__ == __AVR32A__
#include "portmacro.h"
#endif
#endif
#endif
#ifdef __91467D
#include "portmacro.h"
#endif
#ifdef __96340
#include "portmacro.h"
#endif
#ifdef __IAR_V850ES_Fx3__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx3__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx3_L__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx2__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Hx2__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_78K0R_Kx3__
#include "../../Source/portable/IAR/78K0R/portmacro.h"
#endif
#ifdef __IAR_78K0R_Kx3L__
#include "../../Source/portable/IAR/78K0R/portmacro.h"
#endif
#endif /* DEPRECATED_DEFINITIONS_H */

View File

@@ -0,0 +1,788 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef EVENT_GROUPS_H
#define EVENT_GROUPS_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
#endif
/* FreeRTOS includes. */
#include "timers.h"
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/**
* An event group is a collection of bits to which an application can assign a
* meaning. For example, an application may create an event group to convey
* the status of various CAN bus related events in which bit 0 might mean "A CAN
* message has been received and is ready for processing", bit 1 might mean "The
* application has queued a message that is ready for sending onto the CAN
* network", and bit 2 might mean "It is time to send a SYNC message onto the
* CAN network" etc. A task can then test the bit values to see which events
* are active, and optionally enter the Blocked state to wait for a specified
* bit or a group of specified bits to be active. To continue the CAN bus
* example, a CAN controlling task can enter the Blocked state (and therefore
* not consume any processing time) until either bit 0, bit 1 or bit 2 are
* active, at which time the bit that was actually active would inform the task
* which action it had to take (process a received message, send a message, or
* send a SYNC).
*
* The event groups implementation contains intelligence to avoid race
* conditions that would otherwise occur were an application to use a simple
* variable for the same purpose. This is particularly important with respect
* to when a bit within an event group is to be cleared, and when bits have to
* be set and then tested atomically - as is the case where event groups are
* used to create a synchronisation point between multiple tasks (a
* 'rendezvous').
*
* \defgroup EventGroup
*/
/**
* event_groups.h
*
* Type by which event groups are referenced. For example, a call to
* xEventGroupCreate() returns an EventGroupHandle_t variable that can then
* be used as a parameter to other event group functions.
*
* \defgroup EventGroupHandle_t EventGroupHandle_t
* \ingroup EventGroup
*/
struct EventGroupDef_t;
typedef struct EventGroupDef_t * EventGroupHandle_t;
/*
* The type that holds event bits always matches TickType_t - therefore the
* number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
* 32 bits if set to 0.
*
* \defgroup EventBits_t EventBits_t
* \ingroup EventGroup
*/
typedef TickType_t EventBits_t;
/**
* event_groups.h
* <pre>
* EventGroupHandle_t xEventGroupCreate( void );
* </pre>
*
* Create a new event group.
*
* Internally, within the FreeRTOS implementation, event groups use a [small]
* block of memory, in which the event group's structure is stored. If an event
* groups is created using xEventGropuCreate() then the required memory is
* automatically dynamically allocated inside the xEventGroupCreate() function.
* (see https://www.FreeRTOS.org/a00111.html). If an event group is created
* using xEventGropuCreateStatic() then the application writer must instead
* provide the memory that will get used by the event group.
* xEventGroupCreateStatic() therefore allows an event group to be created
* without using any dynamic memory allocation.
*
* Although event groups are not related to ticks, for internal implementation
* reasons the number of bits available for use in an event group is dependent
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
* event bits within an event group.
*
* @return If the event group was created then a handle to the event group is
* returned. If there was insufficient FreeRTOS heap available to create the
* event group then NULL is returned. See https://www.FreeRTOS.org/a00111.html
*
* Example usage:
* <pre>
* // Declare a variable to hold the created event group.
* EventGroupHandle_t xCreatedEventGroup;
*
* // Attempt to create the event group.
* xCreatedEventGroup = xEventGroupCreate();
*
* // Was the event group created successfully?
* if( xCreatedEventGroup == NULL )
* {
* // The event group was not created because there was insufficient
* // FreeRTOS heap available.
* }
* else
* {
* // The event group was created.
* }
* </pre>
* \defgroup xEventGroupCreate xEventGroupCreate
* \ingroup EventGroup
*/
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
#endif
/**
* event_groups.h
* <pre>
* EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
* </pre>
*
* Create a new event group.
*
* Internally, within the FreeRTOS implementation, event groups use a [small]
* block of memory, in which the event group's structure is stored. If an event
* groups is created using xEventGropuCreate() then the required memory is
* automatically dynamically allocated inside the xEventGroupCreate() function.
* (see https://www.FreeRTOS.org/a00111.html). If an event group is created
* using xEventGropuCreateStatic() then the application writer must instead
* provide the memory that will get used by the event group.
* xEventGroupCreateStatic() therefore allows an event group to be created
* without using any dynamic memory allocation.
*
* Although event groups are not related to ticks, for internal implementation
* reasons the number of bits available for use in an event group is dependent
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
* event bits within an event group.
*
* @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type
* StaticEventGroup_t, which will be then be used to hold the event group's data
* structures, removing the need for the memory to be allocated dynamically.
*
* @return If the event group was created then a handle to the event group is
* returned. If pxEventGroupBuffer was NULL then NULL is returned.
*
* Example usage:
* <pre>
* // StaticEventGroup_t is a publicly accessible structure that has the same
* // size and alignment requirements as the real event group structure. It is
* // provided as a mechanism for applications to know the size of the event
* // group (which is dependent on the architecture and configuration file
* // settings) without breaking the strict data hiding policy by exposing the
* // real event group internals. This StaticEventGroup_t variable is passed
* // into the xSemaphoreCreateEventGroupStatic() function and is used to store
* // the event group's data structures
* StaticEventGroup_t xEventGroupBuffer;
*
* // Create the event group without dynamically allocating any memory.
* xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
* </pre>
*/
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
#endif
/**
* event_groups.h
* <pre>
* EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
* const EventBits_t uxBitsToWaitFor,
* const BaseType_t xClearOnExit,
* const BaseType_t xWaitForAllBits,
* const TickType_t xTicksToWait );
* </pre>
*
* [Potentially] block to wait for one or more bits to be set within a
* previously created event group.
*
* This function cannot be called from an interrupt.
*
* @param xEventGroup The event group in which the bits are being tested. The
* event group must have previously been created using a call to
* xEventGroupCreate().
*
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
* inside the event group. For example, to wait for bit 0 and/or bit 2 set
* uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set
* uxBitsToWaitFor to 0x07. Etc.
*
* @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
* uxBitsToWaitFor that are set within the event group will be cleared before
* xEventGroupWaitBits() returns if the wait condition was met (if the function
* returns for a reason other than a timeout). If xClearOnExit is set to
* pdFALSE then the bits set in the event group are not altered when the call to
* xEventGroupWaitBits() returns.
*
* @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
* xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
* are set or the specified block time expires. If xWaitForAllBits is set to
* pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
* in uxBitsToWaitFor is set or the specified block time expires. The block
* time is specified by the xTicksToWait parameter.
*
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
* for one/all (depending on the xWaitForAllBits value) of the bits specified by
* uxBitsToWaitFor to become set.
*
* @return The value of the event group at the time either the bits being waited
* for became set, or the block time expired. Test the return value to know
* which bits were set. If xEventGroupWaitBits() returned because its timeout
* expired then not all the bits being waited for will be set. If
* xEventGroupWaitBits() returned because the bits it was waiting for were set
* then the returned value is the event group value before any bits were
* automatically cleared in the case that xClearOnExit parameter was set to
* pdTRUE.
*
* Example usage:
* <pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
*
* void aFunction( EventGroupHandle_t xEventGroup )
* {
* EventBits_t uxBits;
* const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
*
* // Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
* // the event group. Clear the bits before exiting.
* uxBits = xEventGroupWaitBits(
* xEventGroup, // The event group being tested.
* BIT_0 | BIT_4, // The bits within the event group to wait for.
* pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
* pdFALSE, // Don't wait for both bits, either bit will do.
* xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
*
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
* {
* // xEventGroupWaitBits() returned because both bits were set.
* }
* else if( ( uxBits & BIT_0 ) != 0 )
* {
* // xEventGroupWaitBits() returned because just BIT_0 was set.
* }
* else if( ( uxBits & BIT_4 ) != 0 )
* {
* // xEventGroupWaitBits() returned because just BIT_4 was set.
* }
* else
* {
* // xEventGroupWaitBits() returned because xTicksToWait ticks passed
* // without either BIT_0 or BIT_4 becoming set.
* }
* }
* </pre>
* \defgroup xEventGroupWaitBits xEventGroupWaitBits
* \ingroup EventGroup
*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
* <pre>
* EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
* </pre>
*
* Clear bits within an event group. This function cannot be called from an
* interrupt.
*
* @param xEventGroup The event group in which the bits are to be cleared.
*
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
* in the event group. For example, to clear bit 3 only, set uxBitsToClear to
* 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
*
* @return The value of the event group before the specified bits were cleared.
*
* Example usage:
* <pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
*
* void aFunction( EventGroupHandle_t xEventGroup )
* {
* EventBits_t uxBits;
*
* // Clear bit 0 and bit 4 in xEventGroup.
* uxBits = xEventGroupClearBits(
* xEventGroup, // The event group being updated.
* BIT_0 | BIT_4 );// The bits being cleared.
*
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
* {
* // Both bit 0 and bit 4 were set before xEventGroupClearBits() was
* // called. Both will now be clear (not set).
* }
* else if( ( uxBits & BIT_0 ) != 0 )
* {
* // Bit 0 was set before xEventGroupClearBits() was called. It will
* // now be clear.
* }
* else if( ( uxBits & BIT_4 ) != 0 )
* {
* // Bit 4 was set before xEventGroupClearBits() was called. It will
* // now be clear.
* }
* else
* {
* // Neither bit 0 nor bit 4 were set in the first place.
* }
* }
* </pre>
* \defgroup xEventGroupClearBits xEventGroupClearBits
* \ingroup EventGroup
*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
* <pre>
* BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
* </pre>
*
* A version of xEventGroupClearBits() that can be called from an interrupt.
*
* Setting bits in an event group is not a deterministic operation because there
* are an unknown number of tasks that may be waiting for the bit or bits being
* set. FreeRTOS does not allow nondeterministic operations to be performed
* while interrupts are disabled, so protects event groups that are accessed
* from tasks by suspending the scheduler rather than disabling interrupts. As
* a result event groups cannot be accessed directly from an interrupt service
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
* timer task to have the clear operation performed in the context of the timer
* task.
*
* @param xEventGroup The event group in which the bits are to be cleared.
*
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.
* For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
* and bit 0 set uxBitsToClear to 0x09.
*
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
* <pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
*
* // An event group which it is assumed has already been created by a call to
* // xEventGroupCreate().
* EventGroupHandle_t xEventGroup;
*
* void anInterruptHandler( void )
* {
* // Clear bit 0 and bit 4 in xEventGroup.
* xResult = xEventGroupClearBitsFromISR(
* xEventGroup, // The event group being updated.
* BIT_0 | BIT_4 ); // The bits being set.
*
* if( xResult == pdPASS )
* {
* // The message was posted successfully.
* }
* }
* </pre>
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
* \ingroup EventGroup
*/
#if ( configUSE_TRACE_FACILITY == 1 )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
#else
#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) \
xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )
#endif
/**
* event_groups.h
* <pre>
* EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
* </pre>
*
* Set bits within an event group.
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
* is a version that can be called from an interrupt.
*
* Setting bits in an event group will automatically unblock tasks that are
* blocked waiting for the bits.
*
* @param xEventGroup The event group in which the bits are to be set.
*
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
* and bit 0 set uxBitsToSet to 0x09.
*
* @return The value of the event group at the time the call to
* xEventGroupSetBits() returns. There are two reasons why the returned value
* might have the bits specified by the uxBitsToSet parameter cleared. First,
* if setting a bit results in a task that was waiting for the bit leaving the
* blocked state then it is possible the bit will be cleared automatically
* (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any
* unblocked (or otherwise Ready state) task that has a priority above that of
* the task that called xEventGroupSetBits() will execute and may change the
* event group value before the call to xEventGroupSetBits() returns.
*
* Example usage:
* <pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
*
* void aFunction( EventGroupHandle_t xEventGroup )
* {
* EventBits_t uxBits;
*
* // Set bit 0 and bit 4 in xEventGroup.
* uxBits = xEventGroupSetBits(
* xEventGroup, // The event group being updated.
* BIT_0 | BIT_4 );// The bits being set.
*
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
* {
* // Both bit 0 and bit 4 remained set when the function returned.
* }
* else if( ( uxBits & BIT_0 ) != 0 )
* {
* // Bit 0 remained set when the function returned, but bit 4 was
* // cleared. It might be that bit 4 was cleared automatically as a
* // task that was waiting for bit 4 was removed from the Blocked
* // state.
* }
* else if( ( uxBits & BIT_4 ) != 0 )
* {
* // Bit 4 remained set when the function returned, but bit 0 was
* // cleared. It might be that bit 0 was cleared automatically as a
* // task that was waiting for bit 0 was removed from the Blocked
* // state.
* }
* else
* {
* // Neither bit 0 nor bit 4 remained set. It might be that a task
* // was waiting for both of the bits to be set, and the bits were
* // cleared as the task left the Blocked state.
* }
* }
* </pre>
* \defgroup xEventGroupSetBits xEventGroupSetBits
* \ingroup EventGroup
*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
* <pre>
* BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
* </pre>
*
* A version of xEventGroupSetBits() that can be called from an interrupt.
*
* Setting bits in an event group is not a deterministic operation because there
* are an unknown number of tasks that may be waiting for the bit or bits being
* set. FreeRTOS does not allow nondeterministic operations to be performed in
* interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR()
* sends a message to the timer task to have the set operation performed in the
* context of the timer task - where a scheduler lock is used in place of a
* critical section.
*
* @param xEventGroup The event group in which the bits are to be set.
*
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
* and bit 0 set uxBitsToSet to 0x09.
*
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
* will result in a message being sent to the timer daemon task. If the
* priority of the timer daemon task is higher than the priority of the
* currently running task (the task the interrupt interrupted) then
* *pxHigherPriorityTaskWoken will be set to pdTRUE by
* xEventGroupSetBitsFromISR(), indicating that a context switch should be
* requested before the interrupt exits. For that reason
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
* example code below.
*
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
* <pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
*
* // An event group which it is assumed has already been created by a call to
* // xEventGroupCreate().
* EventGroupHandle_t xEventGroup;
*
* void anInterruptHandler( void )
* {
* BaseType_t xHigherPriorityTaskWoken, xResult;
*
* // xHigherPriorityTaskWoken must be initialised to pdFALSE.
* xHigherPriorityTaskWoken = pdFALSE;
*
* // Set bit 0 and bit 4 in xEventGroup.
* xResult = xEventGroupSetBitsFromISR(
* xEventGroup, // The event group being updated.
* BIT_0 | BIT_4 // The bits being set.
* &xHigherPriorityTaskWoken );
*
* // Was the message posted successfully?
* if( xResult == pdPASS )
* {
* // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
* // switch should be requested. The macro used is port specific and
* // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
* // refer to the documentation page for the port being used.
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
* }
* }
* </pre>
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
* \ingroup EventGroup
*/
#if ( configUSE_TRACE_FACILITY == 1 )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#else
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) \
xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
#endif
/**
* event_groups.h
* <pre>
* EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
* const EventBits_t uxBitsToSet,
* const EventBits_t uxBitsToWaitFor,
* TickType_t xTicksToWait );
* </pre>
*
* Atomically set bits within an event group, then wait for a combination of
* bits to be set within the same event group. This functionality is typically
* used to synchronise multiple tasks, where each task has to wait for the other
* tasks to reach a synchronisation point before proceeding.
*
* This function cannot be used from an interrupt.
*
* The function will return before its block time expires if the bits specified
* by the uxBitsToWait parameter are set, or become set within that time. In
* this case all the bits specified by uxBitsToWait will be automatically
* cleared before the function returns.
*
* @param xEventGroup The event group in which the bits are being tested. The
* event group must have previously been created using a call to
* xEventGroupCreate().
*
* @param uxBitsToSet The bits to set in the event group before determining
* if, and possibly waiting for, all the bits specified by the uxBitsToWait
* parameter are set.
*
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
* inside the event group. For example, to wait for bit 0 and bit 2 set
* uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set
* uxBitsToWaitFor to 0x07. Etc.
*
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
* for all of the bits specified by uxBitsToWaitFor to become set.
*
* @return The value of the event group at the time either the bits being waited
* for became set, or the block time expired. Test the return value to know
* which bits were set. If xEventGroupSync() returned because its timeout
* expired then not all the bits being waited for will be set. If
* xEventGroupSync() returned because all the bits it was waiting for were
* set then the returned value is the event group value before any bits were
* automatically cleared.
*
* Example usage:
* <pre>
* // Bits used by the three tasks.
#define TASK_0_BIT ( 1 << 0 )
#define TASK_1_BIT ( 1 << 1 )
#define TASK_2_BIT ( 1 << 2 )
*
#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
*
* // Use an event group to synchronise three tasks. It is assumed this event
* // group has already been created elsewhere.
* EventGroupHandle_t xEventBits;
*
* void vTask0( void *pvParameters )
* {
* EventBits_t uxReturn;
* TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
*
* for( ;; )
* {
* // Perform task functionality here.
*
* // Set bit 0 in the event flag to note this task has reached the
* // sync point. The other two tasks will set the other two bits defined
* // by ALL_SYNC_BITS. All three tasks have reached the synchronisation
* // point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
* // for this to happen.
* uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
*
* if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
* {
* // All three tasks reached the synchronisation point before the call
* // to xEventGroupSync() timed out.
* }
* }
* }
*
* void vTask1( void *pvParameters )
* {
* for( ;; )
* {
* // Perform task functionality here.
*
* // Set bit 1 in the event flag to note this task has reached the
* // synchronisation point. The other two tasks will set the other two
* // bits defined by ALL_SYNC_BITS. All three tasks have reached the
* // synchronisation point when all the ALL_SYNC_BITS are set. Wait
* // indefinitely for this to happen.
* xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
*
* // xEventGroupSync() was called with an indefinite block time, so
* // this task will only reach here if the synchronisation was made by all
* // three tasks, so there is no need to test the return value.
* }
* }
*
* void vTask2( void *pvParameters )
* {
* for( ;; )
* {
* // Perform task functionality here.
*
* // Set bit 2 in the event flag to note this task has reached the
* // synchronisation point. The other two tasks will set the other two
* // bits defined by ALL_SYNC_BITS. All three tasks have reached the
* // synchronisation point when all the ALL_SYNC_BITS are set. Wait
* // indefinitely for this to happen.
* xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
*
* // xEventGroupSync() was called with an indefinite block time, so
* // this task will only reach here if the synchronisation was made by all
* // three tasks, so there is no need to test the return value.
* }
* }
*
* </pre>
* \defgroup xEventGroupSync xEventGroupSync
* \ingroup EventGroup
*/
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
* <pre>
* EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
* </pre>
*
* Returns the current value of the bits in an event group. This function
* cannot be used from an interrupt.
*
* @param xEventGroup The event group being queried.
*
* @return The event group bits at the time xEventGroupGetBits() was called.
*
* \defgroup xEventGroupGetBits xEventGroupGetBits
* \ingroup EventGroup
*/
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )
/**
* event_groups.h
* <pre>
* EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
* </pre>
*
* A version of xEventGroupGetBits() that can be called from an ISR.
*
* @param xEventGroup The event group being queried.
*
* @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
*
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
* \ingroup EventGroup
*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
* <pre>
* void xEventGroupDelete( EventGroupHandle_t xEventGroup );
* </pre>
*
* Delete an event group that was previously created by a call to
* xEventGroupCreate(). Tasks that are blocked on the event group will be
* unblocked and obtain 0 as the event group's value.
*
* @param xEventGroup The event group being deleted.
*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
/* For internal use only. */
void vEventGroupSetBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
void vEventGroupClearBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) PRIVILEGED_FUNCTION;
void vEventGroupSetNumber( void * xEventGroup,
UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION;
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* EVENT_GROUPS_H */

View File

@@ -0,0 +1,430 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/*
* This is the list implementation used by the scheduler. While it is tailored
* heavily for the schedulers needs, it is also available for use by
* application code.
*
* list_ts can only store pointers to list_item_ts. Each ListItem_t contains a
* numeric value (xItemValue). Most of the time the lists are sorted in
* descending item value order.
*
* Lists are created already containing one list item. The value of this
* item is the maximum possible that can be stored, it is therefore always at
* the end of the list and acts as a marker. The list member pxHead always
* points to this marker - even though it is at the tail of the list. This
* is because the tail contains a wrap back pointer to the true head of
* the list.
*
* In addition to it's value, each list item contains a pointer to the next
* item in the list (pxNext), a pointer to the list it is in (pxContainer)
* and a pointer to back to the object that contains it. These later two
* pointers are included for efficiency of list manipulation. There is
* effectively a two way link between the object containing the list item and
* the list item itself.
*
*
* \page ListIntroduction List Implementation
* \ingroup FreeRTOSIntro
*/
#ifndef LIST_H
#define LIST_H
#ifndef INC_FREERTOS_H
#error "FreeRTOS.h must be included before list.h"
#endif
/*
* The list structure members are modified from within interrupts, and therefore
* by rights should be declared volatile. However, they are only modified in a
* functionally atomic way (within critical sections of with the scheduler
* suspended) and are either passed by reference into a function or indexed via
* a volatile variable. Therefore, in all use cases tested so far, the volatile
* qualifier can be omitted in order to provide a moderate performance
* improvement without adversely affecting functional behaviour. The assembly
* instructions generated by the IAR, ARM and GCC compilers when the respective
* compiler's options were set for maximum optimisation has been inspected and
* deemed to be as intended. That said, as compiler technology advances, and
* especially if aggressive cross module optimisation is used (a use case that
* has not been exercised to any great extend) then it is feasible that the
* volatile qualifier will be needed for correct optimisation. It is expected
* that a compiler removing essential code because, without the volatile
* qualifier on the list structure members and with aggressive cross module
* optimisation, the compiler deemed the code unnecessary will result in
* complete and obvious failure of the scheduler. If this is ever experienced
* then the volatile qualifier can be inserted in the relevant places within the
* list structures by simply defining configLIST_VOLATILE to volatile in
* FreeRTOSConfig.h (as per the example at the bottom of this comment block).
* If configLIST_VOLATILE is not defined then the preprocessor directives below
* will simply #define configLIST_VOLATILE away completely.
*
* To use volatile list structure members then add the following line to
* FreeRTOSConfig.h (without the quotes):
* "#define configLIST_VOLATILE volatile"
*/
#ifndef configLIST_VOLATILE
#define configLIST_VOLATILE
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Macros that can be used to place known values within the list structures,
* then check that the known values do not get corrupted during the execution of
* the application. These may catch the list data structures being overwritten in
* memory. They will not catch data errors caused by incorrect configuration or
* use of FreeRTOS.*/
#if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
/* Define the macros to do nothing. */
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
#define listTEST_LIST_ITEM_INTEGRITY( pxItem )
#define listTEST_LIST_INTEGRITY( pxList )
#else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */
/* Define macros that add new members into the list structures. */
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
/* Define macros that set the new structure members to known values. */
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
/* Define macros that will assert if one of the structure members does not
* contain its expected value. */
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
#define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
/*
* Definition of the only type of object that a list can contain.
*/
struct xLIST;
struct xLIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
struct xLIST * configLIST_VOLATILE pxContainer; /*< Pointer to the list in which this list item is placed (if any). */
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */
struct xMINI_LIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
configLIST_VOLATILE TickType_t xItemValue;
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
/*
* Definition of the type of queue used by the scheduler.
*/
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
volatile UBaseType_t uxNumberOfItems;
ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
} List_t;
/*
* Access macro to set the owner of a list item. The owner of a list item
* is the object (usually a TCB) that contains the list item.
*
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
* \ingroup LinkedList
*/
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
/*
* Access macro to get the owner of a list item. The owner of a list item
* is the object (usually a TCB) that contains the list item.
*
* \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
* \ingroup LinkedList
*/
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
/*
* Access macro to set the value of the list item. In most cases the value is
* used to sort the list in descending order.
*
* \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
* \ingroup LinkedList
*/
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
/*
* Access macro to retrieve the value of the list item. The value can
* represent anything - for example the priority of a task, or the time at
* which a task should be unblocked.
*
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
* \ingroup LinkedList
*/
#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
/*
* Access macro to retrieve the value of the list item at the head of a given
* list.
*
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
* \ingroup LinkedList
*/
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
/*
* Return the list item at the head of the list.
*
* \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
* \ingroup LinkedList
*/
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
/*
* Return the next list item.
*
* \page listGET_NEXT listGET_NEXT
* \ingroup LinkedList
*/
#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
/*
* Return the list item that marks the end of the list
*
* \page listGET_END_MARKER listGET_END_MARKER
* \ingroup LinkedList
*/
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
/*
* Access macro to determine if a list contains any items. The macro will
* only have the value true if the list is empty.
*
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY
* \ingroup LinkedList
*/
#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
/*
* Access macro to return the number of items in the list.
*/
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
/*
* Access function to obtain the owner of the next entry in a list.
*
* The list member pxIndex is used to walk through a list. Calling
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
* and returns that entry's pxOwner parameter. Using multiple calls to this
* function it is therefore possible to move through every item contained in
* a list.
*
* The pxOwner parameter of a list item is a pointer to the object that owns
* the list item. In the scheduler this is normally a task control block.
* The pxOwner parameter effectively creates a two way link between the list
* item and its owner.
*
* @param pxTCB pxTCB is set to the address of the owner of the next list item.
* @param pxList The list from which the next item owner is to be returned.
*
* \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
* \ingroup LinkedList
*/
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
{ \
List_t * const pxConstList = ( pxList ); \
/* Increment the index to the next item and return the item, ensuring */ \
/* we don't return the marker used at the end of the list. */ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
{ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
} \
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
}
/*
* Access function to obtain the owner of the first entry in a list. Lists
* are normally sorted in ascending item value order.
*
* This function returns the pxOwner member of the first item in the list.
* The pxOwner parameter of a list item is a pointer to the object that owns
* the list item. In the scheduler this is normally a task control block.
* The pxOwner parameter effectively creates a two way link between the list
* item and its owner.
*
* @param pxList The list from which the owner of the head item is to be
* returned.
*
* \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
* \ingroup LinkedList
*/
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner )
/*
* Check to see if a list item is within a list. The list item maintains a
* "container" pointer that points to the list it is in. All this macro does
* is check to see if the container and the list match.
*
* @param pxList The list we want to know if the list item is within.
* @param pxListItem The list item we want to know if is in the list.
* @return pdTRUE if the list item is in the list, otherwise pdFALSE.
*/
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )
/*
* Return the list a list item is contained within (referenced from).
*
* @param pxListItem The list item being queried.
* @return A pointer to the List_t object that references the pxListItem
*/
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer )
/*
* This provides a crude means of knowing if a list has been initialised, as
* pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
* function.
*/
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
/*
* Must be called before a list is used! This initialises all the members
* of the list structure and inserts the xListEnd item into the list as a
* marker to the back of the list.
*
* @param pxList Pointer to the list being initialised.
*
* \page vListInitialise vListInitialise
* \ingroup LinkedList
*/
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
/*
* Must be called before a list item is used. This sets the list container to
* null so the item does not think that it is already contained in a list.
*
* @param pxItem Pointer to the list item being initialised.
*
* \page vListInitialiseItem vListInitialiseItem
* \ingroup LinkedList
*/
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
/*
* Insert a list item into a list. The item will be inserted into the list in
* a position determined by its item value (descending item value order).
*
* @param pxList The list into which the item is to be inserted.
*
* @param pxNewListItem The item that is to be placed in the list.
*
* \page vListInsert vListInsert
* \ingroup LinkedList
*/
void vListInsert( List_t * const pxList,
ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
/*
* Insert a list item into a list. The item will be inserted in a position
* such that it will be the last item within the list returned by multiple
* calls to listGET_OWNER_OF_NEXT_ENTRY.
*
* The list member pxIndex is used to walk through a list. Calling
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
* Placing an item in a list using vListInsertEnd effectively places the item
* in the list position pointed to by pxIndex. This means that every other
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
* the pxIndex parameter again points to the item being inserted.
*
* @param pxList The list into which the item is to be inserted.
*
* @param pxNewListItem The list item to be inserted into the list.
*
* \page vListInsertEnd vListInsertEnd
* \ingroup LinkedList
*/
void vListInsertEnd( List_t * const pxList,
ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
/*
* Remove an item from a list. The list item has a pointer to the list that
* it is in, so only the list item need be passed into the function.
*
* @param uxListRemove The item to be removed. The item will remove itself from
* the list pointed to by it's pxContainer parameter.
*
* @return The number of items that remain in the list after the list item has
* been removed.
*
* \page uxListRemove uxListRemove
* \ingroup LinkedList
*/
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef LIST_H */

View File

@@ -0,0 +1,834 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/*
* Message buffers build functionality on top of FreeRTOS stream buffers.
* Whereas stream buffers are used to send a continuous stream of data from one
* task or interrupt to another, message buffers are used to send variable
* length discrete messages from one task or interrupt to another. Their
* implementation is light weight, making them particularly suited for interrupt
* to task and core to core communication scenarios.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* timeout to 0.
*
* Message buffers hold variable length messages. To enable that, when a
* message is written to the message buffer an additional sizeof( size_t ) bytes
* are also written to store the message's length (that happens internally, with
* the API function). sizeof( size_t ) is typically 4 bytes on a 32-bit
* architecture, so writing a 10 byte message to a message buffer on a 32-bit
* architecture will actually reduce the available space in the message buffer
* by 14 bytes (10 byte are used by the message, and 4 bytes to hold the length
* of the message).
*/
#ifndef FREERTOS_MESSAGE_BUFFER_H
#define FREERTOS_MESSAGE_BUFFER_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include message_buffer.h"
#endif
/* Message buffers are built onto of stream buffers. */
#include "stream_buffer.h"
/* *INDENT-OFF* */
#if defined( __cplusplus )
extern "C" {
#endif
/* *INDENT-ON* */
/**
* Type by which message buffers are referenced. For example, a call to
* xMessageBufferCreate() returns an MessageBufferHandle_t variable that can
* then be used as a parameter to xMessageBufferSend(), xMessageBufferReceive(),
* etc.
*/
typedef void * MessageBufferHandle_t;
/*-----------------------------------------------------------*/
/**
* message_buffer.h
*
* <pre>
* MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
* </pre>
*
* Creates a new message buffer using dynamically allocated memory. See
* xMessageBufferCreateStatic() for a version that uses statically allocated
* memory (memory that is allocated at compile time).
*
* configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
* FreeRTOSConfig.h for xMessageBufferCreate() to be available.
*
* @param xBufferSizeBytes The total number of bytes (not messages) the message
* buffer will be able to hold at any one time. When a message is written to
* the message buffer an additional sizeof( size_t ) bytes are also written to
* store the message's length. sizeof( size_t ) is typically 4 bytes on a
* 32-bit architecture, so on most 32-bit architectures a 10 byte message will
* take up 14 bytes of message buffer space.
*
* @return If NULL is returned, then the message buffer cannot be created
* because there is insufficient heap memory available for FreeRTOS to allocate
* the message buffer data structures and storage area. A non-NULL value being
* returned indicates that the message buffer has been created successfully -
* the returned value should be stored as the handle to the created message
* buffer.
*
* Example use:
* <pre>
*
* void vAFunction( void )
* {
* MessageBufferHandle_t xMessageBuffer;
* const size_t xMessageBufferSizeBytes = 100;
*
* // Create a message buffer that can hold 100 bytes. The memory used to hold
* // both the message buffer structure and the messages themselves is allocated
* // dynamically. Each message added to the buffer consumes an additional 4
* // bytes which are used to hold the lengh of the message.
* xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
*
* if( xMessageBuffer == NULL )
* {
* // There was not enough heap memory space available to create the
* // message buffer.
* }
* else
* {
* // The message buffer was created successfully and can now be used.
* }
*
* </pre>
* \defgroup xMessageBufferCreate xMessageBufferCreate
* \ingroup MessageBufferManagement
*/
#define xMessageBufferCreate( xBufferSizeBytes ) \
( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE )
/**
* message_buffer.h
*
* <pre>
* MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
* uint8_t *pucMessageBufferStorageArea,
* StaticMessageBuffer_t *pxStaticMessageBuffer );
* </pre>
* Creates a new message buffer using statically allocated memory. See
* xMessageBufferCreate() for a version that uses dynamically allocated memory.
*
* @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
* pucMessageBufferStorageArea parameter. When a message is written to the
* message buffer an additional sizeof( size_t ) bytes are also written to store
* the message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
* architecture, so on most 32-bit architecture a 10 byte message will take up
* 14 bytes of message buffer space. The maximum number of bytes that can be
* stored in the message buffer is actually (xBufferSizeBytes - 1).
*
* @param pucMessageBufferStorageArea Must point to a uint8_t array that is at
* least xBufferSizeBytes + 1 big. This is the array to which messages are
* copied when they are written to the message buffer.
*
* @param pxStaticMessageBuffer Must point to a variable of type
* StaticMessageBuffer_t, which will be used to hold the message buffer's data
* structure.
*
* @return If the message buffer is created successfully then a handle to the
* created message buffer is returned. If either pucMessageBufferStorageArea or
* pxStaticmessageBuffer are NULL then NULL is returned.
*
* Example use:
* <pre>
*
* // Used to dimension the array used to hold the messages. The available space
* // will actually be one less than this, so 999.
#define STORAGE_SIZE_BYTES 1000
*
* // Defines the memory that will actually hold the messages within the message
* // buffer.
* static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
*
* // The variable used to hold the message buffer structure.
* StaticMessageBuffer_t xMessageBufferStruct;
*
* void MyFunction( void )
* {
* MessageBufferHandle_t xMessageBuffer;
*
* xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucBufferStorage ),
* ucBufferStorage,
* &xMessageBufferStruct );
*
* // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
* // parameters were NULL, xMessageBuffer will not be NULL, and can be used to
* // reference the created message buffer in other message buffer API calls.
*
* // Other code that uses the message buffer can go here.
* }
*
* </pre>
* \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic
* \ingroup MessageBufferManagement
*/
#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \
( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer )
/**
* message_buffer.h
*
* <pre>
* size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
* const void *pvTxData,
* size_t xDataLengthBytes,
* TickType_t xTicksToWait );
* </pre>
*
* Sends a discrete message to the message buffer. The message can be any
* length that fits within the buffer's free space, and is copied into the
* buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xMessageBufferSend() to write to a message buffer from a task. Use
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
* service routine (ISR).
*
* @param xMessageBuffer The handle of the message buffer to which a message is
* being sent.
*
* @param pvTxData A pointer to the message that is to be copied into the
* message buffer.
*
* @param xDataLengthBytes The length of the message. That is, the number of
* bytes to copy from pvTxData into the message buffer. When a message is
* written to the message buffer an additional sizeof( size_t ) bytes are also
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
* on a 32-bit architecture, so on most 32-bit architecture setting
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
* bytes (20 bytes of message data and 4 bytes to hold the message length).
*
* @param xTicksToWait The maximum amount of time the calling task should remain
* in the Blocked state to wait for enough space to become available in the
* message buffer, should the message buffer have insufficient space when
* xMessageBufferSend() is called. The calling task will never block if
* xTicksToWait is zero. The block time is specified in tick periods, so the
* absolute time it represents is dependent on the tick frequency. The macro
* pdMS_TO_TICKS() can be used to convert a time specified in milliseconds into
* a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will cause
* the task to wait indefinitely (without timing out), provided
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
* CPU time when they are in the Blocked state.
*
* @return The number of bytes written to the message buffer. If the call to
* xMessageBufferSend() times out before there was enough space to write the
* message into the message buffer then zero is returned. If the call did not
* time out then xDataLengthBytes is returned.
*
* Example use:
* <pre>
* void vAFunction( MessageBufferHandle_t xMessageBuffer )
* {
* size_t xBytesSent;
* uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
* char *pcStringToSend = "String to send";
* const TickType_t x100ms = pdMS_TO_TICKS( 100 );
*
* // Send an array to the message buffer, blocking for a maximum of 100ms to
* // wait for enough space to be available in the message buffer.
* xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
*
* if( xBytesSent != sizeof( ucArrayToSend ) )
* {
* // The call to xMessageBufferSend() times out before there was enough
* // space in the buffer for the data to be written.
* }
*
* // Send the string to the message buffer. Return immediately if there is
* // not enough space in the buffer.
* xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
*
* if( xBytesSent != strlen( pcStringToSend ) )
* {
* // The string could not be added to the message buffer because there was
* // not enough free space in the buffer.
* }
* }
* </pre>
* \defgroup xMessageBufferSend xMessageBufferSend
* \ingroup MessageBufferManagement
*/
#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) \
xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait )
/**
* message_buffer.h
*
* <pre>
* size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
* const void *pvTxData,
* size_t xDataLengthBytes,
* BaseType_t *pxHigherPriorityTaskWoken );
* </pre>
*
* Interrupt safe version of the API function that sends a discrete message to
* the message buffer. The message can be any length that fits within the
* buffer's free space, and is copied into the buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xMessageBufferSend() to write to a message buffer from a task. Use
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
* service routine (ISR).
*
* @param xMessageBuffer The handle of the message buffer to which a message is
* being sent.
*
* @param pvTxData A pointer to the message that is to be copied into the
* message buffer.
*
* @param xDataLengthBytes The length of the message. That is, the number of
* bytes to copy from pvTxData into the message buffer. When a message is
* written to the message buffer an additional sizeof( size_t ) bytes are also
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
* on a 32-bit architecture, so on most 32-bit architecture setting
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
* bytes (20 bytes of message data and 4 bytes to hold the message length).
*
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
* have a task blocked on it waiting for data. Calling
* xMessageBufferSendFromISR() can make data available, and so cause a task that
* was waiting for data to leave the Blocked state. If calling
* xMessageBufferSendFromISR() causes a task to leave the Blocked state, and the
* unblocked task has a priority higher than the currently executing task (the
* task that was interrupted), then, internally, xMessageBufferSendFromISR()
* will set *pxHigherPriorityTaskWoken to pdTRUE. If
* xMessageBufferSendFromISR() sets this value to pdTRUE, then normally a
* context switch should be performed before the interrupt is exited. This will
* ensure that the interrupt returns directly to the highest priority Ready
* state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
* is passed into the function. See the code example below for an example.
*
* @return The number of bytes actually written to the message buffer. If the
* message buffer didn't have enough free space for the message to be stored
* then 0 is returned, otherwise xDataLengthBytes is returned.
*
* Example use:
* <pre>
* // A message buffer that has already been created.
* MessageBufferHandle_t xMessageBuffer;
*
* void vAnInterruptServiceRoutine( void )
* {
* size_t xBytesSent;
* char *pcStringToSend = "String to send";
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
* // Attempt to send the string to the message buffer.
* xBytesSent = xMessageBufferSendFromISR( xMessageBuffer,
* ( void * ) pcStringToSend,
* strlen( pcStringToSend ),
* &xHigherPriorityTaskWoken );
*
* if( xBytesSent != strlen( pcStringToSend ) )
* {
* // The string could not be added to the message buffer because there was
* // not enough free space in the buffer.
* }
*
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
* // xMessageBufferSendFromISR() then a task that has a priority above the
* // priority of the currently executing task was unblocked and a context
* // switch should be performed to ensure the ISR returns to the unblocked
* // task. In most FreeRTOS ports this is done by simply passing
* // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
* // variables value, and perform the context switch if necessary. Check the
* // documentation for the port in use for port specific instructions.
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
* }
* </pre>
* \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR
* \ingroup MessageBufferManagement
*/
#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) \
xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken )
/**
* message_buffer.h
*
* <pre>
* size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
* void *pvRxData,
* size_t xBufferLengthBytes,
* TickType_t xTicksToWait );
* </pre>
*
* Receives a discrete message from a message buffer. Messages can be of
* variable length and are copied out of the buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
* xMessageBufferReceiveFromISR() to read from a message buffer from an
* interrupt service routine (ISR).
*
* @param xMessageBuffer The handle of the message buffer from which a message
* is being received.
*
* @param pvRxData A pointer to the buffer into which the received message is
* to be copied.
*
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
* parameter. This sets the maximum length of the message that can be received.
* If xBufferLengthBytes is too small to hold the next message then the message
* will be left in the message buffer and 0 will be returned.
*
* @param xTicksToWait The maximum amount of time the task should remain in the
* Blocked state to wait for a message, should the message buffer be empty.
* xMessageBufferReceive() will return immediately if xTicksToWait is zero and
* the message buffer is empty. The block time is specified in tick periods, so
* the absolute time it represents is dependent on the tick frequency. The
* macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
* into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
* cause the task to wait indefinitely (without timing out), provided
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
* CPU time when they are in the Blocked state.
*
* @return The length, in bytes, of the message read from the message buffer, if
* any. If xMessageBufferReceive() times out before a message became available
* then zero is returned. If the length of the message is greater than
* xBufferLengthBytes then the message will be left in the message buffer and
* zero is returned.
*
* Example use:
* <pre>
* void vAFunction( MessageBuffer_t xMessageBuffer )
* {
* uint8_t ucRxData[ 20 ];
* size_t xReceivedBytes;
* const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
*
* // Receive the next message from the message buffer. Wait in the Blocked
* // state (so not using any CPU processing time) for a maximum of 100ms for
* // a message to become available.
* xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
* ( void * ) ucRxData,
* sizeof( ucRxData ),
* xBlockTime );
*
* if( xReceivedBytes > 0 )
* {
* // A ucRxData contains a message that is xReceivedBytes long. Process
* // the message here....
* }
* }
* </pre>
* \defgroup xMessageBufferReceive xMessageBufferReceive
* \ingroup MessageBufferManagement
*/
#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) \
xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait )
/**
* message_buffer.h
*
* <pre>
* size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
* void *pvRxData,
* size_t xBufferLengthBytes,
* BaseType_t *pxHigherPriorityTaskWoken );
* </pre>
*
* An interrupt safe version of the API function that receives a discrete
* message from a message buffer. Messages can be of variable length and are
* copied out of the buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
* xMessageBufferReceiveFromISR() to read from a message buffer from an
* interrupt service routine (ISR).
*
* @param xMessageBuffer The handle of the message buffer from which a message
* is being received.
*
* @param pvRxData A pointer to the buffer into which the received message is
* to be copied.
*
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
* parameter. This sets the maximum length of the message that can be received.
* If xBufferLengthBytes is too small to hold the next message then the message
* will be left in the message buffer and 0 will be returned.
*
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
* have a task blocked on it waiting for space to become available. Calling
* xMessageBufferReceiveFromISR() can make space available, and so cause a task
* that is waiting for space to leave the Blocked state. If calling
* xMessageBufferReceiveFromISR() causes a task to leave the Blocked state, and
* the unblocked task has a priority higher than the currently executing task
* (the task that was interrupted), then, internally,
* xMessageBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
* If xMessageBufferReceiveFromISR() sets this value to pdTRUE, then normally a
* context switch should be performed before the interrupt is exited. That will
* ensure the interrupt returns directly to the highest priority Ready state
* task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
* passed into the function. See the code example below for an example.
*
* @return The length, in bytes, of the message read from the message buffer, if
* any.
*
* Example use:
* <pre>
* // A message buffer that has already been created.
* MessageBuffer_t xMessageBuffer;
*
* void vAnInterruptServiceRoutine( void )
* {
* uint8_t ucRxData[ 20 ];
* size_t xReceivedBytes;
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
* // Receive the next message from the message buffer.
* xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer,
* ( void * ) ucRxData,
* sizeof( ucRxData ),
* &xHigherPriorityTaskWoken );
*
* if( xReceivedBytes > 0 )
* {
* // A ucRxData contains a message that is xReceivedBytes long. Process
* // the message here....
* }
*
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
* // xMessageBufferReceiveFromISR() then a task that has a priority above the
* // priority of the currently executing task was unblocked and a context
* // switch should be performed to ensure the ISR returns to the unblocked
* // task. In most FreeRTOS ports this is done by simply passing
* // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
* // variables value, and perform the context switch if necessary. Check the
* // documentation for the port in use for port specific instructions.
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
* }
* </pre>
* \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR
* \ingroup MessageBufferManagement
*/
#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) \
xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken )
/**
* message_buffer.h
*
* <pre>
* void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
* </pre>
*
* Deletes a message buffer that was previously created using a call to
* xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message
* buffer was created using dynamic memory (that is, by xMessageBufferCreate()),
* then the allocated memory is freed.
*
* A message buffer handle must not be used after the message buffer has been
* deleted.
*
* @param xMessageBuffer The handle of the message buffer to be deleted.
*
*/
#define vMessageBufferDelete( xMessageBuffer ) \
vStreamBufferDelete( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* message_buffer.h
* <pre>
* BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer ) );
* </pre>
*
* Tests to see if a message buffer is full. A message buffer is full if it
* cannot accept any more messages, of any size, until space is made available
* by a message being removed from the message buffer.
*
* @param xMessageBuffer The handle of the message buffer being queried.
*
* @return If the message buffer referenced by xMessageBuffer is full then
* pdTRUE is returned. Otherwise pdFALSE is returned.
*/
#define xMessageBufferIsFull( xMessageBuffer ) \
xStreamBufferIsFull( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* message_buffer.h
* <pre>
* BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer ) );
* </pre>
*
* Tests to see if a message buffer is empty (does not contain any messages).
*
* @param xMessageBuffer The handle of the message buffer being queried.
*
* @return If the message buffer referenced by xMessageBuffer is empty then
* pdTRUE is returned. Otherwise pdFALSE is returned.
*
*/
#define xMessageBufferIsEmpty( xMessageBuffer ) \
xStreamBufferIsEmpty( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* message_buffer.h
* <pre>
* BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
* </pre>
*
* Resets a message buffer to its initial empty state, discarding any message it
* contained.
*
* A message buffer can only be reset if there are no tasks blocked on it.
*
* @param xMessageBuffer The handle of the message buffer being reset.
*
* @return If the message buffer was reset then pdPASS is returned. If the
* message buffer could not be reset because either there was a task blocked on
* the message queue to wait for space to become available, or to wait for a
* a message to be available, then pdFAIL is returned.
*
* \defgroup xMessageBufferReset xMessageBufferReset
* \ingroup MessageBufferManagement
*/
#define xMessageBufferReset( xMessageBuffer ) \
xStreamBufferReset( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* message_buffer.h
* <pre>
* size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) );
* </pre>
* Returns the number of bytes of free space in the message buffer.
*
* @param xMessageBuffer The handle of the message buffer being queried.
*
* @return The number of bytes that can be written to the message buffer before
* the message buffer would be full. When a message is written to the message
* buffer an additional sizeof( size_t ) bytes are also written to store the
* message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
* architecture, so if xMessageBufferSpacesAvailable() returns 10, then the size
* of the largest message that can be written to the message buffer is 6 bytes.
*
* \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable
* \ingroup MessageBufferManagement
*/
#define xMessageBufferSpaceAvailable( xMessageBuffer ) \
xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer )
#define xMessageBufferSpacesAvailable( xMessageBuffer ) \
xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) /* Corrects typo in original macro name. */
/**
* message_buffer.h
* <pre>
* size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer ) );
* </pre>
* Returns the length (in bytes) of the next message in a message buffer.
* Useful if xMessageBufferReceive() returned 0 because the size of the buffer
* passed into xMessageBufferReceive() was too small to hold the next message.
*
* @param xMessageBuffer The handle of the message buffer being queried.
*
* @return The length (in bytes) of the next message in the message buffer, or 0
* if the message buffer is empty.
*
* \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes
* \ingroup MessageBufferManagement
*/
#define xMessageBufferNextLengthBytes( xMessageBuffer ) \
xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* message_buffer.h
*
* <pre>
* BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
* </pre>
*
* For advanced users only.
*
* The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
* data is sent to a message buffer or stream buffer. If there was a task that
* was blocked on the message or stream buffer waiting for data to arrive then
* the sbSEND_COMPLETED() macro sends a notification to the task to remove it
* from the Blocked state. xMessageBufferSendCompletedFromISR() does the same
* thing. It is provided to enable application writers to implement their own
* version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
*
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
* additional information.
*
* @param xStreamBuffer The handle of the stream buffer to which data was
* written.
*
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
* initialised to pdFALSE before it is passed into
* xMessageBufferSendCompletedFromISR(). If calling
* xMessageBufferSendCompletedFromISR() removes a task from the Blocked state,
* and the task has a priority above the priority of the currently running task,
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
* context switch should be performed before exiting the ISR.
*
* @return If a task was removed from the Blocked state then pdTRUE is returned.
* Otherwise pdFALSE is returned.
*
* \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR
* \ingroup StreamBufferManagement
*/
#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
xStreamBufferSendCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
/**
* message_buffer.h
*
* <pre>
* BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
* </pre>
*
* For advanced users only.
*
* The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
* data is read out of a message buffer or stream buffer. If there was a task
* that was blocked on the message or stream buffer waiting for data to arrive
* then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
* remove it from the Blocked state. xMessageBufferReceiveCompletedFromISR()
* does the same thing. It is provided to enable application writers to
* implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
* ANY OTHER TIME.
*
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
* additional information.
*
* @param xStreamBuffer The handle of the stream buffer from which data was
* read.
*
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
* initialised to pdFALSE before it is passed into
* xMessageBufferReceiveCompletedFromISR(). If calling
* xMessageBufferReceiveCompletedFromISR() removes a task from the Blocked state,
* and the task has a priority above the priority of the currently running task,
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
* context switch should be performed before exiting the ISR.
*
* @return If a task was removed from the Blocked state then pdTRUE is returned.
* Otherwise pdFALSE is returned.
*
* \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR
* \ingroup StreamBufferManagement
*/
#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
xStreamBufferReceiveCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
/* *INDENT-OFF* */
#if defined( __cplusplus )
} /* extern "C" */
#endif
/* *INDENT-ON* */
#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */

View File

@@ -0,0 +1,270 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/*
* When the MPU is used the standard (non MPU) API functions are mapped to
* equivalents that start "MPU_", the prototypes for which are defined in this
* header files. This will cause the application code to call the MPU_ version
* which wraps the non-MPU version with privilege promoting then demoting code,
* so the kernel code always runs will full privileges.
*/
#ifndef MPU_PROTOTYPES_H
#define MPU_PROTOTYPES_H
/* MPU versions of tasks.h API functions. */
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskGetInfo( TaskHandle_t xTask,
TaskStatus_t * pxTaskStatus,
BaseType_t xGetFreeStackSpace,
eTaskState eState ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskPrioritySet( TaskHandle_t xTask,
UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskStartScheduler( void ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskSuspendAll( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskResumeAll( void ) FREERTOS_SYSTEM_CALL;
TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL;
char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask,
TaskHookFunction_t pxHookFunction ) FREERTOS_SYSTEM_CALL;
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
BaseType_t xIndex,
void * pvValue ) FREERTOS_SYSTEM_CALL;
void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
BaseType_t xIndex ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask,
void * pvParameter ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
const UBaseType_t uxArraySize,
uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL;
uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskGetRunTimeStats( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
uint32_t ulValue,
eNotifyAction eAction,
uint32_t * pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t * pulNotificationValue,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
BaseType_t xClearCountOnExit,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask,
UBaseType_t uxIndexToClear ) FREERTOS_SYSTEM_CALL;
uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
UBaseType_t uxIndexToClear,
uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL;
/* MPU versions of queue.h API functions. */
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType,
StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount,
StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) FREERTOS_SYSTEM_CALL;
void MPU_vQueueAddToRegistry( QueueHandle_t xQueue,
const char * pcName ) FREERTOS_SYSTEM_CALL;
void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
uint8_t * pucQueueStorage,
StaticQueue_t * pxStaticQueue,
const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue,
BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL;
void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue,
UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
/* MPU versions of timers.h API functions. */
TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction ) FREERTOS_SYSTEM_CALL;
TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t * pxTimerBuffer ) FREERTOS_SYSTEM_CALL;
void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
void MPU_vTimerSetTimerID( TimerHandle_t xTimer,
void * pvNewID ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
void * pvParameter1,
uint32_t ulParameter2,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
void MPU_vTimerSetReloadMode( TimerHandle_t xTimer,
const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer,
const BaseType_t xCommandID,
const TickType_t xOptionalValue,
BaseType_t * const pxHigherPriorityTaskWoken,
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
/* MPU versions of event_group.h API functions. */
EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL;
EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL;
EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL;
EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet ) FREERTOS_SYSTEM_CALL;
EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL;
/* MPU versions of message/stream_buffer.h API functions. */
size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
const void * pvTxData,
size_t xDataLengthBytes,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
void * pvRxData,
size_t xBufferLengthBytes,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL;
StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer ) FREERTOS_SYSTEM_CALL;
StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer ) FREERTOS_SYSTEM_CALL;
#endif /* MPU_PROTOTYPES_H */

View File

@@ -0,0 +1,200 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef MPU_WRAPPERS_H
#define MPU_WRAPPERS_H
/* This file redefines API functions to be called through a wrapper macro, but
* only for ports that are using the MPU. */
#ifdef portUSING_MPU_WRAPPERS
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
* included from queue.c or task.c to prevent it from having an effect within
* those files. */
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/*
* Map standard (non MPU) API functions to equivalents that start
* "MPU_". This will cause the application code to call the MPU_
* version, which wraps the non-MPU version with privilege promoting
* then demoting code, so the kernel code always runs will full
* privileges.
*/
/* Map standard tasks.h API functions to the MPU equivalents. */
#define xTaskCreate MPU_xTaskCreate
#define xTaskCreateStatic MPU_xTaskCreateStatic
#define vTaskDelete MPU_vTaskDelete
#define vTaskDelay MPU_vTaskDelay
#define xTaskDelayUntil MPU_xTaskDelayUntil
#define xTaskAbortDelay MPU_xTaskAbortDelay
#define uxTaskPriorityGet MPU_uxTaskPriorityGet
#define eTaskGetState MPU_eTaskGetState
#define vTaskGetInfo MPU_vTaskGetInfo
#define vTaskPrioritySet MPU_vTaskPrioritySet
#define vTaskSuspend MPU_vTaskSuspend
#define vTaskResume MPU_vTaskResume
#define vTaskSuspendAll MPU_vTaskSuspendAll
#define xTaskResumeAll MPU_xTaskResumeAll
#define xTaskGetTickCount MPU_xTaskGetTickCount
#define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
#define pcTaskGetName MPU_pcTaskGetName
#define xTaskGetHandle MPU_xTaskGetHandle
#define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
#define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2
#define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
#define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
#define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer
#define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer
#define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
#define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
#define uxTaskGetSystemState MPU_uxTaskGetSystemState
#define vTaskList MPU_vTaskList
#define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
#define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter
#define xTaskGenericNotify MPU_xTaskGenericNotify
#define xTaskGenericNotifyWait MPU_xTaskGenericNotifyWait
#define ulTaskGenericNotifyTake MPU_ulTaskGenericNotifyTake
#define xTaskGenericNotifyStateClear MPU_xTaskGenericNotifyStateClear
#define ulTaskGenericNotifyValueClear MPU_ulTaskGenericNotifyValueClear
#define xTaskCatchUpTicks MPU_xTaskCatchUpTicks
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
#define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
#define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
#define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
/* Map standard queue.h API functions to the MPU equivalents. */
#define xQueueGenericSend MPU_xQueueGenericSend
#define xQueueReceive MPU_xQueueReceive
#define xQueuePeek MPU_xQueuePeek
#define xQueueSemaphoreTake MPU_xQueueSemaphoreTake
#define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
#define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable
#define vQueueDelete MPU_vQueueDelete
#define xQueueCreateMutex MPU_xQueueCreateMutex
#define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic
#define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
#define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic
#define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
#define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
#define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
#define xQueueGenericCreate MPU_xQueueGenericCreate
#define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic
#define xQueueCreateSet MPU_xQueueCreateSet
#define xQueueAddToSet MPU_xQueueAddToSet
#define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
#define xQueueSelectFromSet MPU_xQueueSelectFromSet
#define xQueueGenericReset MPU_xQueueGenericReset
#if ( configQUEUE_REGISTRY_SIZE > 0 )
#define vQueueAddToRegistry MPU_vQueueAddToRegistry
#define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
#define pcQueueGetName MPU_pcQueueGetName
#endif
/* Map standard timer.h API functions to the MPU equivalents. */
#define xTimerCreate MPU_xTimerCreate
#define xTimerCreateStatic MPU_xTimerCreateStatic
#define pvTimerGetTimerID MPU_pvTimerGetTimerID
#define vTimerSetTimerID MPU_vTimerSetTimerID
#define xTimerIsTimerActive MPU_xTimerIsTimerActive
#define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle
#define xTimerPendFunctionCall MPU_xTimerPendFunctionCall
#define pcTimerGetName MPU_pcTimerGetName
#define vTimerSetReloadMode MPU_vTimerSetReloadMode
#define uxTimerGetReloadMode MPU_uxTimerGetReloadMode
#define xTimerGetPeriod MPU_xTimerGetPeriod
#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
#define xTimerGenericCommand MPU_xTimerGenericCommand
/* Map standard event_group.h API functions to the MPU equivalents. */
#define xEventGroupCreate MPU_xEventGroupCreate
#define xEventGroupCreateStatic MPU_xEventGroupCreateStatic
#define xEventGroupWaitBits MPU_xEventGroupWaitBits
#define xEventGroupClearBits MPU_xEventGroupClearBits
#define xEventGroupSetBits MPU_xEventGroupSetBits
#define xEventGroupSync MPU_xEventGroupSync
#define vEventGroupDelete MPU_vEventGroupDelete
/* Map standard message/stream_buffer.h API functions to the MPU
* equivalents. */
#define xStreamBufferSend MPU_xStreamBufferSend
#define xStreamBufferReceive MPU_xStreamBufferReceive
#define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes
#define vStreamBufferDelete MPU_vStreamBufferDelete
#define xStreamBufferIsFull MPU_xStreamBufferIsFull
#define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty
#define xStreamBufferReset MPU_xStreamBufferReset
#define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable
#define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable
#define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel
#define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate
#define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic
/* Remove the privileged function macro, but keep the PRIVILEGED_DATA
* macro so applications can place data in privileged access sections
* (useful when using statically allocated objects). */
#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
#define FREERTOS_SYSTEM_CALL
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
/* Ensure API functions go in the privileged execution section. */
#define PRIVILEGED_FUNCTION __attribute__( ( section( "privileged_functions" ) ) )
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
#define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) )
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
#else /* portUSING_MPU_WRAPPERS */
#include "sl_code_classification.h"
#define PRIVILEGED_FUNCTION SL_CODE_CLASSIFY(SL_CODE_COMPONENT_FREERTOS_KERNEL, SL_CODE_CLASS_TIME_CRITICAL)
#define PRIVILEGED_DATA
#define FREERTOS_SYSTEM_CALL
#define portUSING_MPU_WRAPPERS 0
#endif /* portUSING_MPU_WRAPPERS */
#endif /* MPU_WRAPPERS_H */

View File

@@ -0,0 +1,229 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/*-----------------------------------------------------------
* Portable layer API. Each function must be defined for each port.
*----------------------------------------------------------*/
#ifndef PORTABLE_H
#define PORTABLE_H
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
* pre-processor definition was used to ensure the pre-processor found the correct
* portmacro.h file for the port being used. That scheme was deprecated in favour
* of setting the compiler's include path such that it found the correct
* portmacro.h file - removing the need for the constant and allowing the
* portmacro.h file to be located anywhere in relation to the port being used.
* Purely for reasons of backward compatibility the old method is still valid, but
* to make it clear that new projects should not use it, support for the port
* specific constants has been moved into the deprecated_definitions.h header
* file. */
#include "deprecated_definitions.h"
/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
* did not result in a portmacro.h header file being included - and it should be
* included here. In this case the path to the correct portmacro.h header file
* must be set in the compiler's include path. */
#ifndef portENTER_CRITICAL
#include "portmacro.h"
#endif
#if portBYTE_ALIGNMENT == 32
#define portBYTE_ALIGNMENT_MASK ( 0x001f )
#endif
#if portBYTE_ALIGNMENT == 16
#define portBYTE_ALIGNMENT_MASK ( 0x000f )
#endif
#if portBYTE_ALIGNMENT == 8
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
#endif
#if portBYTE_ALIGNMENT == 4
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
#endif
#if portBYTE_ALIGNMENT == 2
#define portBYTE_ALIGNMENT_MASK ( 0x0001 )
#endif
#if portBYTE_ALIGNMENT == 1
#define portBYTE_ALIGNMENT_MASK ( 0x0000 )
#endif
#ifndef portBYTE_ALIGNMENT_MASK
#error "Invalid portBYTE_ALIGNMENT definition"
#endif
#ifndef portNUM_CONFIGURABLE_REGIONS
#define portNUM_CONFIGURABLE_REGIONS 1
#endif
#ifndef portHAS_STACK_OVERFLOW_CHECKING
#define portHAS_STACK_OVERFLOW_CHECKING 0
#endif
#ifndef portARCH_NAME
#define portARCH_NAME NULL
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
#include "mpu_wrappers.h"
/*
* Setup the stack of a new task so it is ready to be placed under the
* scheduler control. The registers have to be placed on the stack in
* the order that the port expects to find them.
*
*/
#if ( portUSING_MPU_WRAPPERS == 1 )
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
#else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
#endif
#else /* if ( portUSING_MPU_WRAPPERS == 1 ) */
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) PRIVILEGED_FUNCTION;
#else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters ) PRIVILEGED_FUNCTION;
#endif
#endif /* if ( portUSING_MPU_WRAPPERS == 1 ) */
/* Used by heap_5.c to define the start address and size of each memory region
* that together comprise the total FreeRTOS heap space. */
typedef struct HeapRegion
{
uint8_t * pucStartAddress;
size_t xSizeInBytes;
} HeapRegion_t;
/* Used to pass information about the heap out of vPortGetHeapStats(). */
typedef struct xHeapStats
{
size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */
size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */
size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */
size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */
size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */
} HeapStats_t;
/*
* Used to define multiple heap regions for use by heap_5.c. This function
* must be called before any calls to pvPortMalloc() - not creating a task,
* queue, semaphore, mutex, software timer, event group, etc. will result in
* pvPortMalloc being called.
*
* pxHeapRegions passes in an array of HeapRegion_t structures - each of which
* defines a region of memory that can be used as the heap. The array is
* terminated by a HeapRegions_t structure that has a size of 0. The region
* with the lowest start address must appear first in the array.
*/
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
/*
* Returns a HeapStats_t structure filled with information about the current
* heap state.
*/
void vPortGetHeapStats( HeapStats_t * pxHeapStats );
/*
* Map to the memory management routines required for the port.
*/
void * pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
void vPortFree( void * pv ) PRIVILEGED_FUNCTION;
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
/*
* Setup the hardware ready for the scheduler to take control. This generally
* sets up a tick interrupt and sets timers for the correct tick frequency.
*/
BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
/*
* Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
* the hardware is left in its original condition after the scheduler stops
* executing.
*/
void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
/*
* The structures and methods of manipulating the MPU are contained within the
* port layer.
*
* Fills the xMPUSettings structure with the memory region information
* contained in xRegions.
*/
#if ( portUSING_MPU_WRAPPERS == 1 )
struct xMEMORY_REGION;
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
uint32_t ulStackDepth ) PRIVILEGED_FUNCTION;
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTABLE_H */

View File

@@ -0,0 +1,133 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef PROJDEFS_H
#define PROJDEFS_H
/*
* Defines the prototype to which task functions must conform. Defined in this
* file to ensure the type is known before portable.h is included.
*/
typedef void (* TaskFunction_t)( void * );
/* Converts a time in milliseconds to a time in ticks. This macro can be
* overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
* definition here is not suitable for your application. */
#ifndef pdMS_TO_TICKS
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000U ) )
#endif
#define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( BaseType_t ) 1 )
#define pdPASS ( pdTRUE )
#define pdFAIL ( pdFALSE )
#define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
#define errQUEUE_FULL ( ( BaseType_t ) 0 )
/* FreeRTOS error definitions. */
#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
#define errQUEUE_BLOCKED ( -4 )
#define errQUEUE_YIELD ( -5 )
/* Macros used for basic data corruption checks. */
#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES
#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0
#endif
#if ( configUSE_16_BIT_TICKS == 1 )
#define pdINTEGRITY_CHECK_VALUE 0x5a5a
#else
#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
#endif
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
* itself. */
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
* itself. */
#define pdFREERTOS_LITTLE_ENDIAN 0
#define pdFREERTOS_BIG_ENDIAN 1
/* Re-defining endian values for generic naming. */
#define pdLITTLE_ENDIAN pdFREERTOS_LITTLE_ENDIAN
#define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN
#endif /* PROJDEFS_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,140 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef STACK_MACROS_H
#define STACK_MACROS_H
/*
* Call the stack overflow hook function if the stack of the task being swapped
* out is currently overflowed, or looks like it might have overflowed in the
* past.
*
* Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
* the current stack state only - comparing the current top of stack value to
* the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
* will also cause the last few stack bytes to be checked to ensure the value
* to which the bytes were set when the task was created have not been
* overwritten. Note this second test does not guarantee that an overflowed
* stack will always be recognised.
*/
/*-----------------------------------------------------------*/
#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
/* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
/* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
/*-----------------------------------------------------------*/
#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
/* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
\
/* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
/*-----------------------------------------------------------*/
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \
\
if( ( pulStack[ 0 ] != ulCheckValue ) || \
( pulStack[ 1 ] != ulCheckValue ) || \
( pulStack[ 2 ] != ulCheckValue ) || \
( pulStack[ 3 ] != ulCheckValue ) ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
/*-----------------------------------------------------------*/
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
\
\
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
\
/* Has the extremity of the task stack ever been written over? */ \
if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
/*-----------------------------------------------------------*/
/* Remove stack overflow macro if not being used. */
#ifndef taskCHECK_FOR_STACK_OVERFLOW
#define taskCHECK_FOR_STACK_OVERFLOW()
#endif
#endif /* STACK_MACROS_H */

View File

@@ -0,0 +1,880 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/*
* Stream buffers are used to send a continuous stream of data from one task or
* interrupt to another. Their implementation is light weight, making them
* particularly suited for interrupt to task and core to core communication
* scenarios.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xStreamBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xStreamBufferReceive()) inside a critical section section and set the
* receive block time to 0.
*
*/
#ifndef STREAM_BUFFER_H
#define STREAM_BUFFER_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include stream_buffer.h"
#endif
/* *INDENT-OFF* */
#if defined( __cplusplus )
extern "C" {
#endif
/* *INDENT-ON* */
/**
* Type by which stream buffers are referenced. For example, a call to
* xStreamBufferCreate() returns an StreamBufferHandle_t variable that can
* then be used as a parameter to xStreamBufferSend(), xStreamBufferReceive(),
* etc.
*/
struct StreamBufferDef_t;
typedef struct StreamBufferDef_t * StreamBufferHandle_t;
/**
* message_buffer.h
*
* <pre>
* StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );
* </pre>
*
* Creates a new stream buffer using dynamically allocated memory. See
* xStreamBufferCreateStatic() for a version that uses statically allocated
* memory (memory that is allocated at compile time).
*
* configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
* FreeRTOSConfig.h for xStreamBufferCreate() to be available.
*
* @param xBufferSizeBytes The total number of bytes the stream buffer will be
* able to hold at any one time.
*
* @param xTriggerLevelBytes The number of bytes that must be in the stream
* buffer before a task that is blocked on the stream buffer to wait for data is
* moved out of the blocked state. For example, if a task is blocked on a read
* of an empty stream buffer that has a trigger level of 1 then the task will be
* unblocked when a single byte is written to the buffer or the task's block
* time expires. As another example, if a task is blocked on a read of an empty
* stream buffer that has a trigger level of 10 then the task will not be
* unblocked until the stream buffer contains at least 10 bytes or the task's
* block time expires. If a reading task's block time expires before the
* trigger level is reached then the task will still receive however many bytes
* are actually available. Setting a trigger level of 0 will result in a
* trigger level of 1 being used. It is not valid to specify a trigger level
* that is greater than the buffer size.
*
* @return If NULL is returned, then the stream buffer cannot be created
* because there is insufficient heap memory available for FreeRTOS to allocate
* the stream buffer data structures and storage area. A non-NULL value being
* returned indicates that the stream buffer has been created successfully -
* the returned value should be stored as the handle to the created stream
* buffer.
*
* Example use:
* <pre>
*
* void vAFunction( void )
* {
* StreamBufferHandle_t xStreamBuffer;
* const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10;
*
* // Create a stream buffer that can hold 100 bytes. The memory used to hold
* // both the stream buffer structure and the data in the stream buffer is
* // allocated dynamically.
* xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
*
* if( xStreamBuffer == NULL )
* {
* // There was not enough heap memory space available to create the
* // stream buffer.
* }
* else
* {
* // The stream buffer was created successfully and can now be used.
* }
* }
* </pre>
* \defgroup xStreamBufferCreate xStreamBufferCreate
* \ingroup StreamBufferManagement
*/
#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE )
/**
* stream_buffer.h
*
* <pre>
* StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes,
* size_t xTriggerLevelBytes,
* uint8_t *pucStreamBufferStorageArea,
* StaticStreamBuffer_t *pxStaticStreamBuffer );
* </pre>
* Creates a new stream buffer using statically allocated memory. See
* xStreamBufferCreate() for a version that uses dynamically allocated memory.
*
* configSUPPORT_STATIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h for
* xStreamBufferCreateStatic() to be available.
*
* @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
* pucStreamBufferStorageArea parameter.
*
* @param xTriggerLevelBytes The number of bytes that must be in the stream
* buffer before a task that is blocked on the stream buffer to wait for data is
* moved out of the blocked state. For example, if a task is blocked on a read
* of an empty stream buffer that has a trigger level of 1 then the task will be
* unblocked when a single byte is written to the buffer or the task's block
* time expires. As another example, if a task is blocked on a read of an empty
* stream buffer that has a trigger level of 10 then the task will not be
* unblocked until the stream buffer contains at least 10 bytes or the task's
* block time expires. If a reading task's block time expires before the
* trigger level is reached then the task will still receive however many bytes
* are actually available. Setting a trigger level of 0 will result in a
* trigger level of 1 being used. It is not valid to specify a trigger level
* that is greater than the buffer size.
*
* @param pucStreamBufferStorageArea Must point to a uint8_t array that is at
* least xBufferSizeBytes + 1 big. This is the array to which streams are
* copied when they are written to the stream buffer.
*
* @param pxStaticStreamBuffer Must point to a variable of type
* StaticStreamBuffer_t, which will be used to hold the stream buffer's data
* structure.
*
* @return If the stream buffer is created successfully then a handle to the
* created stream buffer is returned. If either pucStreamBufferStorageArea or
* pxStaticstreamBuffer are NULL then NULL is returned.
*
* Example use:
* <pre>
*
* // Used to dimension the array used to hold the streams. The available space
* // will actually be one less than this, so 999.
#define STORAGE_SIZE_BYTES 1000
*
* // Defines the memory that will actually hold the streams within the stream
* // buffer.
* static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
*
* // The variable used to hold the stream buffer structure.
* StaticStreamBuffer_t xStreamBufferStruct;
*
* void MyFunction( void )
* {
* StreamBufferHandle_t xStreamBuffer;
* const size_t xTriggerLevel = 1;
*
* xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ),
* xTriggerLevel,
* ucBufferStorage,
* &xStreamBufferStruct );
*
* // As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer
* // parameters were NULL, xStreamBuffer will not be NULL, and can be used to
* // reference the created stream buffer in other stream buffer API calls.
*
* // Other code that uses the stream buffer can go here.
* }
*
* </pre>
* \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic
* \ingroup StreamBufferManagement
*/
#define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) \
xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer )
/**
* stream_buffer.h
*
* <pre>
* size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
* const void *pvTxData,
* size_t xDataLengthBytes,
* TickType_t xTicksToWait );
* </pre>
*
* Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xStreamBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xStreamBufferReceive()) inside a critical section and set the receive
* block time to 0.
*
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
* xStreamBufferSendFromISR() to write to a stream buffer from an interrupt
* service routine (ISR).
*
* @param xStreamBuffer The handle of the stream buffer to which a stream is
* being sent.
*
* @param pvTxData A pointer to the buffer that holds the bytes to be copied
* into the stream buffer.
*
* @param xDataLengthBytes The maximum number of bytes to copy from pvTxData
* into the stream buffer.
*
* @param xTicksToWait The maximum amount of time the task should remain in the
* Blocked state to wait for enough space to become available in the stream
* buffer, should the stream buffer contain too little space to hold the
* another xDataLengthBytes bytes. The block time is specified in tick periods,
* so the absolute time it represents is dependent on the tick frequency. The
* macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
* into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
* cause the task to wait indefinitely (without timing out), provided
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. If a task times out
* before it can write all xDataLengthBytes into the buffer it will still write
* as many bytes as possible. A task does not use any CPU time when it is in
* the blocked state.
*
* @return The number of bytes written to the stream buffer. If a task times
* out before it can write all xDataLengthBytes into the buffer it will still
* write as many bytes as possible.
*
* Example use:
* <pre>
* void vAFunction( StreamBufferHandle_t xStreamBuffer )
* {
* size_t xBytesSent;
* uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
* char *pcStringToSend = "String to send";
* const TickType_t x100ms = pdMS_TO_TICKS( 100 );
*
* // Send an array to the stream buffer, blocking for a maximum of 100ms to
* // wait for enough space to be available in the stream buffer.
* xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
*
* if( xBytesSent != sizeof( ucArrayToSend ) )
* {
* // The call to xStreamBufferSend() times out before there was enough
* // space in the buffer for the data to be written, but it did
* // successfully write xBytesSent bytes.
* }
*
* // Send the string to the stream buffer. Return immediately if there is not
* // enough space in the buffer.
* xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
*
* if( xBytesSent != strlen( pcStringToSend ) )
* {
* // The entire string could not be added to the stream buffer because
* // there was not enough free space in the buffer, but xBytesSent bytes
* // were sent. Could try again to send the remaining bytes.
* }
* }
* </pre>
* \defgroup xStreamBufferSend xStreamBufferSend
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
const void * pvTxData,
size_t xDataLengthBytes,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
* const void *pvTxData,
* size_t xDataLengthBytes,
* BaseType_t *pxHigherPriorityTaskWoken );
* </pre>
*
* Interrupt safe version of the API function that sends a stream of bytes to
* the stream buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xStreamBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xStreamBufferReceive()) inside a critical section and set the receive
* block time to 0.
*
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
* xStreamBufferSendFromISR() to write to a stream buffer from an interrupt
* service routine (ISR).
*
* @param xStreamBuffer The handle of the stream buffer to which a stream is
* being sent.
*
* @param pvTxData A pointer to the data that is to be copied into the stream
* buffer.
*
* @param xDataLengthBytes The maximum number of bytes to copy from pvTxData
* into the stream buffer.
*
* @param pxHigherPriorityTaskWoken It is possible that a stream buffer will
* have a task blocked on it waiting for data. Calling
* xStreamBufferSendFromISR() can make data available, and so cause a task that
* was waiting for data to leave the Blocked state. If calling
* xStreamBufferSendFromISR() causes a task to leave the Blocked state, and the
* unblocked task has a priority higher than the currently executing task (the
* task that was interrupted), then, internally, xStreamBufferSendFromISR()
* will set *pxHigherPriorityTaskWoken to pdTRUE. If
* xStreamBufferSendFromISR() sets this value to pdTRUE, then normally a
* context switch should be performed before the interrupt is exited. This will
* ensure that the interrupt returns directly to the highest priority Ready
* state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
* is passed into the function. See the example code below for an example.
*
* @return The number of bytes actually written to the stream buffer, which will
* be less than xDataLengthBytes if the stream buffer didn't have enough free
* space for all the bytes to be written.
*
* Example use:
* <pre>
* // A stream buffer that has already been created.
* StreamBufferHandle_t xStreamBuffer;
*
* void vAnInterruptServiceRoutine( void )
* {
* size_t xBytesSent;
* char *pcStringToSend = "String to send";
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
* // Attempt to send the string to the stream buffer.
* xBytesSent = xStreamBufferSendFromISR( xStreamBuffer,
* ( void * ) pcStringToSend,
* strlen( pcStringToSend ),
* &xHigherPriorityTaskWoken );
*
* if( xBytesSent != strlen( pcStringToSend ) )
* {
* // There was not enough free space in the stream buffer for the entire
* // string to be written, ut xBytesSent bytes were written.
* }
*
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
* // xStreamBufferSendFromISR() then a task that has a priority above the
* // priority of the currently executing task was unblocked and a context
* // switch should be performed to ensure the ISR returns to the unblocked
* // task. In most FreeRTOS ports this is done by simply passing
* // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
* // variables value, and perform the context switch if necessary. Check the
* // documentation for the port in use for port specific instructions.
* taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
* }
* </pre>
* \defgroup xStreamBufferSendFromISR xStreamBufferSendFromISR
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
const void * pvTxData,
size_t xDataLengthBytes,
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
* void *pvRxData,
* size_t xBufferLengthBytes,
* TickType_t xTicksToWait );
* </pre>
*
* Receives bytes from a stream buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xStreamBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xStreamBufferReceive()) inside a critical section and set the receive
* block time to 0.
*
* Use xStreamBufferReceive() to read from a stream buffer from a task. Use
* xStreamBufferReceiveFromISR() to read from a stream buffer from an
* interrupt service routine (ISR).
*
* @param xStreamBuffer The handle of the stream buffer from which bytes are to
* be received.
*
* @param pvRxData A pointer to the buffer into which the received bytes will be
* copied.
*
* @param xBufferLengthBytes The length of the buffer pointed to by the
* pvRxData parameter. This sets the maximum number of bytes to receive in one
* call. xStreamBufferReceive will return as many bytes as possible up to a
* maximum set by xBufferLengthBytes.
*
* @param xTicksToWait The maximum amount of time the task should remain in the
* Blocked state to wait for data to become available if the stream buffer is
* empty. xStreamBufferReceive() will return immediately if xTicksToWait is
* zero. The block time is specified in tick periods, so the absolute time it
* represents is dependent on the tick frequency. The macro pdMS_TO_TICKS() can
* be used to convert a time specified in milliseconds into a time specified in
* ticks. Setting xTicksToWait to portMAX_DELAY will cause the task to wait
* indefinitely (without timing out), provided INCLUDE_vTaskSuspend is set to 1
* in FreeRTOSConfig.h. A task does not use any CPU time when it is in the
* Blocked state.
*
* @return The number of bytes actually read from the stream buffer, which will
* be less than xBufferLengthBytes if the call to xStreamBufferReceive() timed
* out before xBufferLengthBytes were available.
*
* Example use:
* <pre>
* void vAFunction( StreamBuffer_t xStreamBuffer )
* {
* uint8_t ucRxData[ 20 ];
* size_t xReceivedBytes;
* const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
*
* // Receive up to another sizeof( ucRxData ) bytes from the stream buffer.
* // Wait in the Blocked state (so not using any CPU processing time) for a
* // maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be
* // available.
* xReceivedBytes = xStreamBufferReceive( xStreamBuffer,
* ( void * ) ucRxData,
* sizeof( ucRxData ),
* xBlockTime );
*
* if( xReceivedBytes > 0 )
* {
* // A ucRxData contains another xRecievedBytes bytes of data, which can
* // be processed here....
* }
* }
* </pre>
* \defgroup xStreamBufferReceive xStreamBufferReceive
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
void * pvRxData,
size_t xBufferLengthBytes,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
* void *pvRxData,
* size_t xBufferLengthBytes,
* BaseType_t *pxHigherPriorityTaskWoken );
* </pre>
*
* An interrupt safe version of the API function that receives bytes from a
* stream buffer.
*
* Use xStreamBufferReceive() to read bytes from a stream buffer from a task.
* Use xStreamBufferReceiveFromISR() to read bytes from a stream buffer from an
* interrupt service routine (ISR).
*
* @param xStreamBuffer The handle of the stream buffer from which a stream
* is being received.
*
* @param pvRxData A pointer to the buffer into which the received bytes are
* copied.
*
* @param xBufferLengthBytes The length of the buffer pointed to by the
* pvRxData parameter. This sets the maximum number of bytes to receive in one
* call. xStreamBufferReceive will return as many bytes as possible up to a
* maximum set by xBufferLengthBytes.
*
* @param pxHigherPriorityTaskWoken It is possible that a stream buffer will
* have a task blocked on it waiting for space to become available. Calling
* xStreamBufferReceiveFromISR() can make space available, and so cause a task
* that is waiting for space to leave the Blocked state. If calling
* xStreamBufferReceiveFromISR() causes a task to leave the Blocked state, and
* the unblocked task has a priority higher than the currently executing task
* (the task that was interrupted), then, internally,
* xStreamBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
* If xStreamBufferReceiveFromISR() sets this value to pdTRUE, then normally a
* context switch should be performed before the interrupt is exited. That will
* ensure the interrupt returns directly to the highest priority Ready state
* task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
* passed into the function. See the code example below for an example.
*
* @return The number of bytes read from the stream buffer, if any.
*
* Example use:
* <pre>
* // A stream buffer that has already been created.
* StreamBuffer_t xStreamBuffer;
*
* void vAnInterruptServiceRoutine( void )
* {
* uint8_t ucRxData[ 20 ];
* size_t xReceivedBytes;
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
* // Receive the next stream from the stream buffer.
* xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer,
* ( void * ) ucRxData,
* sizeof( ucRxData ),
* &xHigherPriorityTaskWoken );
*
* if( xReceivedBytes > 0 )
* {
* // ucRxData contains xReceivedBytes read from the stream buffer.
* // Process the stream here....
* }
*
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
* // xStreamBufferReceiveFromISR() then a task that has a priority above the
* // priority of the currently executing task was unblocked and a context
* // switch should be performed to ensure the ISR returns to the unblocked
* // task. In most FreeRTOS ports this is done by simply passing
* // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
* // variables value, and perform the context switch if necessary. Check the
* // documentation for the port in use for port specific instructions.
* taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
* }
* </pre>
* \defgroup xStreamBufferReceiveFromISR xStreamBufferReceiveFromISR
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
void * pvRxData,
size_t xBufferLengthBytes,
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
* </pre>
*
* Deletes a stream buffer that was previously created using a call to
* xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream
* buffer was created using dynamic memory (that is, by xStreamBufferCreate()),
* then the allocated memory is freed.
*
* A stream buffer handle must not be used after the stream buffer has been
* deleted.
*
* @param xStreamBuffer The handle of the stream buffer to be deleted.
*
* \defgroup vStreamBufferDelete vStreamBufferDelete
* \ingroup StreamBufferManagement
*/
void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
* </pre>
*
* Queries a stream buffer to see if it is full. A stream buffer is full if it
* does not have any free space, and therefore cannot accept any more data.
*
* @param xStreamBuffer The handle of the stream buffer being queried.
*
* @return If the stream buffer is full then pdTRUE is returned. Otherwise
* pdFALSE is returned.
*
* \defgroup xStreamBufferIsFull xStreamBufferIsFull
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
* </pre>
*
* Queries a stream buffer to see if it is empty. A stream buffer is empty if
* it does not contain any data.
*
* @param xStreamBuffer The handle of the stream buffer being queried.
*
* @return If the stream buffer is empty then pdTRUE is returned. Otherwise
* pdFALSE is returned.
*
* \defgroup xStreamBufferIsEmpty xStreamBufferIsEmpty
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
* </pre>
*
* Resets a stream buffer to its initial, empty, state. Any data that was in
* the stream buffer is discarded. A stream buffer can only be reset if there
* are no tasks blocked waiting to either send to or receive from the stream
* buffer.
*
* @param xStreamBuffer The handle of the stream buffer being reset.
*
* @return If the stream buffer is reset then pdPASS is returned. If there was
* a task blocked waiting to send to or read from the stream buffer then the
* stream buffer is not reset and pdFAIL is returned.
*
* \defgroup xStreamBufferReset xStreamBufferReset
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
* </pre>
*
* Queries a stream buffer to see how much free space it contains, which is
* equal to the amount of data that can be sent to the stream buffer before it
* is full.
*
* @param xStreamBuffer The handle of the stream buffer being queried.
*
* @return The number of bytes that can be written to the stream buffer before
* the stream buffer would be full.
*
* \defgroup xStreamBufferSpacesAvailable xStreamBufferSpacesAvailable
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
* </pre>
*
* Queries a stream buffer to see how much data it contains, which is equal to
* the number of bytes that can be read from the stream buffer before the stream
* buffer would be empty.
*
* @param xStreamBuffer The handle of the stream buffer being queried.
*
* @return The number of bytes that can be read from the stream buffer before
* the stream buffer would be empty.
*
* \defgroup xStreamBufferBytesAvailable xStreamBufferBytesAvailable
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel );
* </pre>
*
* A stream buffer's trigger level is the number of bytes that must be in the
* stream buffer before a task that is blocked on the stream buffer to
* wait for data is moved out of the blocked state. For example, if a task is
* blocked on a read of an empty stream buffer that has a trigger level of 1
* then the task will be unblocked when a single byte is written to the buffer
* or the task's block time expires. As another example, if a task is blocked
* on a read of an empty stream buffer that has a trigger level of 10 then the
* task will not be unblocked until the stream buffer contains at least 10 bytes
* or the task's block time expires. If a reading task's block time expires
* before the trigger level is reached then the task will still receive however
* many bytes are actually available. Setting a trigger level of 0 will result
* in a trigger level of 1 being used. It is not valid to specify a trigger
* level that is greater than the buffer size.
*
* A trigger level is set when the stream buffer is created, and can be modified
* using xStreamBufferSetTriggerLevel().
*
* @param xStreamBuffer The handle of the stream buffer being updated.
*
* @param xTriggerLevel The new trigger level for the stream buffer.
*
* @return If xTriggerLevel was less than or equal to the stream buffer's length
* then the trigger level will be updated and pdTRUE is returned. Otherwise
* pdFALSE is returned.
*
* \defgroup xStreamBufferSetTriggerLevel xStreamBufferSetTriggerLevel
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
size_t xTriggerLevel ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
* </pre>
*
* For advanced users only.
*
* The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
* data is sent to a message buffer or stream buffer. If there was a task that
* was blocked on the message or stream buffer waiting for data to arrive then
* the sbSEND_COMPLETED() macro sends a notification to the task to remove it
* from the Blocked state. xStreamBufferSendCompletedFromISR() does the same
* thing. It is provided to enable application writers to implement their own
* version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
*
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
* additional information.
*
* @param xStreamBuffer The handle of the stream buffer to which data was
* written.
*
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
* initialised to pdFALSE before it is passed into
* xStreamBufferSendCompletedFromISR(). If calling
* xStreamBufferSendCompletedFromISR() removes a task from the Blocked state,
* and the task has a priority above the priority of the currently running task,
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
* context switch should be performed before exiting the ISR.
*
* @return If a task was removed from the Blocked state then pdTRUE is returned.
* Otherwise pdFALSE is returned.
*
* \defgroup xStreamBufferSendCompletedFromISR xStreamBufferSendCompletedFromISR
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* <pre>
* BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
* </pre>
*
* For advanced users only.
*
* The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
* data is read out of a message buffer or stream buffer. If there was a task
* that was blocked on the message or stream buffer waiting for data to arrive
* then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
* remove it from the Blocked state. xStreamBufferReceiveCompletedFromISR()
* does the same thing. It is provided to enable application writers to
* implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
* ANY OTHER TIME.
*
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
* additional information.
*
* @param xStreamBuffer The handle of the stream buffer from which data was
* read.
*
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
* initialised to pdFALSE before it is passed into
* xStreamBufferReceiveCompletedFromISR(). If calling
* xStreamBufferReceiveCompletedFromISR() removes a task from the Blocked state,
* and the task has a priority above the priority of the currently running task,
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
* context switch should be performed before exiting the ISR.
*
* @return If a task was removed from the Blocked state then pdTRUE is returned.
* Otherwise pdFALSE is returned.
*
* \defgroup xStreamBufferReceiveCompletedFromISR xStreamBufferReceiveCompletedFromISR
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/* Functions below here are not part of the public API. */
StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION;
StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
#if ( configUSE_TRACE_FACILITY == 1 )
void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer,
UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION;
UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
#endif
/* *INDENT-OFF* */
#if defined( __cplusplus )
}
#endif
/* *INDENT-ON* */
#endif /* !defined( STREAM_BUFFER_H ) */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

223
Libs/FreeRTOS/kernel/list.c Normal file
View File

@@ -0,0 +1,223 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
* all the API functions to use the MPU wrappers. That should only be done when
* task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#include "FreeRTOS.h"
#include "list.h"
/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be
* defined for the header files above, but not in this file, in order to
* generate the correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
/*-----------------------------------------------------------
* PUBLIC LIST API documented in list.h
*----------------------------------------------------------*/
void vListInitialise( List_t * const pxList )
{
/* The list structure contains a list item which is used to mark the
* end of the list. To initialise the list the list end is inserted
* as the only list entry. */
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
/* The list end value is the highest possible value in the list to
* ensure it remains at the end of the list. */
pxList->xListEnd.xItemValue = portMAX_DELAY;
/* The list end next and previous pointers point to itself so we know
* when the list is empty. */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
/* Write known values into the list if
* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
/*-----------------------------------------------------------*/
void vListInitialiseItem( ListItem_t * const pxItem )
{
/* Make sure the list item is not recorded as being on a list. */
pxItem->pxContainer = NULL;
/* Write known values into the list item if
* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
/*-----------------------------------------------------------*/
void vListInsertEnd( List_t * const pxList,
ListItem_t * const pxNewListItem )
{
ListItem_t * const pxIndex = pxList->pxIndex;
/* Only effective when configASSERT() is also defined, these tests may catch
* the list data structures being overwritten in memory. They will not catch
* data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert a new list item into pxList, but rather than sort the list,
* makes the new list item the last item to be removed by a call to
* listGET_OWNER_OF_NEXT_ENTRY(). */
pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
/* Only used during decision coverage testing. */
mtCOVERAGE_TEST_DELAY();
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
/* Remember which list the item is in. */
pxNewListItem->pxContainer = pxList;
( pxList->uxNumberOfItems )++;
}
/*-----------------------------------------------------------*/
void vListInsert( List_t * const pxList,
ListItem_t * const pxNewListItem )
{
ListItem_t * pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Only effective when configASSERT() is also defined, these tests may catch
* the list data structures being overwritten in memory. They will not catch
* data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert the new list item into the list, sorted in xItemValue order.
*
* If the list already contains a list item with the same item value then the
* new list item should be placed after it. This ensures that TCBs which are
* stored in ready lists (all of which have the same xItemValue value) get a
* share of the CPU. However, if the xItemValue is the same as the back marker
* the iteration loop below will not end. Therefore the value is checked
* first, and the algorithm slightly modified if necessary. */
if( xValueOfInsertion == portMAX_DELAY )
{
pxIterator = pxList->xListEnd.pxPrevious;
}
else
{
/* *** NOTE ***********************************************************
* If you find your application is crashing here then likely causes are
* listed below. In addition see https://www.FreeRTOS.org/FAQHelp.html for
* more tips, and ensure configASSERT() is defined!
* https://www.FreeRTOS.org/a00110.html#configASSERT
*
* 1) Stack overflow -
* see https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html
* 2) Incorrect interrupt priority assignment, especially on Cortex-M
* parts where numerically high priority values denote low actual
* interrupt priorities, which can seem counter intuitive. See
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html and the definition
* of configMAX_SYSCALL_INTERRUPT_PRIORITY on
* https://www.FreeRTOS.org/a00110.html
* 3) Calling an API function from within a critical section or when
* the scheduler is suspended, or calling an API function that does
* not end in "FromISR" from an interrupt.
* 4) Using a queue or semaphore before it has been initialised or
* before the scheduler has been started (are interrupts firing
* before vTaskStartScheduler() has been called?).
**********************************************************************/
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */
{
/* There is nothing to do here, just iterating to the wanted
* insertion position. */
}
}
pxNewListItem->pxNext = pxIterator->pxNext;
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
pxNewListItem->pxPrevious = pxIterator;
pxIterator->pxNext = pxNewListItem;
/* Remember which list the item is in. This allows fast removal of the
* item later. */
pxNewListItem->pxContainer = pxList;
( pxList->uxNumberOfItems )++;
}
/*-----------------------------------------------------------*/
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
/* The list item knows which list it is in. Obtain the list from the list
* item. */
List_t * const pxList = pxItemToRemove->pxContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
/* Only used during decision coverage testing. */
mtCOVERAGE_TEST_DELAY();
/* Make sure the index is left pointing to a valid item. */
if( pxList->pxIndex == pxItemToRemove )
{
pxList->pxIndex = pxItemToRemove->pxPrevious;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
pxItemToRemove->pxContainer = NULL;
( pxList->uxNumberOfItems )--;
return pxList->uxNumberOfItems;
}
/*-----------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,333 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdint.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
* is defined correctly and privileged functions are placed in correct sections. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* Portasm includes. */
#include "portasm.h"
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
* header files. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n"
#if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */
" \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */
" \n"
#if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */
" \n"
" .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */
);
}
/*-----------------------------------------------------------*/
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{
__asm volatile
(
" mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */
" \n"
" .align 4 \n"
::: "r0", "memory"
);
}
/*-----------------------------------------------------------*/
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */
::: "r0", "memory"
);
}
/*-----------------------------------------------------------*/
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{
__asm volatile
(
" mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */
::: "r0", "memory"
);
}
/*-----------------------------------------------------------*/
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n"
" dsb \n"
" isb \n"
" svc %0 \n"/* System call to start the first task. */
" nop \n"
" \n"
" .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory"
);
}
/*-----------------------------------------------------------*/
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n"
" isb \n"
" bx lr \n"/* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
);
}
/*-----------------------------------------------------------*/
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n"
" isb \n"
" bx lr \n"/* Return. */
::: "memory"
);
}
/*-----------------------------------------------------------*/
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" mrs r0, psp \n"/* Read PSP in r0. */
#if ( configENABLE_FPU == 1 )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
" it eq \n"
" vstmdbeq r0!, {s16-s31} \n"/* Store the FPU registers which are not saved automatically. */
#endif /* configENABLE_FPU */
#if ( configENABLE_MPU == 1 )
" mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
#else /* configENABLE_MPU */
" mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
#endif /* configENABLE_MPU */
" \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
" \n"
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n"
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n"/* Enable interrupts. */
" \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n"
#if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */
" \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n"
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */
" \n"
#if ( configENABLE_MPU == 1 )
" ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
#else /* configENABLE_MPU */
" ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#endif /* configENABLE_MPU */
" \n"
#if ( configENABLE_FPU == 1 )
" tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
" it eq \n"
" vldmiaeq r0!, {s16-s31} \n"/* Restore the FPU registers which are not restored automatically. */
#endif /* configENABLE_FPU */
" \n"
#if ( configENABLE_MPU == 1 )
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */
#else /* configENABLE_MPU */
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
#endif /* configENABLE_MPU */
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
" bx r3 \n"
" \n"
" .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);
}
/*-----------------------------------------------------------*/
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" ldr r1, svchandler_address_const \n"
" bx r1 \n"
" \n"
" .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n"
);
}
/*-----------------------------------------------------------*/

View File

@@ -0,0 +1,126 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
#ifndef __PORT_ASM_H__
#define __PORT_ASM_H__
/* Scheduler includes. */
#include "FreeRTOS.h"
/* MPU wrappers includes. */
#include "mpu_wrappers.h"
/**
* @brief Restore the context of the first task so that the first task starts
* executing.
*/
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Checks whether or not the processor is privileged.
*
* @return 1 if the processor is already privileged, 0 otherwise.
*/
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
/**
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
* register.
*
* @note This is a privileged function and should only be called from the kenrel
* code.
*
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
* Bit[0] = 0 --> The processor is running privileged
* Bit[0] = 1 --> The processor is running unprivileged.
*/
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register.
*
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
* Bit[0] = 0 --> The processor is running privileged
* Bit[0] = 1 --> The processor is running unprivileged.
*/
void vResetPrivilege( void ) __attribute__( ( naked ) );
/**
* @brief Starts the first task.
*/
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Disables interrupts.
*/
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Enables interrupts.
*/
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief PendSV Exception handler.
*/
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief SVC Handler.
*/
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Allocate a Secure context for the calling task.
*
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
* secure side for the calling task.
*/
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
/**
* @brief Free the task's secure context.
*
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
*/
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
#endif /* __PORT_ASM_H__ */

View File

@@ -0,0 +1,325 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/*------------------------------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the given hardware
* and compiler.
*
* These settings should not be altered.
*------------------------------------------------------------------------------
*/
#ifndef configENABLE_FPU
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
#endif /* configENABLE_FPU */
#ifndef configENABLE_MPU
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
#endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
#endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/
/**
* @brief Type definitions.
*/
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
/**
* Architecture specifics.
*/
#define portARCH_NAME "Cortex-M33"
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
#define portNOP()
#define portINLINE __inline
#ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif
#define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/
/**
* @brief Extern declarations.
*/
extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */
#if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/
/**
* @brief MPU specific constants.
*/
#if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL )
#else
#define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */
/* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers.
*
* 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE
* 10 --> Device-nGRE
* 11 --> Device-GRE
* Bit[1:0] - 00, Reserved.
*/
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/
/**
* @brief Settings to define an MPU region.
*/
typedef struct MPURegionSettings
{
uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t;
/**
* @brief MPU settings as stored in the TCB.
*/
typedef struct MPU_SETTINGS
{
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS;
/*-----------------------------------------------------------*/
/**
* @brief SVC numbers.
*/
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/
/**
* @brief Scheduler utilities.
*/
#define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/**
* @brief Critical section management.
*/
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
/**
* @brief Tickless idle/low power functionality.
*/
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif
/*-----------------------------------------------------------*/
/**
* @brief Task function macros as described on the FreeRTOS.org WEB site.
*/
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/
#if ( configENABLE_TRUSTZONE == 1 )
/**
* @brief Allocate a secure context for the task.
*
* Tasks are not created with a secure context. Any task that is going to call
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
* secure context before it calls any secure function.
*
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
*/
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/**
* @brief Called when a task is deleted to delete the task's secure context,
* if it has one.
*
* @param[in] pxTCB The TCB of the task being deleted.
*/
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
/**
* @brief Checks whether or not the processor is privileged.
*
* @return 1 if the processor is already privileged, 0 otherwise.
*/
#define portIS_PRIVILEGED() xIsPrivileged()
/**
* @brief Raise an SVC request to raise privilege.
*
* The SVC handler checks that the SVC was raised from a system call and only
* then it raises the privilege. If this is called from any other place,
* the privilege is not raised.
*/
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
/**
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register.
*/
#define portRESET_PRIVILEGE() vResetPrivilege()
#else
#define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/
/**
* @brief Barriers.
*/
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View File

@@ -0,0 +1,107 @@
/***************************************************************************//**
* # License
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is Third Party Software licensed by Silicon Labs from a third party
* and is governed by the sections of the MSLA applicable to Third Party
* Software and the additional terms set forth below.
*
******************************************************************************/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
/*
* Implementation of pvPortMalloc() and vPortFree() that relies on the
* compilers own malloc() and free() implementations.
*
* This file can only be used if the linker is configured to to generate
* a heap memory area.
*
* See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the
* memory management pages of https://www.FreeRTOS.org for more information.
*/
#include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
* all the API functions to use the MPU wrappers. That should only be done when
* task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#include "FreeRTOS.h"
#include "task.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
#endif
/*-----------------------------------------------------------*/
void * pvPortMalloc( size_t xWantedSize )
{
void * pvReturn;
vTaskSuspendAll();
{
pvReturn = malloc( xWantedSize );
traceMALLOC( pvReturn, xWantedSize );
}
( void ) xTaskResumeAll();
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
{
if( pvReturn == NULL )
{
extern void vApplicationMallocFailedHook( void );
vApplicationMallocFailedHook();
}
}
#endif
return pvReturn;
}
/*-----------------------------------------------------------*/
void vPortFree( void * pv )
{
if( pv )
{
vTaskSuspendAll();
{
free( pv );
traceFREE( pv, 0 );
}
( void ) xTaskResumeAll();
}
}

View File

@@ -0,0 +1,232 @@
/***************************************************************************//**
* @file
* @brief FreeRTOS Tick and Sleep port.
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
/* Compiler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "portmacro.h"
#include "sl_sleeptimer.h"
#include "sl_atomic.h"
#include "sl_power_manager.h"
#if configUSE_TICKLESS_IDLE == 0
#error "This port requires configUSE_TICKLESS_IDLE to be enabled."
#endif
/* Local variables */
/* Number of lf ticks per OS ticks. */
static uint32_t lfticks_per_os_ticks = 0;
/* Tick count (in lf ticks) last time the tick count was updated in FreeRTOS. */
static uint32_t last_update_lftick = 0;
/* Indicates if system is sleeping. */
static bool is_sleeping = false;
/* Maximum number of os ticks the system can sleep per call. */
static TickType_t max_sleep_os_ticks = 0;
/* Expected sleep ticks */
static TickType_t expected_sleep_ticks = 0;
/* Total ticks slept */
static TickType_t total_slept_os_ticks = 0;
/* Handle to schedule wakeup timer. */
static sl_sleeptimer_timer_handle_t schedule_wakeup_timer_handle;
/* Local functions */
static void sli_schedule_wakeup_timer_expire_handler(sl_sleeptimer_timer_handle_t *handle,
void *data);
static void sli_os_schedule_wakeup(TickType_t os_ticks);
/***************************************************************************//**
* Sets up sleeptimer timer for constant ticking.
******************************************************************************/
void vPortSetupTimerInterrupt( void )
{
uint32_t sleeptimer_freq;
/* FreeRTOS requires a high SVC priority when starting the scheduler */
NVIC_SetPriority(SVCall_IRQn, 0);
sleeptimer_freq = sl_sleeptimer_get_timer_frequency();
configASSERT( configTICK_RATE_HZ <= sleeptimer_freq );
lfticks_per_os_ticks = (sleeptimer_freq + (configTICK_RATE_HZ - 1)) / configTICK_RATE_HZ;
max_sleep_os_ticks = (0xFFFFFFFF / lfticks_per_os_ticks) - 10;
last_update_lftick = sl_sleeptimer_get_tick_count();
/* Schedule a wakeup in one tick. */
sli_os_schedule_wakeup(1);
}
/***************************************************************************//**
* Stop constant ticking and wake the system up after specified idle time.
*
* @param xExpectedIdleTime Time in os ticks that the system is expected to
* sleep.
******************************************************************************/
SL_WEAK void sli_iot_power_set_expected_idle(TickType_t expected_idle)
{
(void)expected_idle;
return;
}
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
sl_atomic_store(is_sleeping, true);
/* Schedule a wakeup for expected idle end time. */
sl_sleeptimer_stop_timer(&schedule_wakeup_timer_handle);
sli_os_schedule_wakeup(xExpectedIdleTime);
configPRE_SLEEP_PROCESSING( xExpectedIdleTime );
sli_iot_power_set_expected_idle(xExpectedIdleTime);
expected_sleep_ticks = xExpectedIdleTime;
total_slept_os_ticks = 0;
sl_power_manager_sleep();
configPOST_SLEEP_PROCESSING( total_slept_os_ticks );
sl_atomic_store(is_sleeping, false);
/* Schedule a wakeup in one tick. */
sl_sleeptimer_stop_timer(&schedule_wakeup_timer_handle);
sli_os_schedule_wakeup(1);
}
/***************************************************************************//**
* Function called when schedule wakeup timer expires.
******************************************************************************/
static void sli_schedule_wakeup_timer_expire_handler(sl_sleeptimer_timer_handle_t *handle, void *data)
{
uint32_t current_tick_count = sl_sleeptimer_get_tick_count();
(void)handle;
(void)data;
uint32_t originalMask = portSET_INTERRUPT_MASK_FROM_ISR();
/* If system was not sleeping, update lfticks counter. */
if (!is_sleeping) {
bool sched = false;
/* Increment the RTOS tick. */
while ((current_tick_count - last_update_lftick) >= lfticks_per_os_ticks) {
sched |= xTaskIncrementTick();
last_update_lftick += lfticks_per_os_ticks;
}
if ( sched != pdFALSE ) {
/* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */
portYIELD();
}
sli_os_schedule_wakeup(1);
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(originalMask);
}
/***************************************************************************//**
* (Re)-start schedule wakeup timer with delay specified.
*
* @param os_ticks Delay, in os ticks, before next wakeup/tick.
******************************************************************************/
static void sli_os_schedule_wakeup(TickType_t os_ticks)
{
sl_status_t status;
uint32_t lf_ticks_to_sleep;
TickType_t os_ticks_to_sleep;
uint32_t current_tick_count = sl_sleeptimer_get_tick_count();
/* Compute number of lfticks to sleep. */
os_ticks_to_sleep = (os_ticks <= max_sleep_os_ticks) ? os_ticks : max_sleep_os_ticks;
/* This function implements a correction mechanism that corrects any drift that can */
/* occur between the sleep timer time and the tick count in FreeRTOS. */
lf_ticks_to_sleep = os_ticks_to_sleep * lfticks_per_os_ticks;
if (lf_ticks_to_sleep <= (current_tick_count - last_update_lftick)) {
lf_ticks_to_sleep = 1;
} else {
lf_ticks_to_sleep -= (current_tick_count - last_update_lftick);
}
status = sl_sleeptimer_start_timer(&schedule_wakeup_timer_handle,
lf_ticks_to_sleep,
sli_schedule_wakeup_timer_expire_handler,
0,
0,
0);
configASSERT( status == SL_STATUS_OK );
#if (configASSERT_DEFINED == 0)
(void)status;
#endif
}
/***************************************************************************//**
* Function called by power manager to ensure that system is ok to sleep.
******************************************************************************/
SL_WEAK bool sli_iot_power_ok_to_sleep(void)
{
return true;
}
bool sl_power_manager_is_ok_to_sleep(void)
{
return sli_iot_power_ok_to_sleep() && (eTaskConfirmSleepModeStatus() != eAbortSleep);
}
/***************************************************************************//**
* Function called by power manager to determine if system can go back to sleep
* after a wakeup.
*
* @note Function is called in critical section
******************************************************************************/
bool sl_power_manager_sleep_on_isr_exit(void)
{
uint32_t slept_lf_ticks;
uint32_t slept_os_ticks;
/* Determine how long we slept. */
slept_lf_ticks = sl_sleeptimer_get_tick_count() - last_update_lftick;
slept_os_ticks = slept_lf_ticks / lfticks_per_os_ticks;
last_update_lftick += slept_os_ticks * lfticks_per_os_ticks;
/* Notify FreeRTOS of how long we slept. */
if ((total_slept_os_ticks + slept_os_ticks) < expected_sleep_ticks) {
vTaskStepTick(slept_os_ticks);
total_slept_os_ticks += slept_os_ticks;
} else {
vTaskStepTick(expected_sleep_ticks - total_slept_os_ticks);
total_slept_os_ticks = expected_sleep_ticks;
}
/* Have we slept enough ? */
if (total_slept_os_ticks >= expected_sleep_ticks) {
return false;
}
/* Check if we can sleep again */
return (eTaskConfirmSleepModeStatus() != eAbortSleep);
}

3029
Libs/FreeRTOS/kernel/queue.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

5408
Libs/FreeRTOS/kernel/tasks.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
/***************************************************************************//**
* @file
* @brief API "assert" implementation.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_ASSERT_H
#define SL_ASSERT_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(DOXY_DOC_ONLY)
/** Included for documentation purposes only. This define is not present by default.
* DEBUG_EFM should be defined from the compiler to enable the default internal
* assert handler. */
#define DEBUG_EFM
#endif
#if defined(DEBUG_EFM) || defined(DEBUG_EFM_USER)
/***************************************************************************//**
* @addtogroup assert ASSERT - Assert
* @brief Assert/error checking module
* @details
* By default, library assert usage is not included to reduce
* footprint and processing overhead. Further, assert usage is decoupled
* from ISO C assert handling (NDEBUG usage) to allow using ISO C
* assert without including assert statements.
*
* Below are available defines for controlling assert inclusion. The defines
* are typically for a project to be used by the preprocessor.
*
* @li If DEBUG_EFM is defined, the internal library assert handling will
* be used. This is implemented as a simple while(true) loop. DEBUG_EFM is not
* defined by default.
*
* @li If DEBUG_EFM_USER is defined, the user must provide custom
* implementation of the assertEFM() function.
*
* @li If both DEBUG_EFM and DEBUG_EFM_USER are undefined, all EFM_ASSERT()
* statements are not operational.
*
* @note
* The internal assert is documented because DEBUG_EFM is defined in
* the doxygen configuration.
* @{
******************************************************************************/
/* Due to footprint considerations, we only pass file name and line number, */
/* not the assert expression (nor function name (C99)) */
/***************************************************************************//**
* @brief
* Assert function for EFM.
* @param[in] file - path and file name of the assert.
*
* @param[in] line - line number, in the file.
******************************************************************************/
void assertEFM(const char *file, int line);
/** Default assertion is not operational */
#define EFM_ASSERT(expr) ((expr) ? ((void)0) : assertEFM(__FILE__, __LINE__))
#else
/** Default assertion is not operational */
#define EFM_ASSERT(expr) ((void)(expr))
#endif /* defined(DEBUG_EFM) || defined(DEBUG_EFM_USER) */
/** @} (end addtogroup assert) */
#ifdef __cplusplus
}
#endif
#endif /* SL_ASSERT_H */

View File

@@ -0,0 +1,80 @@
/*******************************************************************************
* @file
* @brief Implementation of atomic operations.
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_ATOMIC_H
#define SL_ATOMIC_H
/*******************************************************************************
* @addtogroup atomic Atomic Operations
* @brief Atomic operations provide RAM store and read functionalities.
* @n @section atomic_usage Atomic Operations Usage
* @{
******************************************************************************/
/***************************************************************************//**
* @brief Perform an atomic load. Use when a variable must be read from
* RAM.
*
* @param dest Variable where to copy the loaded value.
*
* @param source Variable from where to load the value.
*
* @note Does only support native types <= 32 bits.
*
* @note Load operation on 32 bit value is atomic on ARM architecture.
*
* @note Only the load operation from 'source' is guaranteed to be
* performed atomically. If writing to 'dest' implies a store,
* the load and store operations are not guaranteed to be
* performed atomically.
******************************************************************************/
#define sl_atomic_load(dest, source) ((dest) = (source))
/*******************************************************************************
* @brief Perform an atomic store. Use when a value must be stored in
* RAM.
*
* @param dest Variable where to store the value.
*
* @param source Variable that contains the value to store in 'dest'.
*
* @note Does only support native types <= 32 bits.
*
* @note Store operation on 32 bit value is atomic on ARM architecture.
*
* @note Only the store operation to 'dest' is guaranteed to be
* performed atomically. If reading from 'source' implies a load,
* the store and load operations are not guaranteed to be
* performed atomically.
******************************************************************************/
#define sl_atomic_store(dest, source) ((dest) = (source))
/** @} (end addtogroup atomic) */
#endif /* SL_ATOMIC_H */

View File

@@ -0,0 +1,189 @@
/***************************************************************************//**
* @file
* @brief Implementation of bit operations.
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_BIT_H
#define SL_BIT_H
/***************************************************************************//**
* @addtogroup bit Bit Manipulation
* @brief Bitwise operations
* @{
******************************************************************************/
/****************************************************************************************************//**
* SL_DEF_BIT()
*
* @brief Create bit mask with single, specified bit set.
*
* @param bit Bit number of bit to set.
*
* @return Bit mask with single, specified bit set.
*
* @note (1) 'bit' SHOULD be a non-negative integer.
*
* @note (2) 'bit' values that overflow the target CPU &/or compiler environment (e.g. negative
* or greater-than-CPU-data-size values) MAY generate compiler warnings &/or errors.
*******************************************************************************************************/
#define SL_DEF_BIT(bit) (1u << (bit))
/****************************************************************************************************//**
* SL_SET_BIT()
*
* @brief Set specified bit(s) in a value.
*
* @param val Value to modify by setting specified bit(s).
*
* @param mask Mask of bits to set.
*
* @return Modified value with specified bit(s) set.
*
* @note 'val' & 'mask' SHOULD be unsigned integers.
*******************************************************************************************************/
#define SL_SET_BIT(val, mask) ((val) = ((val) | (mask)))
/****************************************************************************************************//**
* SL_CLEAR_BIT()
*
* @brief Clear specified bit(s) in a value.
*
* @param val Value to modify by clearing specified bit(s).
*
* @param mask Mask of bits to clear.
*
* @return Modified value with specified bit(s) clear.
*
* @note 'val' & 'mask' SHOULD be unsigned integers.
*
* @note 'mask' SHOULD be cast with the same data type than 'val'.
*******************************************************************************************************/
#define SL_CLEAR_BIT(val, mask) ((val) = ((val) & (~(mask))))
/****************************************************************************************************//**
* SL_IS_BIT_SET()
*
* @brief Determine whether the specified bit(s) in a value are set.
*
* @param val Value to check for specified bit(s) set.
*
* @param mask Mask of bits to check if set.
*
* @return true, if ALL specified bit(s) are set in value.
*
* false, if ALL specified bit(s) are NOT set in value.
*
* @note 'val' & 'mask' SHOULD be unsigned integers.
*
* @note NULL 'mask' allowed; returns 'false' since NO mask bits specified.
*******************************************************************************************************/
#define SL_IS_BIT_SET(val, mask) (((((val) & (mask)) == (mask)) && ((mask) != 0u)) ? (true) : (false))
/****************************************************************************************************//**
* SL_IS_BIT_CLEAR()
*
* @brief Determine whether the specified bit(s) in a value are clear.
*
* @param val Value to check for specified bit(s) clear.
*
* @param mask Mask of bits to check if clear.
*
* @return true, if ALL specified bit(s) are clear in value.
*
* false, if ALL specified bit(s) are NOT clear in value.
*
* @note val' & 'mask' SHOULD be unsigned integers.
*
* @note NULL 'mask' allowed; returns 'false' since NO mask bits specified.
*******************************************************************************************************/
#define SL_IS_BIT_CLEAR(val, mask) (((((val) & (mask)) == 0u) && ((mask) != 0u)) ? (true) : (false))
/****************************************************************************************************//**
* SL_IS_ANY_BIT_SET()
*
* @brief Determine whether any specified bit(s) in a value are set.
*
* @param val Value to check for specified bit(s) set.
*
* @param mask Mask of bits to check if set (see Note #2).
*
* @return true, if ANY specified bit(s) are set in value.
*
* false, if ALL specified bit(s) are NOT set in value.
*
* @note 'val' & 'mask' SHOULD be unsigned integers.
*
* @note NULL 'mask' allowed; returns 'false' since NO mask bits specified.
*******************************************************************************************************/
#define SL_IS_ANY_BIT_SET(val, mask) ((((val) & (mask)) == 0u) ? (false) : (true))
/****************************************************************************************************//**
* SL_IS_ANY_BIT_CLEAR()
*
* @brief Determine whether any specified bit(s) in a value are clear.
*
* @param val Value to check for specified bit(s) clear.
*
* @param mask Mask of bits to check if clear (see Note #2).
*
* @return true, if ANY specified bit(s) are clear in value.
*
* false, if ALL specified bit(s) are NOT clear in value.
*
* @note 'val' & 'mask' SHOULD be unsigned integers.
*
* @note NULL 'mask' allowed; returns 'false' since NO mask bits specified.
*******************************************************************************************************/
#define SL_IS_ANY_BIT_CLEAR(val, mask) ((((val) & (mask)) == (mask)) ? (false) : (true))
/****************************************************************************************************//**
* SL_MATH_IS_PWR2()
*
* @brief Determine if a value is a power of 2.
*
* @param val Value.
*
* @return true, 'val' is a power of 2.
* false, 'val' is not a power of 2.
*******************************************************************************************************/
#define SL_MATH_IS_PWR2(val) ((((val) != 0u) && (((val) & ((val) - 1u)) == 0u)) ? true : false)
/*******************************************************************************
****************************** DEFINES ************************************
******************************************************************************/
/** @} (end addtogroup bit) */
#endif /* SL_BIT_H */

View File

@@ -0,0 +1,200 @@
/***************************************************************************//**
* @file sl_cmsis_os2_common.h
* @brief OS-agnostic header to provide CMSIS OS-Specific APIs like typedefs.
* @version x.y.z
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_CMSIS_OS2_COMMON_H
#define SL_CMSIS_OS2_COMMON_H
#include <stdint.h>
#include "cmsis_os2.h"
#include "sl_status.h"
#if defined(SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#endif
// Validate the chosen RTOS
#if !defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && !defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
#error "The extended CMSIS RTOS2 API currently only supports FreeRTOS or MicriumOS"
#endif
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
#include "FreeRTOS.h"
#elif defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
#include "os.h"
#endif
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
#define osEventFlagsCbSize sizeof(StaticEventGroup_t)
#define osThreadCbSize sizeof(StaticTask_t)
#define osTimerCbSize sizeof(StaticTimer_t)
#define osMutexCbSize sizeof(StaticSemaphore_t)
#define osSemaphoreCbSize sizeof(StaticSemaphore_t)
#define osMessageQueueCbSize sizeof(StaticQueue_t)
#define osAlignment (portBYTE_ALIGNMENT)
typedef StaticEventGroup_t osEventFlags_t;
typedef StaticTask_t osThread_t;
typedef StaticTimer_t osTimer_t;
typedef StaticSemaphore_t osMutex_t;
typedef StaticSemaphore_t osSemaphore_t;
typedef StaticQueue_t osMessageQueue_t;
#elif defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
typedef struct {
OS_TCB tcb; // This must be the first element, used by OSTCBCurPtr
#if (OS_CFG_FLAG_EN == DEF_ENABLED)
OS_FLAG_GRP flag_grp;
#endif
#if (OS_CFG_MUTEX_EN == DEF_ENABLED)
OS_MUTEX join_mutex;
#endif
uint8_t obj_dyn_alloc;
uint8_t stack_dyn_alloc;
uint32_t attr_bits;
} osThread_t;
#if (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED)
typedef struct {
sl_sleeptimer_timer_handle_t handle;
osTimerFunc_t callback;
void *callback_data;
osTimerType_t type;
const char *name;
uint8_t dyn_alloc;
} osTimer_t;
#endif
#if (OS_CFG_FLAG_EN == DEF_ENABLED)
typedef struct {
OS_FLAG_GRP flag_grp;
uint8_t dyn_alloc;
uint32_t flags;
} osEventFlags_t;
#endif
#if (OS_CFG_MUTEX_EN == DEF_ENABLED)
typedef struct {
OS_MUTEX mutex;
uint8_t dyn_alloc;
uint8_t recursive;
} osMutex_t;
#endif
#if (OS_CFG_SEM_EN == DEF_ENABLED)
typedef struct {
OS_SEM sem;
uint8_t dyn_alloc;
uint32_t max_ctr;
} osSemaphore_t;
#endif
#if (OS_CFG_SEM_EN == DEF_ENABLED)
typedef struct {
OS_SEM sem_put;
OS_SEM sem_get;
uint8_t *buf;
uint8_t obj_dyn_alloc;
uint8_t buf_dyn_alloc;
uint32_t msg_count;
uint32_t msg_size;
uint32_t msg_queued;
uint32_t msg_head;
uint32_t msg_tail;
} osMessageQueue_t;
#endif
#if (OS_CFG_SEM_EN == DEF_ENABLED)
typedef struct {
OS_SEM sem;
uint8_t *buf;
uint8_t obj_dyn_alloc;
uint8_t buf_dyn_alloc;
uint32_t block_count;
uint32_t block_size;
uint32_t free_count;
uint32_t free_head;
} osMemoryPool_t;
#endif
#if (OS_CFG_FLAG_EN == DEF_ENABLED)
#define osEventFlagsCbSize sizeof(osEventFlags_t)
#endif
#define osThreadCbSize sizeof(osThread_t)
#if (OS_CFG_TMR_EN == DEF_ENABLED)
#define osTimerCbSize sizeof(osTimer_t)
#endif
#if (OS_CFG_MUTEX_EN == DEF_ENABLED)
#define osMutexCbSize sizeof(osMutex_t)
#endif
#if (OS_CFG_SEM_EN == DEF_ENABLED)
#define osSemaphoreCbSize sizeof(osSemaphore_t)
#endif
#if (OS_CFG_SEM_EN == DEF_ENABLED)
#define osMessageQueueCbSize sizeof(osMessageQueue_t)
#endif
#if (OS_CFG_SEM_EN == DEF_ENABLED)
#define osMemoryPoolCbSize sizeof(osMemoryPool_t)
#endif
#define osAlignment sizeof(CPU_ALIGN)
#endif // SL_CATALOG_MICRIUMOS_KERNEL_PRESENT
// -----------------------------------------------------------------------------
// Functions
#ifdef __cplusplus
extern "C" {
#endif
/********************************************************************************************************
* sl_cmsis_os_convert_status()
*
* @brief Convert OsStatus from CMSIS-RTOS2 to sl_status type.
*
* @param os_status The OS status code returned by CMSIS-RTOS2 API.
*
* @return Status code converted to sl_status.
*******************************************************************************************************/
sl_status_t sl_cmsis_os_convert_status(osStatus_t os_status);
#ifdef __cplusplus
}
#endif
#endif // SL_CMSIS_OS2_COMMON_H

View File

@@ -0,0 +1,75 @@
/***************************************************************************//**
* @file
* @brief Code Classification API
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef _SL_CODE_CLASSIFICATION_H_
#define _SL_CODE_CLASSIFICATION_H_
#include "sli_code_classification.h"
// NOTE: This API is for use by applications only.
/**************************************************************************//**
* @addtogroup code_placement
* @brief Code Classification API
* @{
*****************************************************************************/
/******************************************************************************/
/* Macro API */
/******************************************************************************/
#if defined(__GNUC__) && !defined(__llvm__)
// With GCC, __attribute__ can be used to specify the input section of
// functions.
/// Prepend a function definition with this macro to place it in RAM.
#define SL_CODE_RAM \
__attribute__((section("text_application_ram")))
#elif defined(__ICCARM__)
// With IAR, _Pragma can be used to specify the input section of
// functions.
/// Prepend a function definition with this macro to place it in RAM.
#define SL_CODE_RAM \
_Pragma("location =\"text_application_ram\"")
#elif defined(__llvm__)
#define SL_CODE_RAM
#else
#error "(sl_code_classification.h): Code classification does not support \
the chosen compiler."
#endif // __GNUC__
/** @} (end addtogroup code_placement) */
#endif // _SL_CODE_CLASSIFICATION_H_

View File

@@ -0,0 +1,420 @@
/***************************************************************************//**
* @file
* @brief General purpose utilities.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_COMMON_H
#define SL_COMMON_H
#include <stdint.h>
#include <stdbool.h>
#include "sl_assert.h"
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(__STATIC_INLINE)
#if !defined(__unix__) && defined(__arm__)
/* Compiler agnostic definitions */
#include "cmsis_compiler.h"
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define __STATIC_INLINE static inline
#else
#warning Please provide a macro for your compiler and architecture
#define __STATIC_INLINE static
#endif
#endif
/***************************************************************************//**
* @addtogroup common COMMON - Common Utilities
* @brief General purpose utilities and cross-compiler support
* @details
* This SDK supports the following compilers/IDEs:
* @li Simplicity Studio
* @li IAR Embedded Workbench
* @li Keil uVision IDE
* @li Plain armgcc
*
* Certain compiler features such as alignment is implemented differently in the tools.
* Therefore, macros such as @ref SL_ALIGN are provided to enable compiler independent
* code.
*
* @note RAM code macros are implemented in [RAMFUNC](/gecko-platform/<docspace-docleaf-version>/emlib-efm32g/).
* Cross-compiler RAM code support needs extended documentation and it is therefore
* implemented as a separate module.
*
* @{
******************************************************************************/
/** @brief Macros to concatenate. */
#define _CONCAT_2(first, second) first ## second
#define SL_CONCAT_PASTER_2(first, second) _CONCAT_2(first, second) ///< sl concat paster 2.
#define _CONCAT_3(first, second, third) first ## second ## third
#define SL_CONCAT_PASTER_3(first, second, third) _CONCAT_3(first, second, third) ///< sl concat paster 3.
#define _CONCAT_4(first, second, third, fourth) first ## second ## third ## fourth
#define SL_CONCAT_PASTER_4(first, second, third, fourth) _CONCAT_4(first, second, third, fourth) ///< sl concat paster 4.
/** @brief Round n up to closest interval of i. */
#define SL_CEILING(n, i) ((((n) + (i) - 1U) / (i)) * (i))
/** @brief Round n down to closest interval of i. */
#define SL_FLOOR(n, i) ((n / i) * i)
/** @brief Stringify X */
#define STRINGIZE(X) #X
#if !defined(__GNUC__)
/* Not GCC compilers */
/** @brief Macros for giving the compiler hints about the likelihood of a branch. */
#define SL_BRANCH_LIKELY(x) (x)
#define SL_BRANCH_UNLIKELY(x) (x)
/** @brief Macro for getting minimum value. */
#define SL_MIN(a, b) ((a) < (b) ? (a) : (b))
/** @brief Macro for getting maximum value. */
#define SL_MAX(a, b) ((a) > (b) ? (a) : (b))
/** @brief Macros for handling packed structures. */
#define SL_PACK_START(X) _Pragma(STRINGIZE(pack(X)))
#define SL_PACK_END() _Pragma("pack()")
#define SL_ATTRIBUTE_PACKED
#if defined(__CC_ARM)
/** @brief MDK-ARM compiler: Macros for handling aligned structures. */
#define SL_ALIGN(X) __align(X)
/** MDK-ARM compiler: Macro for handling weak symbols. */
#define SL_WEAK __attribute__ ((weak))
/** MDK-ARM compiler: Macro for handling non-returning functions. */
#define SL_NORETURN __attribute__ ((noreturn))
/** MDK-ARM compiler: Macro for handling section placement */
#define SL_ATTRIBUTE_SECTION(X) __attribute__ ((section(X)))
#endif
#if defined(__ICCARM__)
#if (__VER__ >= 8000000)
/** @brief Obsoleted macro from version 8.00 and on . */
#define _STD_BEGIN
/** @brief Obsoleted macro from version 8.00 and on . */
#define _STD_END
#endif
/** @brief IAR Embedded Workbench: Macros for handling aligned structures. */
#define SL_ALIGN(X) _Pragma(STRINGIZE(data_alignment = X))
/** @brief IAR Embedded Workbench: Macros for handling weak symbols. */
#define SL_WEAK __weak
/** @brief IAR Embedded Workbench: Macro for handling non-returning functions. */
#define SL_NORETURN __noreturn
/* *INDENT-OFF* */
/** IAR Embedded Workbench: Macro for handling section placement */
#define SL_ATTRIBUTE_SECTION(X) @ X
#endif
/* *INDENT-ON* */
#define SL_ATTRIBUTE_ALIGN(X)
/** @brief Macro for notifying the compiler of an intended
* switch case fallthrough. */
#define SL_FALLTHROUGH
/** @brief A macro for notifying the compiler to ignore type limit check. */
#define SL_IGNORE_TYPE_LIMIT_BEGIN
#define SL_IGNORE_TYPE_LIMIT_END
#else // !defined(__GNUC__)
/* GCC compilers */
/** @brief Macros for giving the compiler hints about the likelihood of a branch. */
#define SL_BRANCH_LIKELY(x) __builtin_expect(!!(x), 1)
#define SL_BRANCH_UNLIKELY(x) __builtin_expect(!!(x), 0)
/** @brief A macro for getting the minimum value. No side-effects, a and b are evaluated one time only. */
#define SL_MIN(a, b) __extension__({ __typeof__(a)_a = (a); __typeof__(b)_b = (b); _a < _b ? _a : _b; })
/** @brief A macro for getting the maximum value. No side-effects, a and b are evaluated one time only. */
#define SL_MAX(a, b) __extension__({ __typeof__(a)_a = (a); __typeof__(b)_b = (b); _a > _b ? _a : _b; })
/** @brief A GCC style macro for handling packed structures. */
#define SL_ATTRIBUTE_PACKED __attribute__ ((packed))
/** @brief A macro for handling packed structures.
* @n Use this macro before the structure definition.
* @n X denotes the maximum alignment of structure members. X is not supported with
* GCC. GCC always uses 1 byte maximum alignment.
*/
#define SL_PACK_START(x)
/** @brief A macro for handling packed structures.
* @n Use this macro after the structure definition.
* @n With GCC, add SL_ATTRIBUTE_PACKED after the closing curly braces of the structure
* definition.
*/
#define SL_PACK_END()
/** @brief GCC style macro for aligning a variable. */
#define SL_ATTRIBUTE_ALIGN(X) __attribute__ ((aligned(X)))
/** @brief A macro for aligning a variable.
* @n Use this macro before the variable definition.
* @n X denotes the storage alignment value in bytes.
* @n To be GCC-compatible, use SL_ATTRIBUTE_ALIGN(X) before the semicolon on normal
* variables. Use SL_ATTRIBUTE_ALIGN(X) before the opening curly brace on structure variables.
*/
#define SL_ALIGN(X)
/** @brief A macro for defining a weak symbol. */
#define SL_WEAK __attribute__ ((weak))
/** @brief A macro for handling non-returning functions. */
#define SL_NORETURN __attribute__ ((noreturn))
/** A macro for placing a variable in a section.
* @n Use this macro after the variable definition, before the equal sign or a semicolon.
* @n X denotes the section to place the variable in.
*/
#define SL_ATTRIBUTE_SECTION(X) __attribute__ ((section(X)))
/** @brief A macro for notifying the compiler of an intended
* switch case fallthrough. */
#if __GNUC__ >= 7
#define SL_FALLTHROUGH __attribute__ ((fallthrough));
#else
#define SL_FALLTHROUGH
#endif
/** @brief A macro for notifying the compiler to ignore type limit check. */
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#define SL_IGNORE_TYPE_LIMIT_BEGIN \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"")
#define SL_IGNORE_TYPE_LIMIT_END \
_Pragma("GCC diagnostic pop")
#else
#define SL_IGNORE_TYPE_LIMIT_BEGIN
#define SL_IGNORE_TYPE_LIMIT_END ///< A MACRO to notify the compiler, limit END.
#endif
#endif // !defined(__GNUC__)
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/** @brief
* Macro for marking deprecated functions
*
* @details
* SL_DEPRECATED_API_SDK_<RELEASE> is used to mark functions that are
* deprecated and should not be used from a given version of the SDK.
* The accompanying SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_<RELEASE>
* define can be set to suppress warnings generated when using
* deprecated APIs.
*/
#ifdef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_3_0
#define SL_DEPRECATED_API_SDK_3_0
#else
#define SL_DEPRECATED_API_SDK_3_0 __attribute__ ((deprecated))
#endif
#ifdef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_3_2
#define SL_DEPRECATED_API_SDK_3_2
#else
#define SL_DEPRECATED_API_SDK_3_2 __attribute__ ((deprecated))
#endif
#ifdef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_3_3
#define SL_DEPRECATED_API_SDK_3_3
#else
#define SL_DEPRECATED_API_SDK_3_3 __attribute__ ((deprecated))
#endif
#ifdef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_4_1
#define SL_DEPRECATED_API_SDK_4_1
#else
#define SL_DEPRECATED_API_SDK_4_1 __attribute__ ((deprecated))
#endif
#ifdef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_4_2
#define SL_DEPRECATED_API_SDK_4_2
#else
#define SL_DEPRECATED_API_SDK_4_2 __attribute__ ((deprecated))
#endif
#ifdef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_4_4
#define SL_DEPRECATED_API_SDK_4_4
#else
#define SL_DEPRECATED_API_SDK_4_4 __attribute__ ((deprecated))
#endif
#ifdef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_2024_6
#define SL_DEPRECATED_API_SDK_2024_6
#else
#define SL_DEPRECATED_API_SDK_2024_6 __attribute__ ((deprecated))
#endif
/** @endcond */
/***************************************************************************//**
* @brief
* Count trailing number of zeros. Use CLZ instruction if available.
*
* @param[in] value
* Data value to check for number of trailing zero bits.
*
* @return
* A number of trailing zeros in value.
******************************************************************************/
__STATIC_INLINE uint32_t SL_CTZ(uint32_t value)
{
#if defined(__CORTEX_M) && (__CORTEX_M >= 3U)
return __CLZ(__RBIT(value));
#else
uint32_t zeros;
for (zeros = 0; (zeros < 32) && ((value & 0x1) == 0); zeros++, value >>= 1) {
;
}
return zeros;
#endif
}
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/* Deprecated function. New code should use @ref SL_CTZ. */
__STATIC_INLINE uint32_t EFM32_CTZ(uint32_t value)
{
return SL_CTZ(value);
}
/** @endcond */
/***************************************************************************//**
* @brief
* Reverse the bits. Use the RBIT instruction if available, else process.
*
* @param[in] value
* Data value to reverse.
*
* @return
* A reversed value.
******************************************************************************/
__STATIC_INLINE uint32_t SL_RBIT(uint32_t value)
{
uint32_t result;
#if defined(__CORTEX_M) && (__CORTEX_M >= 0x03U)
result = __RBIT(value);
#else
int32_t s = 4 * 8 - 1;
result = value;
for (value >>= 1U; value != 0U; value >>= 1U) {
result <<= 1U;
result |= value & 1U;
s--;
}
result <<= s;
#endif
return result;
}
/***************************************************************************//**
* @brief
* Reverse the bits. Use the RBIT instruction if available, else process.
*
* @param[in] value
* 16-bit data value to reverse.
*
* @return
* A 16-bit reversed value.
******************************************************************************/
__STATIC_INLINE uint16_t SL_RBIT16(uint16_t value)
{
return (uint16_t)(SL_RBIT(value) >> 16);
}
/***************************************************************************//**
* @brief
* Reverse the bits. Use the RBIT instruction if available, else process.
*
* @param[in] value
* 8-bit data value to reverse.
*
* @return
* A 8-bit reversed value.
******************************************************************************/
__STATIC_INLINE uint8_t SL_RBIT8(uint8_t value)
{
return (uint8_t)(SL_RBIT(value) >> 24);
}
/***************************************************************************//**
* @brief
* Convert logarithm of 2 to division factor.
*
* @param[in] log2
* Logarithm of 2.
*
* @return
* Dividend.
******************************************************************************/
__STATIC_INLINE uint32_t SL_Log2ToDiv(uint32_t log2)
{
EFM_ASSERT(log2 < 32U);
return 1UL << log2;
}
/***************************************************************************//**
* @brief
* Count the number of bits that are set to 1 in a 32-bit bitfield.
*
* @param[in] bitfield
* 32-bit bitfield.
*
* @return
* The number of bits that are set to 1 in the bitfield.
******************************************************************************/
__STATIC_INLINE uint32_t SL_POPCOUNT32(uint32_t bitfield)
{
bitfield = bitfield - ((bitfield >> 1) & 0x55555555);
bitfield = (bitfield & 0x33333333) + ((bitfield >> 2) & 0x33333333);
bitfield = (bitfield + (bitfield >> 4)) & 0x0F0F0F0F;
return (bitfield * 0x01010101) >> 24;
}
/** @} (end addtogroup common) */
#ifdef __cplusplus
}
#endif
#endif /* SL_COMMON_H */

View File

@@ -0,0 +1,210 @@
/***************************************************************************//**
* @file
* @brief Silabs Compiler definitions.
*******************************************************************************
* # License
* <b>Copyright 2022 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_COMPILER_H
#define SL_COMPILER_H
/***************************************************************************//**
* @addtogroup compiler Compiler definitions
* @brief Compiler definitions
* @{
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#if defined (__GNUC__)
// Fallback for __has_builtin.
#ifndef __has_builtin
#define __has_builtin(x) (0)
#endif
// Compiler specific defines.
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((__noreturn__))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed, aligned(1)))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma system_include
#if (__VER__ >= 8000000)
#define __ICCARM_V8 1
#else
#define __ICCARM_V8 0
#endif
#ifndef __ALIGNED
#if __ICCARM_V8
#define __ALIGNED(x) __attribute__((aligned(x)))
#elif (__VER__ >= 7080000)
/* Needs IAR language extensions */
#define __ALIGNED(x) __attribute__((aligned(x)))
#else
#warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#endif
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __NO_RETURN
#if __ICCARM_V8
#define __NO_RETURN __attribute__((__noreturn__))
#else
#define __NO_RETURN _Pragma("object_attribute=__noreturn")
#endif
#endif
#ifndef __PACKED
#if __ICCARM_V8
#define __PACKED __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
#define __PACKED __packed
#endif
#endif
#ifndef __PACKED_STRUCT
#if __ICCARM_V8
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
#define __PACKED_STRUCT __packed struct
#endif
#endif
#ifndef __PACKED_UNION
#if __ICCARM_V8
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
#define __PACKED_UNION __packed union
#endif
#endif
#ifndef __RESTRICT
#define __RESTRICT restrict
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __FORCEINLINE
#define __FORCEINLINE _Pragma("inline=forced")
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE
#endif
#ifndef __USED
#if __ICCARM_V8
#define __USED __attribute__((used))
#else
#define __USED _Pragma("__root")
#endif
#endif
#ifndef __WEAK
#if __ICCARM_V8
#define __WEAK __attribute__((weak))
#else
#define __WEAK _Pragma("__weak")
#endif
#endif
#else
#error "Unknown compiler."
#endif
// IO definitions (access restrictions to peripheral registers).
#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
// The 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
#ifdef __cplusplus
}
#endif
/** @} (end group compiler) */
#endif // SL_COMPILER_H

View File

@@ -0,0 +1,499 @@
/***************************************************************************//**
* @file
* @brief Core API
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_CORE_H
#define SL_CORE_H
#include <stdint.h>
#include <stdbool.h>
#include "sl_code_classification.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup sl_core Core
*
* @section sl_core_intro Introduction
*
* The core abstraction API provides high-level, device agnostic, control of
* core peripherals, most notably the ability to execute code in sections with
* varying levels of interrupt masking.
*
* This module provides support for two types of critical sections, each
* with different interrupt masking capabilities.
*
* @li <b>CRITICAL section</b>: Inside a critical section, all interrupts are
* masked (except for core exception handlers).
* @li <b>ATOMIC section</b>: Inside an atomic section, interrupts with a
* priority less than the configurable @ref SL_CORE_BASE_PRIORITY_LEVEL
* value will be masked.
*
* @section sl_core_conf Compile-time Configuration
*
* The following #define is used to configure sl_core:
* @code{.c}
* // Enables debug methods to measure the time spent in critical sections.
* #define SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING 0
* @endcode
*
* @section sl_core_macro_api Macro API
*
* The core abstraction API has macros to facilitate executing code in
* ATOMIC and CRITICAL sections.
*
* @ref CORE_DECLARE_IRQ_STATE, @ref CORE_ENTER_ATOMIC() and
* @ref CORE_EXIT_ATOMIC() can be used together to implement an ATOMIC section.
* @code{.c}
* {
* CORE_DECLARE_IRQ_STATE; // Storage for saving IRQ state prior to
* // atomic section entry.
*
* CORE_ENTER_ATOMIC(); // Enter atomic section.
*
* ...
* ... your code goes here ...
* ...
*
* CORE_EXIT_ATOMIC(); // Exit atomic section, IRQ state is restored.
* }
* @endcode
*
* @ref CORE_ATOMIC_SECTION(yourcode) is aconcatenation of all three of the
* macros above.
* @code{.c}
* {
* CORE_ATOMIC_SECTION(
* ...
* ... your code goes here ...
* ...
* )
* }
* @endcode
*
* The following macros implement CRITICAL sections in a similar fashion as
* described above for ATOMIC sections:
* <li>@ref CORE_DECLARE_IRQ_STATE</li>
* <li>@ref CORE_ENTER_CRITICAL()</li>
* <li>@ref CORE_EXIT_CRITICAL()</li>
* <li>@ref CORE_CRITICAL_SECTION(yourcode)</li>
*
* @section sl_core_reimplementation API Reimplementation
*
* Most of the functions in the API are implemented as weak functions. This means
* that it is easy to reimplement when special needs arise. Shown below is a
* reimplementation of CRITICAL sections suitable if FreeRTOS OS is used:
* @code{.c}
* CORE_irqState_t CORE_EnterCritical(void)
* {
* vPortEnterCritical();
* return 0;
* }
*
* void CORE_ExitCritical(CORE_irqState_t irqState)
* {
* (void)irqState;
* vPortExitCritical();
* }
* @endcode
* Also note that CORE_Enter/ExitCritical() are not implemented as inline
* functions. As a result, reimplementations will be possible even when original
* implementations are inside a linked library.
*
* Some RTOSes must be notified on interrupt handler entry and exit. Macros
* @ref CORE_INTERRUPT_ENTRY() and @ref CORE_INTERRUPT_EXIT() are suitable
* placeholders for inserting such code. Insert these macros in all your
* interrupt handlers and then override the default macro implementations.
* This is an example if uC/OS is used:
* @code{.c}
* // In emlib_config.h:
*
* #define CORE_INTERRUPT_ENTRY() OSIntEnter()
* #define CORE_INTERRUPT_EXIT() OSIntExit()
* @endcode
*
* @section sl_core_max_timing Maximum Interrupt Disabled Time
*
* The maximum time spent (in cycles) in critical and atomic sections can be
* measured for performance and interrupt latency analysis.
* To enable the timings, use the SL_CORE_ENABLE_INTERRUPT_DISABLED_TIMING
* configuration option. When enabled, the functions
* @ref CORE_get_max_time_critical_section() and
* @ref CORE_get_max_time_atomic_section()
* can be used to get the max timings since startup.
*
* @section sl_core_porting Porting from em_int
*
* Existing code using INT_Enable() and INT_Disable() must be ported to the
* sl_core API. While em_int used, a global counter to store the interrupt state,
* sl_core uses a local variable. Any usage of INT_Disable(), therefore, needs to
* be replaced with a declaration of the interrupt state variable before entering
* the critical section.
*
* Since the state variable is in local scope, the critical section exit
* needs to occur within the scope of the variable. If multiple nested critical
* sections are used, each needs to have its own state variable in its own scope.
*
* In many cases, completely disabling all interrupts using CRITICAL sections
* might be more heavy-handed than needed. When porting, consider whether
* an ATOMIC section can be used to only disable a subset of the interrupts.
*
* Replacing em_int calls with sl_core function calls:
* @code{.c}
* void func(void)
* {
* // INT_Disable();
* CORE_DECLARE_IRQ_STATE;
* CORE_ENTER_ATOMIC();
* .
* .
* .
* // INT_Enable();
* CORE_EXIT_ATOMIC();
* }
* @endcode
* @{
******************************************************************************/
/*******************************************************************************
***************************** DEFINES *************************************
******************************************************************************/
#if !defined(CORE_ATOMIC_BASE_PRIORITY_LEVEL)
/** The interrupt priority level disabled within ATOMIC regions. Interrupts
* with priority level equal to or lower than this definition will be disabled
* within ATOMIC regions. */
#define CORE_ATOMIC_BASE_PRIORITY_LEVEL 3
#else
#ifndef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_2024_6
#warning "The CORE_ATOMIC_BASE_PRIORITY_LEVEL configuration is DEPRECATED. In \
later releases, the base priority of atomic sections will be hardcoded to 3 \
and will no longer be configurable. Please consider updating the priorities \
of interrupts in your application to account for this new hardcoded value."
#endif
#endif
/*******************************************************************************
************************ MACRO API ***************************************
******************************************************************************/
/// Allocate storage for PRIMASK or BASEPRI value for use by
/// CORE_ENTER/EXIT_ATOMIC() and CORE_ENTER/EXIT_CRITICAL() macros.
#define CORE_DECLARE_IRQ_STATE CORE_irqState_t irqState
/// CRITICAL style interrupt disable.
#define CORE_CRITICAL_IRQ_DISABLE() CORE_CriticalDisableIrq()
/// CRITICAL style interrupt enable.
#define CORE_CRITICAL_IRQ_ENABLE() CORE_CriticalEnableIrq()
/// Convenience macro for implementing a CRITICAL section.
#define CORE_CRITICAL_SECTION(yourcode) \
{ \
CORE_DECLARE_IRQ_STATE; \
CORE_ENTER_CRITICAL(); \
{ \
yourcode \
} \
CORE_EXIT_CRITICAL(); \
}
/// Enter CRITICAL section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in
/// scope.
#define CORE_ENTER_CRITICAL() irqState = CORE_EnterCritical()
/// Exit CRITICAL section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in
/// scope.
#define CORE_EXIT_CRITICAL() CORE_ExitCritical(irqState)
/// CRITICAL style yield.
#define CORE_YIELD_CRITICAL() CORE_YieldCritical()
/// ATOMIC style interrupt disable.
#define CORE_ATOMIC_IRQ_DISABLE() CORE_AtomicDisableIrq()
/// ATOMIC style interrupt enable.
#define CORE_ATOMIC_IRQ_ENABLE() CORE_AtomicEnableIrq()
/// Convenience macro for implementing an ATOMIC section.
#define CORE_ATOMIC_SECTION(yourcode) \
{ \
CORE_DECLARE_IRQ_STATE; \
CORE_ENTER_ATOMIC(); \
{ \
yourcode \
} \
CORE_EXIT_ATOMIC(); \
}
/// Enter ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in
/// scope.
#define CORE_ENTER_ATOMIC() irqState = CORE_EnterAtomic()
/// Exit ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in
/// scope.
#define CORE_EXIT_ATOMIC() CORE_ExitAtomic(irqState)
/// ATOMIC style yield.
#define CORE_YIELD_ATOMIC() CORE_YieldAtomic()
/// Check if IRQ is disabled.
#define CORE_IRQ_DISABLED() CORE_IrqIsDisabled()
/// Check if inside an IRQ handler.
#define CORE_IN_IRQ_CONTEXT() CORE_InIrqContext()
// Reset System.
#define CORE_RESET_SYSTEM() CORE_ResetSystem()
/*******************************************************************************
************************* TYPEDEFS ****************************************
******************************************************************************/
/// Storage for PRIMASK or BASEPRI value.
typedef uint32_t CORE_irqState_t;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Disable interrupts.
*
* Disable all interrupts by setting PRIMASK.
* (Fault exception handlers will still be enabled).
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_CriticalDisableIrq(void);
/***************************************************************************//**
* @brief
* Enable interrupts.
*
* Enable interrupts by clearing PRIMASK.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_CriticalEnableIrq(void);
/***************************************************************************//**
* @brief
* Exit a CRITICAL section.
*
* @param[in] irqState
* The interrupt priority blocking level to restore to PRIMASK when exiting
* the CRITICAL section. This value is usually the one returned by a prior
* call to @ref CORE_EnterCritical().
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_ExitCritical(CORE_irqState_t irqState);
/***************************************************************************//**
* @brief
* Brief interrupt enable/disable sequence to allow handling of
* pending interrupts.
*
* @note
* Usually used within a CRITICAL section.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_YieldCritical(void);
/***************************************************************************//**
* @brief
* Enter a CRITICAL section.
*
* When a CRITICAL section is entered, all interrupts (except fault handlers)
* are disabled.
*
* @return
* The value of PRIMASK register prior to the CRITICAL section entry.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
CORE_irqState_t CORE_EnterCritical(void);
/***************************************************************************//**
* @brief
* Disable interrupts.
*
* Disable interrupts with a priority lower or equal to
* @ref CORE_ATOMIC_BASE_PRIORITY_LEVEL. Sets core BASEPRI register
* to CORE_ATOMIC_BASE_PRIORITY_LEVEL.
*
* @note
* If @ref CORE_ATOMIC_METHOD is @ref CORE_ATOMIC_METHOD_PRIMASK, this
* function is identical to @ref CORE_CriticalDisableIrq().
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_AtomicDisableIrq(void);
/***************************************************************************//**
* @brief
* Enable interrupts.
*
* Enable interrupts by setting core BASEPRI register to 0.
*
* @note
* If @ref CORE_ATOMIC_METHOD is @ref CORE_ATOMIC_METHOD_BASEPRI and PRIMASK
* is set (CPU is inside a CRITICAL section), interrupts will still be
* disabled after calling this function.
*
* @note
* If @ref CORE_ATOMIC_METHOD is @ref CORE_ATOMIC_METHOD_PRIMASK, this
* function is identical to @ref CORE_CriticalEnableIrq().
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_AtomicEnableIrq(void);
/***************************************************************************//**
* @brief
* Exit an ATOMIC section.
*
* @param[in] irqState
* The interrupt priority blocking level to restore to BASEPRI when exiting
* the ATOMIC section. This value is usually the one returned by a prior
* call to @ref CORE_EnterAtomic().
*
* @note
* If @ref CORE_ATOMIC_METHOD is set to @ref CORE_ATOMIC_METHOD_PRIMASK, this
* function is identical to @ref CORE_ExitCritical().
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_ExitAtomic(CORE_irqState_t irqState);
/***************************************************************************//**
* @brief
* Brief interrupt enable/disable sequence to allow handling of
* pending interrupts.
*
* @note
* Usually used within an ATOMIC section.
*
* @note
* If @ref CORE_ATOMIC_METHOD is @ref CORE_ATOMIC_METHOD_PRIMASK, this
* function is identical to @ref CORE_YieldCritical().
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_YieldAtomic(void);
/***************************************************************************//**
* @brief
* Enter an ATOMIC section.
*
* When an ATOMIC section is entered, interrupts with priority lower or equal
* to @ref CORE_ATOMIC_BASE_PRIORITY_LEVEL are disabled.
*
* @note
* If @ref CORE_ATOMIC_METHOD is @ref CORE_ATOMIC_METHOD_PRIMASK, this
* function is identical to @ref CORE_EnterCritical().
*
* @return
* The value of BASEPRI register prior to ATOMIC section entry.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
CORE_irqState_t CORE_EnterAtomic(void);
/***************************************************************************//**
* @brief
* Check whether the current CPU operation mode is handler mode.
*
* @return
* True if the CPU is in handler mode (currently executing an interrupt handler).
* @n False if the CPU is in thread mode.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
bool CORE_InIrqContext(void);
/***************************************************************************//**
* @brief
* Check if interrupts are disabled.
*
* @return
* True if interrupts are disabled.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
bool CORE_IrqIsDisabled(void);
/***************************************************************************//**
* @brief
* Returns the max time spent in critical section.
*
* @return
* The max time spent in critical section.
*
* @note SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
uint32_t CORE_get_max_time_critical_section(void);
/***************************************************************************//**
* @brief
* Returns the max time spent in atomic section.
*
* @return
* The max time spent in atomic section.
*
* @note SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
uint32_t CORE_get_max_time_atomic_section(void);
/***************************************************************************//**
* @brief
* Clears the max time spent in atomic section.
*
* @note SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_clear_max_time_critical_section(void);
/***************************************************************************//**
* @brief
* Clears the max time spent in atomic section.
*
* @note SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CORE, SL_CODE_CLASS_TIME_CRITICAL)
void CORE_clear_max_time_atomic_section(void);
/***************************************************************************//**
* @brief
* Reset chip routine.
******************************************************************************/
void CORE_ResetSystem(void);
/** @} (end addtogroup sl_core) */
#ifdef __cplusplus
}
#endif
#endif /* SL_CORE_H */

View File

@@ -0,0 +1,66 @@
/*******************************************************************************
* @file
* @brief SL_ENUM Implementation
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_ENUM_H
#define SL_ENUM_H
/*******************************************************************************
* @addtogroup enum Enumerations
* @brief Enumerations with stable binary representation
* @details
* Silicon Labs libraries do not use enumerations because the ARM EABI leaves
* their size ambiguous, which causes problems if the application is built
* with different flags than the library. Instead, uint8_t typedefs
* are used in compiled code for all enumerations. For documentation purposes,
* this is converted to an actual enumeration in documentation.
* @{
******************************************************************************/
#ifdef DOXYGEN
/// Enumeration mapped to uint8_t
#define SL_ENUM(name) enum name
/// Enumeration mapped to arbitrary type
#define SL_ENUM_GENERIC(name, type) enum name
#else
// NOTE: The following macros might cause MISRA warnings because
// Macro parameters need to be enclosed in parentheses.
// However, it is not possible in C to enclose declaration
// identifiers in parentheses. For example:
// typedef uint8_t (some_identifier);
// is not syntactically correct in the C language (C99).
#define SL_ENUM(name) typedef uint8_t name; enum name##_enum
#define SL_ENUM_GENERIC(name, type) typedef type name; enum name##_enum
// For debugging, use the following define to turn this back into a proper enumeration
// #define SL_ENUM(name) typedef enum name##_enum name; enum name##_enum
#endif
/** @} end enum */
#endif // SL_ENUM_H

View File

@@ -0,0 +1,173 @@
/*******************************************************************************
* @file
* @brief Single Link List.
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SLIST_H
#define SL_SLIST_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* @addtogroup slist Singly-Linked List
* @brief Singly-linked List module provides APIs to handle singly-linked list
* operations such as insert, push, pop, push back, sort and remove.
*
* @note The pop operation follows FIFO method.
* @n @section slist_usage Singly-Linked List module Usage
* @{
******************************************************************************/
/// List node type
typedef struct sl_slist_node sl_slist_node_t;
/// List node
struct sl_slist_node {
sl_slist_node_t *node; ///< List node
};
#ifndef DOXYGEN
#define container_of(ptr, type, member) (type *)((uintptr_t)(ptr) - ((uintptr_t)(&((type *)0)->member)))
#define SL_SLIST_ENTRY container_of
#define SL_SLIST_FOR_EACH(list_head, iterator) for ((iterator) = (list_head); (iterator) != NULL; (iterator) = (iterator)->node)
#define SL_SLIST_FOR_EACH_ENTRY(list_head, entry, type, member) for ( (entry) = SL_SLIST_ENTRY(list_head, type, member); \
(type *)(entry) != SL_SLIST_ENTRY(NULL, type, member); \
(entry) = SL_SLIST_ENTRY((entry)->member.node, type, member))
#endif
// -----------------------------------------------------------------------------
// Prototypes
/*******************************************************************************
* Initialize a singly-linked list.
*
* @param head Pointer to pointer of head element of list.
******************************************************************************/
void sl_slist_init(sl_slist_node_t **head);
/*******************************************************************************
* Add given item at beginning of the list.
*
* @param head Pointer to pointer of head element of the list.
*
* @param item Pointer to an item to add.
******************************************************************************/
void sl_slist_push(sl_slist_node_t **head,
sl_slist_node_t *item);
/*******************************************************************************
* Add item at the end of the list.
*
* @param head Pointer to the pointer of a head element of the list.
*
* @param item Pointer to the item to add.
******************************************************************************/
void sl_slist_push_back(sl_slist_node_t **head,
sl_slist_node_t *item);
/*******************************************************************************
* Remove and return the first element of the list.
*
* @param head Pointer to he pointer of the head element of the list.
*
* @return Pointer to item that was at top of the list.
******************************************************************************/
sl_slist_node_t *sl_slist_pop(sl_slist_node_t **head);
/*******************************************************************************
* Insert an item after the given item.
*
* @param item Pointer to an item to add.
*
* @param pos Pointer to an item after which the item to add will be inserted.
******************************************************************************/
void sl_slist_insert(sl_slist_node_t *item,
sl_slist_node_t *pos);
/*******************************************************************************
* Join two lists together.
*
* @param head_list_1 Pointer to the pointer of a head element of the list.
*
* @param head_list_2 Pointer to the pointer of a head element of the list
* to be appended. After the call, this pointer will be
* invalidated (set to NULL).
******************************************************************************/
void sl_slist_join(sl_slist_node_t **head_list_1,
sl_slist_node_t **head_list_2);
/*******************************************************************************
* Remove an item from the list.
*
* @param head Pointer to pointer of the head element of list.
*
* @param item Pointer to the item to remove.
******************************************************************************/
void sl_slist_remove(sl_slist_node_t **head,
sl_slist_node_t *item);
/*******************************************************************************
* Sort list items.
*
* @param head Pointer to the pointer of the head element of the list.
*
* @param cmp_fnct Pointer to function to use for sorting the list.
* item_l Pointer to left item.
* item_r Pointer to right item.
* Returns whether the two items are ordered (true) or not (false).
******************************************************************************/
void sl_slist_sort(sl_slist_node_t **head,
bool (*cmp_fnct)(sl_slist_node_t *item_l,
sl_slist_node_t *item_r));
/*******************************************************************************
* Checks if the list is empty.
*
* @param head Pointer to the head element of the list.
******************************************************************************/
static inline bool sl_slist_is_empty(sl_slist_node_t *head)
{
return head == NULL;
}
/** @} (end addtogroup slist) */
#ifdef __cplusplus
}
#endif
#endif /* SL_SLIST_H */

View File

@@ -0,0 +1,526 @@
/*******************************************************************************
* @file
* @brief SL Status Codes.
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_STATUS_H
#define SL_STATUS_H
#include <stdint.h>
/*******************************************************************************
* @addtogroup status Status Codes
* @details Status Codes contains error and status code definitions used by
* Simplicity SDK software components and stacks. This module also
* provides routines to read the string linked with the error and
* status codes.
* @{
******************************************************************************/
// -----------------------------------------------------------------------------
// Space Defines
#define SL_STATUS_SPACE_MASK ((sl_status_t)0xFF00) ///< sl status space mask.
#define SL_STATUS_GENERIC_SPACE ((sl_status_t)0x0000) ///< sl status generic space.
#define SL_STATUS_PLATFORM_1_SPACE ((sl_status_t)0x0100) ///< sl status platform 1 space.
#define SL_STATUS_PLATFORM_2_SPACE ((sl_status_t)0x0200) ///< sl status platform 2 space.
#define SL_STATUS_HARDWARE_SPACE ((sl_status_t)0x0300) ///< sl status hardware space.
#define SL_STATUS_BLUETOOTH_SPACE ((sl_status_t)0x0400) ///< sl status bluetooth space.
#define SL_STATUS_BLUETOOTH_MESH_SPACE ((sl_status_t)0x0500) ///< sl status bluetooth mesh space.
#define SL_STATUS_CAN_CANOPEN_SPACE ((sl_status_t)0x0600) ///< sl status can canopen space.
#define SL_STATUS_CONNECT_SPACE ((sl_status_t)0x0700) ///< sl status connect space.
#define SL_STATUS_NET_SUITE_SPACE ((sl_status_t)0x0800) ///< sl status net suite space.
#define SL_STATUS_THREAD_SPACE ((sl_status_t)0x0900) ///< sl status thread space.
#define SL_STATUS_USB_SPACE ((sl_status_t)0x0A00) ///< sl status usb space.
#define SL_STATUS_WIFI_SPACE ((sl_status_t)0x0B00) ///< sl status wifi space.
#define SL_STATUS_ZIGBEE_SPACE ((sl_status_t)0x0C00) ///< sl status zigbee space.
#define SL_STATUS_Z_WAVE_SPACE ((sl_status_t)0x0D00) ///< sl status z wave space.
#define SL_STATUS_GECKO_OS_1_SPACE ((sl_status_t)0x0E00) ///< sl status gecko os 1 space.
#define SL_STATUS_GECKO_OS_2_SPACE ((sl_status_t)0x0F00) ///< sl status gecko os 2 space.
#define SL_STATUS_BLUETOOTH_CTRL_SPACE ((sl_status_t)0x1000) ///< sl status bluetooth ctrl space.
#define SL_STATUS_BLUETOOTH_ATT_SPACE ((sl_status_t)0x1100) ///< sl status bluetooth att space.
#define SL_STATUS_BLUETOOTH_SMP_SPACE ((sl_status_t)0x1200) ///< sl status bluetooth mesh foundation space.
#define SL_STATUS_BLUETOOTH_MESH_FOUNDATION_SPACE ((sl_status_t)0x1300) ///< sl status bluetooth mesh foundation space.
#define SL_STATUS_WISUN_SPACE ((sl_status_t)0x1400) ///< sl status wisun space.
#define SL_STATUS_COMPUTE_SPACE ((sl_status_t)0x1500) ///< sl status compute space.
// -----------------------------------------------------------------------------
// Status Defines
// -----------------------------------------------------------------------------
// Generic Errors
#define SL_STATUS_OK ((sl_status_t)0x0000) ///< No error.
#define SL_STATUS_FAIL ((sl_status_t)0x0001) ///< Generic error.
// State Errors
#define SL_STATUS_INVALID_STATE ((sl_status_t)0x0002) ///< Generic invalid state error.
#define SL_STATUS_NOT_READY ((sl_status_t)0x0003) ///< Module is not ready for requested operation.
#define SL_STATUS_BUSY ((sl_status_t)0x0004) ///< Module is busy and cannot carry out requested operation.
#define SL_STATUS_IN_PROGRESS ((sl_status_t)0x0005) ///< Operation is in progress and not yet complete (pass or fail).
#define SL_STATUS_ABORT ((sl_status_t)0x0006) ///< Operation aborted.
#define SL_STATUS_TIMEOUT ((sl_status_t)0x0007) ///< Operation timed out.
#define SL_STATUS_PERMISSION ((sl_status_t)0x0008) ///< Operation not allowed per permissions.
#define SL_STATUS_WOULD_BLOCK ((sl_status_t)0x0009) ///< Non-blocking operation would block.
#define SL_STATUS_IDLE ((sl_status_t)0x000A) ///< Operation/module is Idle, cannot carry requested operation.
#define SL_STATUS_IS_WAITING ((sl_status_t)0x000B) ///< Operation cannot be done while construct is waiting.
#define SL_STATUS_NONE_WAITING ((sl_status_t)0x000C) ///< No task/construct waiting/pending for that action/event.
#define SL_STATUS_SUSPENDED ((sl_status_t)0x000D) ///< Operation cannot be done while construct is suspended.
#define SL_STATUS_NOT_AVAILABLE ((sl_status_t)0x000E) ///< Feature not available due to software configuration.
#define SL_STATUS_NOT_SUPPORTED ((sl_status_t)0x000F) ///< Feature not supported.
#define SL_STATUS_INITIALIZATION ((sl_status_t)0x0010) ///< Initialization failed.
#define SL_STATUS_NOT_INITIALIZED ((sl_status_t)0x0011) ///< Module has not been initialized.
#define SL_STATUS_ALREADY_INITIALIZED ((sl_status_t)0x0012) ///< Module has already been initialized.
#define SL_STATUS_DELETED ((sl_status_t)0x0013) ///< Object/construct has been deleted.
#define SL_STATUS_ISR ((sl_status_t)0x0014) ///< Illegal call from ISR.
#define SL_STATUS_NETWORK_UP ((sl_status_t)0x0015) ///< Illegal call because network is up.
#define SL_STATUS_NETWORK_DOWN ((sl_status_t)0x0016) ///< Illegal call because network is down.
#define SL_STATUS_NOT_JOINED ((sl_status_t)0x0017) ///< Failure due to not being joined in a network.
#define SL_STATUS_NO_BEACONS ((sl_status_t)0x0018) ///< Invalid operation as there are no beacons.
// Allocation/ownership Errors
#define SL_STATUS_ALLOCATION_FAILED ((sl_status_t)0x0019) ///< Generic allocation error.
#define SL_STATUS_NO_MORE_RESOURCE ((sl_status_t)0x001A) ///< No more resource available to perform the operation.
#define SL_STATUS_EMPTY ((sl_status_t)0x001B) ///< Item/list/queue is empty.
#define SL_STATUS_FULL ((sl_status_t)0x001C) ///< Item/list/queue is full.
#define SL_STATUS_WOULD_OVERFLOW ((sl_status_t)0x001D) ///< Item would overflow.
#define SL_STATUS_HAS_OVERFLOWED ((sl_status_t)0x001E) ///< Item/list/queue has been overflowed.
#define SL_STATUS_OWNERSHIP ((sl_status_t)0x001F) ///< Generic ownership error.
#define SL_STATUS_IS_OWNER ((sl_status_t)0x0020) ///< Already/still owning resource.
// Invalid Parameters Errors
#define SL_STATUS_INVALID_PARAMETER ((sl_status_t)0x0021) ///< Generic invalid argument or consequence of invalid argument.
#define SL_STATUS_NULL_POINTER ((sl_status_t)0x0022) ///< Invalid null pointer received as argument.
#define SL_STATUS_INVALID_CONFIGURATION ((sl_status_t)0x0023) ///< Invalid configuration provided.
#define SL_STATUS_INVALID_MODE ((sl_status_t)0x0024) ///< Invalid mode.
#define SL_STATUS_INVALID_HANDLE ((sl_status_t)0x0025) ///< Invalid handle.
#define SL_STATUS_INVALID_TYPE ((sl_status_t)0x0026) ///< Invalid type for operation.
#define SL_STATUS_INVALID_INDEX ((sl_status_t)0x0027) ///< Invalid index.
#define SL_STATUS_INVALID_RANGE ((sl_status_t)0x0028) ///< Invalid range.
#define SL_STATUS_INVALID_KEY ((sl_status_t)0x0029) ///< Invalid key.
#define SL_STATUS_INVALID_CREDENTIALS ((sl_status_t)0x002A) ///< Invalid credentials.
#define SL_STATUS_INVALID_COUNT ((sl_status_t)0x002B) ///< Invalid count.
#define SL_STATUS_INVALID_SIGNATURE ((sl_status_t)0x002C) ///< Invalid signature / verification failed.
#define SL_STATUS_NOT_FOUND ((sl_status_t)0x002D) ///< Item could not be found.
#define SL_STATUS_ALREADY_EXISTS ((sl_status_t)0x002E) ///< Item already exists.
// IO/Communication Errors
#define SL_STATUS_IO ((sl_status_t)0x002F) ///< Generic I/O failure.
#define SL_STATUS_IO_TIMEOUT ((sl_status_t)0x0030) ///< I/O failure due to timeout.
#define SL_STATUS_TRANSMIT ((sl_status_t)0x0031) ///< Generic transmission error.
#define SL_STATUS_TRANSMIT_UNDERFLOW ((sl_status_t)0x0032) ///< Transmit underflowed.
#define SL_STATUS_TRANSMIT_INCOMPLETE ((sl_status_t)0x0033) ///< Transmit is incomplete.
#define SL_STATUS_TRANSMIT_BUSY ((sl_status_t)0x0034) ///< Transmit is busy.
#define SL_STATUS_RECEIVE ((sl_status_t)0x0035) ///< Generic reception error.
#define SL_STATUS_OBJECT_READ ((sl_status_t)0x0036) ///< Failed to read on/via given object.
#define SL_STATUS_OBJECT_WRITE ((sl_status_t)0x0037) ///< Failed to write on/via given object.
#define SL_STATUS_MESSAGE_TOO_LONG ((sl_status_t)0x0038) ///< Message is too long.
// EEPROM/Flash Errors
#define SL_STATUS_EEPROM_MFG_VERSION_MISMATCH ((sl_status_t)0x0039) ///< EEPROM MFG version mismatch.
#define SL_STATUS_EEPROM_STACK_VERSION_MISMATCH ((sl_status_t)0x003A) ///< EEPROM Stack version mismatch.
#define SL_STATUS_FLASH_WRITE_INHIBITED ((sl_status_t)0x003B) ///< Flash write is inhibited.
#define SL_STATUS_FLASH_VERIFY_FAILED ((sl_status_t)0x003C) ///< Flash verification failed.
#define SL_STATUS_FLASH_PROGRAM_FAILED ((sl_status_t)0x003D) ///< Flash programming failed.
#define SL_STATUS_FLASH_ERASE_FAILED ((sl_status_t)0x003E) ///< Flash erase failed.
// MAC Errors
#define SL_STATUS_MAC_NO_DATA ((sl_status_t)0x003F) ///< MAC no data.
#define SL_STATUS_MAC_NO_ACK_RECEIVED ((sl_status_t)0x0040) ///< MAC no ACK received.
#define SL_STATUS_MAC_INDIRECT_TIMEOUT ((sl_status_t)0x0041) ///< MAC indirect timeout.
#define SL_STATUS_MAC_UNKNOWN_HEADER_TYPE ((sl_status_t)0x0042) ///< MAC unknown header type.
#define SL_STATUS_MAC_ACK_HEADER_TYPE ((sl_status_t)0x0043) ///< MAC ACK unknown header type.
#define SL_STATUS_MAC_COMMAND_TRANSMIT_FAILURE ((sl_status_t)0x0044) ///< MAC command transmit failure.
// CLI_STORAGE Errors
#define SL_STATUS_CLI_STORAGE_NVM_OPEN_ERROR ((sl_status_t)0x0045) ///< Error in open NVM
// Security status codes
#define SL_STATUS_SECURITY_IMAGE_CHECKSUM_ERROR ((sl_status_t)0x0046) ///< Image checksum is not valid.
#define SL_STATUS_SECURITY_DECRYPT_ERROR ((sl_status_t)0x0047) ///< Decryption failed
// Command status codes
#define SL_STATUS_COMMAND_IS_INVALID ((sl_status_t)0x0048) ///< Command was not recognized
#define SL_STATUS_COMMAND_TOO_LONG ((sl_status_t)0x0049) ///< Command or parameter maximum length exceeded
#define SL_STATUS_COMMAND_INCOMPLETE ((sl_status_t)0x004A) ///< Data received does not form a complete command
// Misc Errors
#define SL_STATUS_BUS_ERROR ((sl_status_t)0x004B) ///< Bus error, e.g. invalid DMA address
// Unified MAC Errors
#define SL_STATUS_CCA_FAILURE ((sl_status_t)0x004C) ///< CCA failure.
// Scan errors
#define SL_STATUS_MAC_SCANNING ((sl_status_t)0x004D) ///< MAC scanning.
#define SL_STATUS_MAC_INCORRECT_SCAN_TYPE ((sl_status_t)0x004E) ///< MAC incorrect scan type.
#define SL_STATUS_INVALID_CHANNEL_MASK ((sl_status_t)0x004F) ///< Invalid channel mask.
#define SL_STATUS_BAD_SCAN_DURATION ((sl_status_t)0x0050) ///< Bad scan duration.
// MAC transmit related status
#define SL_STATUS_MAC_TRANSMIT_QUEUE_FULL ((sl_status_t)0x0053) ///< The MAC transmit queue is full
#define SL_STATUS_TRANSMIT_SCHEDULER_FAIL ((sl_status_t)0x0054) ///< The transmit attempt failed because the radio scheduler could not find a slot to transmit this packet in or a higher priority event interrupted it
#define SL_STATUS_TRANSMIT_INVALID_CHANNEL ((sl_status_t)0x0055) ///< An unsupported channel setting was specified
#define SL_STATUS_TRANSMIT_INVALID_POWER ((sl_status_t)0x0056) ///< An unsupported power setting was specified
#define SL_STATUS_TRANSMIT_ACK_RECEIVED ((sl_status_t)0x0057) ///< The expected ACK was received after the last transmission
#define SL_STATUS_TRANSMIT_BLOCKED ((sl_status_t)0x0058) ///< The transmit attempt was blocked from going over the air. Typically this is due to the Radio Hold Off (RHO) or Coexistence plugins as they can prevent transmits based on external signals.
// NVM3 specific errors
#define SL_STATUS_NVM3_ALIGNMENT_INVALID ((sl_status_t)0x0059) ///< The initialization was aborted as the NVM3 instance is not aligned properly in memory
#define SL_STATUS_NVM3_SIZE_TOO_SMALL ((sl_status_t)0x005A) ///< The initialization was aborted as the size of the NVM3 instance is too small
#define SL_STATUS_NVM3_PAGE_SIZE_NOT_SUPPORTED ((sl_status_t)0x005B) ///< The initialization was aborted as the NVM3 page size is not supported
#define SL_STATUS_NVM3_TOKEN_INIT_FAILED ((sl_status_t)0x005C) ///< The application that there was an error initializing some of the tokens
#define SL_STATUS_NVM3_OPENED_WITH_OTHER_PARAMETERS ((sl_status_t)0x005D) ///< The initialization was aborted as the NVM3 instance was already opened with other parameters
#define SL_STATUS_NVM3_NO_VALID_PAGES ((sl_status_t)0x005E) ///< Initialization aborted, no valid page found
#define SL_STATUS_NVM3_OBJECT_SIZE_NOT_SUPPORTED ((sl_status_t)0x005F) ///< The object size is not supported
#define SL_STATUS_NVM3_OBJECT_IS_NOT_DATA ((sl_status_t)0x0060) ///< Trying to access a data object which is currently a counter object
#define SL_STATUS_NVM3_OBJECT_IS_NOT_A_COUNTER ((sl_status_t)0x0061) ///< Trying to access a counter object which is currently a data object
#define SL_STATUS_NVM3_WRITE_DATA_SIZE ((sl_status_t)0x0062) ///< The object is too large
#define SL_STATUS_NVM3_READ_DATA_SIZE ((sl_status_t)0x0063) ///< Trying to read with a length different from actual object size
#define SL_STATUS_NVM3_INIT_WITH_FULL_NVM ((sl_status_t)0x0064) ///< The module was opened with a full NVM
#define SL_STATUS_NVM3_RESIZE_PARAMETER ((sl_status_t)0x0065) ///< Illegal parameter
#define SL_STATUS_NVM3_RESIZE_NOT_ENOUGH_SPACE ((sl_status_t)0x0066) ///< Not enough NVM to complete resize
#define SL_STATUS_NVM3_ERASE_COUNT_ERROR ((sl_status_t)0x0067) ///< Erase counts are not valid
#define SL_STATUS_NVM3_NVM_ACCESS ((sl_status_t)0x0068) ///< A NVM function call was failing
#define SL_STATUS_NVM3_CRYPTO_INIT_FAILED ((sl_status_t)0x0069) ///< Crypto initialization failed
#define SL_STATUS_NVM3_ENCRYPTION_KEY_ERROR ((sl_status_t)0x006A) ///< Error in obtaining encryption key
#define SL_STATUS_NVM3_RANDOM_NUM_GENERATION_FAILED ((sl_status_t)0x006B) ///< Error in obtaining random number
#define SL_STATUS_NVM3_ENCRYPTION_FAILED ((sl_status_t)0x006C) ///< Encryption failed
#define SL_STATUS_NVM3_WRITE_TO_NOT_ERASED ((sl_status_t)0x006D) ///< Write to memory that is not erased
#define SL_STATUS_NVM3_INVALID_ADDR ((sl_status_t)0x006E) ///< Invalid NVM address
#define SL_STATUS_NVM3_KEY_MISMATCH ((sl_status_t)0x006F) ///< Key validation failure
#define SL_STATUS_NVM3_SIZE_ERROR ((sl_status_t)0x0070) ///< Size mismatch error
#define SL_STATUS_NVM3_EMULATOR ((sl_status_t)0x0071) ///< Emulator error
#define SL_STATUS_NVM3_SECURITY_INIT_FAILED ((sl_status_t)0x0072) ///< Security init failed
#define SL_STATUS_NVM3_GET_REGION_LOCATION_FAILED ((sl_status_t)0x0073) ///< Get data region location failed
// Bluetooth status codes
#define SL_STATUS_BT_OUT_OF_BONDS ((sl_status_t)0x0402) ///< Bonding procedure can't be started because device has no space left for bond.
#define SL_STATUS_BT_UNSPECIFIED ((sl_status_t)0x0403) ///< Unspecified error
#define SL_STATUS_BT_HARDWARE ((sl_status_t)0x0404) ///< Hardware failure
#define SL_STATUS_BT_NO_BONDING ((sl_status_t)0x0406) ///< The bonding does not exist.
#define SL_STATUS_BT_CRYPTO ((sl_status_t)0x0407) ///< Error using crypto functions
#define SL_STATUS_BT_DATA_CORRUPTED ((sl_status_t)0x0408) ///< Data was corrupted.
#define SL_STATUS_BT_INVALID_SYNC_HANDLE ((sl_status_t)0x040A) ///< Invalid periodic advertising sync handle
#define SL_STATUS_BT_INVALID_MODULE_ACTION ((sl_status_t)0x040B) ///< Bluetooth cannot be used on this hardware
#define SL_STATUS_BT_RADIO ((sl_status_t)0x040C) ///< Error received from radio
#define SL_STATUS_BT_L2CAP_REMOTE_DISCONNECTED ((sl_status_t)0x040D) ///< Returned when remote disconnects the connection-oriented channel by sending disconnection request.
#define SL_STATUS_BT_L2CAP_LOCAL_DISCONNECTED ((sl_status_t)0x040E) ///< Returned when local host disconnect the connection-oriented channel by sending disconnection request.
#define SL_STATUS_BT_L2CAP_CID_NOT_EXIST ((sl_status_t)0x040F) ///< Returned when local host did not find a connection-oriented channel with given destination CID.
#define SL_STATUS_BT_L2CAP_LE_DISCONNECTED ((sl_status_t)0x0410) ///< Returned when connection-oriented channel disconnected due to LE connection is dropped.
#define SL_STATUS_BT_L2CAP_FLOW_CONTROL_VIOLATED ((sl_status_t)0x0412) ///< Returned when connection-oriented channel disconnected due to remote end send data even without credit.
#define SL_STATUS_BT_L2CAP_FLOW_CONTROL_CREDIT_OVERFLOWED ((sl_status_t)0x0413) ///< Returned when connection-oriented channel disconnected due to remote end send flow control credits exceed 65535.
#define SL_STATUS_BT_L2CAP_NO_FLOW_CONTROL_CREDIT ((sl_status_t)0x0414) ///< Returned when connection-oriented channel has run out of flow control credit and local application still trying to send data.
#define SL_STATUS_BT_L2CAP_CONNECTION_REQUEST_TIMEOUT ((sl_status_t)0x0415) ///< Returned when connection-oriented channel has not received connection response message within maximum timeout.
#define SL_STATUS_BT_L2CAP_INVALID_CID ((sl_status_t)0x0416) ///< Returned when local host received a connection-oriented channel connection response with an invalid destination CID.
#define SL_STATUS_BT_L2CAP_WRONG_STATE ((sl_status_t)0x0417) ///< Returned when local host application tries to send a command which is not suitable for L2CAP channel's current state.
#define SL_STATUS_BT_PS_STORE_FULL ((sl_status_t)0x041B) ///< Flash reserved for PS store is full
#define SL_STATUS_BT_PS_KEY_NOT_FOUND ((sl_status_t)0x041C) ///< PS key not found
#define SL_STATUS_BT_APPLICATION_MISMATCHED_OR_INSUFFICIENT_SECURITY ((sl_status_t)0x041D) ///< Mismatched or insufficient security level
#define SL_STATUS_BT_APPLICATION_ENCRYPTION_DECRYPTION_ERROR ((sl_status_t)0x041E) ///< Encryption/decryption operation failed.
// Bluetooth controller status codes
#define SL_STATUS_BT_CTRL_UNKNOWN_CONNECTION_IDENTIFIER ((sl_status_t)0x1002) ///< Connection does not exist, or connection open request was cancelled.
#define SL_STATUS_BT_CTRL_AUTHENTICATION_FAILURE ((sl_status_t)0x1005) ///< Pairing or authentication failed due to incorrect results in the pairing or authentication procedure. This could be due to an incorrect PIN or Link Key
#define SL_STATUS_BT_CTRL_PIN_OR_KEY_MISSING ((sl_status_t)0x1006) ///< Pairing failed because of missing PIN, or authentication failed because of missing Key
#define SL_STATUS_BT_CTRL_MEMORY_CAPACITY_EXCEEDED ((sl_status_t)0x1007) ///< Controller is out of memory.
#define SL_STATUS_BT_CTRL_CONNECTION_TIMEOUT ((sl_status_t)0x1008) ///< Link supervision timeout has expired.
#define SL_STATUS_BT_CTRL_CONNECTION_LIMIT_EXCEEDED ((sl_status_t)0x1009) ///< Controller is at limit of connections it can support.
#define SL_STATUS_BT_CTRL_SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED ((sl_status_t)0x100A) ///< The Synchronous Connection Limit to a Device Exceeded error code indicates that the Controller has reached the limit to the number of synchronous connections that can be achieved to a device.
#define SL_STATUS_BT_CTRL_ACL_CONNECTION_ALREADY_EXISTS ((sl_status_t)0x100B) ///< The ACL Connection Already Exists error code indicates that an attempt to create a new ACL Connection to a device when there is already a connection to this device.
#define SL_STATUS_BT_CTRL_COMMAND_DISALLOWED ((sl_status_t)0x100C) ///< Command requested cannot be executed because the Controller is in a state where it cannot process this command at this time.
#define SL_STATUS_BT_CTRL_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES ((sl_status_t)0x100D) ///< The Connection Rejected Due To Limited Resources error code indicates that an incoming connection was rejected due to limited resources.
#define SL_STATUS_BT_CTRL_CONNECTION_REJECTED_DUE_TO_SECURITY_REASONS ((sl_status_t)0x100E) ///< The Connection Rejected Due To Security Reasons error code indicates that a connection was rejected due to security requirements not being fulfilled, like authentication or pairing.
#define SL_STATUS_BT_CTRL_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR ((sl_status_t)0x100F) ///< The Connection was rejected because this device does not accept the BD_ADDR. This may be because the device will only accept connections from specific BD_ADDRs.
#define SL_STATUS_BT_CTRL_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED ((sl_status_t)0x1010) ///< The Connection Accept Timeout has been exceeded for this connection attempt.
#define SL_STATUS_BT_CTRL_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE ((sl_status_t)0x1011) ///< A feature or parameter value in the HCI command is not supported.
#define SL_STATUS_BT_CTRL_INVALID_COMMAND_PARAMETERS ((sl_status_t)0x1012) ///< Command contained invalid parameters.
#define SL_STATUS_BT_CTRL_REMOTE_USER_TERMINATED ((sl_status_t)0x1013) ///< User on the remote device terminated the connection.
#define SL_STATUS_BT_CTRL_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES ((sl_status_t)0x1014) ///< The remote device terminated the connection because of low resources
#define SL_STATUS_BT_CTRL_REMOTE_POWERING_OFF ((sl_status_t)0x1015) ///< Remote Device Terminated Connection due to Power Off
#define SL_STATUS_BT_CTRL_CONNECTION_TERMINATED_BY_LOCAL_HOST ((sl_status_t)0x1016) ///< Local device terminated the connection.
#define SL_STATUS_BT_CTRL_REPEATED_ATTEMPTS ((sl_status_t)0x1017) ///< The Controller is disallowing an authentication or pairing procedure because too little time has elapsed since the last authentication or pairing attempt failed.
#define SL_STATUS_BT_CTRL_PAIRING_NOT_ALLOWED ((sl_status_t)0x1018) ///< The device does not allow pairing. This can be for example, when a device only allows pairing during a certain time window after some user input allows pairing
#define SL_STATUS_BT_CTRL_UNSUPPORTED_REMOTE_FEATURE ((sl_status_t)0x101A) ///< The remote device does not support the feature associated with the issued command.
#define SL_STATUS_BT_CTRL_INVALID_LL_PARAMETERS ((sl_status_t)0x101E) ///< Indicates that some LMP PDU / LL Control PDU parameters were invalid
#define SL_STATUS_BT_CTRL_UNSPECIFIED_ERROR ((sl_status_t)0x101F) ///< No other error code specified is appropriate to use.
#define SL_STATUS_BT_CTRL_LL_RESPONSE_TIMEOUT ((sl_status_t)0x1022) ///< Connection terminated due to link-layer procedure timeout.
#define SL_STATUS_BT_CTRL_LL_PROCEDURE_COLLISION ((sl_status_t)0x1023) ///< LL procedure has collided with the same transaction or procedure that is already in progress.
#define SL_STATUS_BT_CTRL_ENCRYPTION_MODE_NOT_ACCEPTABLE ((sl_status_t)0x1025) ///< The requested encryption mode is not acceptable at this time.
#define SL_STATUS_BT_CTRL_LINK_KEY_CANNOT_BE_CHANGED ((sl_status_t)0x1026) ///< Link key cannot be changed because a fixed unit key is being used.
#define SL_STATUS_BT_CTRL_INSTANT_PASSED ((sl_status_t)0x1028) ///< LMP PDU or LL PDU that includes an instant cannot be performed because the instant when this would have occurred has passed.
#define SL_STATUS_BT_CTRL_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED ((sl_status_t)0x1029) ///< It was not possible to pair as a unit key was requested and it is not supported.
#define SL_STATUS_BT_CTRL_DIFFERENT_TRANSACTION_COLLISION ((sl_status_t)0x102A) ///< LMP transaction was started that collides with an ongoing transaction.
#define SL_STATUS_BT_CTRL_CHANNEL_ASSESSMENT_NOT_SUPPORTED ((sl_status_t)0x102E) ///< The Controller cannot perform channel assessment because it is not supported.
#define SL_STATUS_BT_CTRL_INSUFFICIENT_SECURITY ((sl_status_t)0x102F) ///< The HCI command or LMP PDU sent is only possible on an encrypted link.
#define SL_STATUS_BT_CTRL_PARAMETER_OUT_OF_MANDATORY_RANGE ((sl_status_t)0x1030) ///< A parameter value requested is outside the mandatory range of parameters for the given HCI command or LMP PDU.
#define SL_STATUS_BT_CTRL_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST ((sl_status_t)0x1037) ///< The IO capabilities request or response was rejected because the sending Host does not support Secure Simple Pairing even though the receiving Link Manager does.
#define SL_STATUS_BT_CTRL_HOST_BUSY_PAIRING ((sl_status_t)0x1038) ///< The Host is busy with another pairing operation and unable to support the requested pairing. The receiving device should retry pairing again later.
#define SL_STATUS_BT_CTRL_CONNECTION_REJECTED_DUE_TO_NO_SUITABLE_CHANNEL_FOUND ((sl_status_t)0x1039) ///< The Controller could not calculate an appropriate value for the Channel selection operation.
#define SL_STATUS_BT_CTRL_CONTROLLER_BUSY ((sl_status_t)0x103A) ///< Operation was rejected because the controller is busy and unable to process the request.
#define SL_STATUS_BT_CTRL_UNACCEPTABLE_CONNECTION_INTERVAL ((sl_status_t)0x103B) ///< Remote device terminated the connection because of an unacceptable connection interval.
#define SL_STATUS_BT_CTRL_ADVERTISING_TIMEOUT ((sl_status_t)0x103C) ///< Advertising for a fixed duration completed or, for directed advertising, that advertising completed without a connection being created.
#define SL_STATUS_BT_CTRL_CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE ((sl_status_t)0x103D) ///< Connection was terminated because the Message Integrity Check (MIC) failed on a received packet.
#define SL_STATUS_BT_CTRL_CONNECTION_FAILED_TO_BE_ESTABLISHED ((sl_status_t)0x103E) ///< LL initiated a connection but the connection has failed to be established. Controller did not receive any packets from remote end.
#define SL_STATUS_BT_CTRL_MAC_CONNECTION_FAILED ((sl_status_t)0x103F) ///< The MAC of the 802.11 AMP was requested to connect to a peer, but the connection failed.
#define SL_STATUS_BT_CTRL_COARSE_CLOCK_ADJUSTMENT_REJECTED_BUT_WILL_TRY_TO_ADJUST_USING_CLOCK_DRAGGING ((sl_status_t)0x1040) ///< The master, at this time, is unable to make a coarse adjustment to the piconet clock, using the supplied parameters. Instead the master will attempt to move the clock using clock dragging.
#define SL_STATUS_BT_CTRL_UNKNOWN_ADVERTISING_IDENTIFIER ((sl_status_t)0x1042) ///< A command was sent from the Host that should identify an Advertising or Sync handle, but the Advertising or Sync handle does not exist.
#define SL_STATUS_BT_CTRL_LIMIT_REACHED ((sl_status_t)0x1043) ///< Number of operations requested has been reached and has indicated the completion of the activity (e.g., advertising or scanning).
#define SL_STATUS_BT_CTRL_OPERATION_CANCELLED_BY_HOST ((sl_status_t)0x1044) ///< A request to the Controller issued by the Host and still pending was successfully canceled.
#define SL_STATUS_BT_CTRL_PACKET_TOO_LONG ((sl_status_t)0x1045) ///< An attempt was made to send or receive a packet that exceeds the maximum allowed packet length.
#define SL_STATUS_BT_CTRL_TOO_LATE ((sl_status_t)0x1046) ///< Information was provided too late to the controller.
#define SL_STATUS_BT_CTRL_TOO_EARLY ((sl_status_t)0x1047) ///< Information was provided too early to the controller.
#define SL_STATUS_BT_CTRL_INSUFFICIENT_CHANNELS ((sl_status_t)0x1048) ///< Indicates that the result of the requested operation would yield too few physical channels.
// Bluetooth attribute status codes
#define SL_STATUS_BT_ATT_INVALID_HANDLE ((sl_status_t)0x1101) ///< The attribute handle given was not valid on this server
#define SL_STATUS_BT_ATT_READ_NOT_PERMITTED ((sl_status_t)0x1102) ///< The attribute cannot be read
#define SL_STATUS_BT_ATT_WRITE_NOT_PERMITTED ((sl_status_t)0x1103) ///< The attribute cannot be written
#define SL_STATUS_BT_ATT_INVALID_PDU ((sl_status_t)0x1104) ///< The attribute PDU was invalid
#define SL_STATUS_BT_ATT_INSUFFICIENT_AUTHENTICATION ((sl_status_t)0x1105) ///< The attribute requires authentication before it can be read or written.
#define SL_STATUS_BT_ATT_REQUEST_NOT_SUPPORTED ((sl_status_t)0x1106) ///< Attribute Server does not support the request received from the client.
#define SL_STATUS_BT_ATT_INVALID_OFFSET ((sl_status_t)0x1107) ///< Offset specified was past the end of the attribute
#define SL_STATUS_BT_ATT_INSUFFICIENT_AUTHORIZATION ((sl_status_t)0x1108) ///< The attribute requires authorization before it can be read or written.
#define SL_STATUS_BT_ATT_PREPARE_QUEUE_FULL ((sl_status_t)0x1109) ///< Too many prepare writes have been queued
#define SL_STATUS_BT_ATT_ATT_NOT_FOUND ((sl_status_t)0x110A) ///< No attribute found within the given attribute handle range.
#define SL_STATUS_BT_ATT_ATT_NOT_LONG ((sl_status_t)0x110B) ///< The attribute cannot be read or written using the Read Blob Request
#define SL_STATUS_BT_ATT_INSUFFICIENT_ENC_KEY_SIZE ((sl_status_t)0x110C) ///< The Encryption Key Size used for encrypting this link is insufficient.
#define SL_STATUS_BT_ATT_INVALID_ATT_LENGTH ((sl_status_t)0x110D) ///< The attribute value length is invalid for the operation
#define SL_STATUS_BT_ATT_UNLIKELY_ERROR ((sl_status_t)0x110E) ///< The attribute request that was requested has encountered an error that was unlikely, and therefore could not be completed as requested.
#define SL_STATUS_BT_ATT_INSUFFICIENT_ENCRYPTION ((sl_status_t)0x110F) ///< The attribute requires encryption before it can be read or written.
#define SL_STATUS_BT_ATT_UNSUPPORTED_GROUP_TYPE ((sl_status_t)0x1110) ///< The attribute type is not a supported grouping attribute as defined by a higher layer specification.
#define SL_STATUS_BT_ATT_INSUFFICIENT_RESOURCES ((sl_status_t)0x1111) ///< Insufficient Resources to complete the request
#define SL_STATUS_BT_ATT_OUT_OF_SYNC ((sl_status_t)0x1112) ///< The server requests the client to rediscover the database.
#define SL_STATUS_BT_ATT_VALUE_NOT_ALLOWED ((sl_status_t)0x1113) ///< The attribute parameter value was not allowed.
#define SL_STATUS_BT_ATT_APPLICATION ((sl_status_t)0x1180) ///< When this is returned in a BGAPI response, the application tried to read or write the value of a user attribute from the GATT database.
#define SL_STATUS_BT_ATT_WRITE_REQUEST_REJECTED ((sl_status_t)0x11FC) ///< The requested write operation cannot be fulfilled for reasons other than permissions.
#define SL_STATUS_BT_ATT_CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR_IMPROPERLY_CONFIGURED ((sl_status_t)0x11FD) ///< The Client Characteristic Configuration descriptor is not configured according to the requirements of the profile or service.
#define SL_STATUS_BT_ATT_PROCEDURE_ALREADY_IN_PROGRESS ((sl_status_t)0x11FE) ///< The profile or service request cannot be serviced because an operation that has been previously triggered is still in progress.
#define SL_STATUS_BT_ATT_OUT_OF_RANGE ((sl_status_t)0x11FF) ///< The attribute value is out of range as defined by a profile or service specification.
// Bluetooth Security Manager Protocol status codes
#define SL_STATUS_BT_SMP_PASSKEY_ENTRY_FAILED ((sl_status_t)0x1201) ///< The user input of passkey failed, for example, the user cancelled the operation
#define SL_STATUS_BT_SMP_OOB_NOT_AVAILABLE ((sl_status_t)0x1202) ///< Out of Band data is not available for authentication
#define SL_STATUS_BT_SMP_AUTHENTICATION_REQUIREMENTS ((sl_status_t)0x1203) ///< The pairing procedure cannot be performed as authentication requirements cannot be met due to IO capabilities of one or both devices
#define SL_STATUS_BT_SMP_CONFIRM_VALUE_FAILED ((sl_status_t)0x1204) ///< The confirm value does not match the calculated compare value
#define SL_STATUS_BT_SMP_PAIRING_NOT_SUPPORTED ((sl_status_t)0x1205) ///< Pairing is not supported by the device
#define SL_STATUS_BT_SMP_ENCRYPTION_KEY_SIZE ((sl_status_t)0x1206) ///< The resultant encryption key size is insufficient for the security requirements of this device
#define SL_STATUS_BT_SMP_COMMAND_NOT_SUPPORTED ((sl_status_t)0x1207) ///< The SMP command received is not supported on this device
#define SL_STATUS_BT_SMP_UNSPECIFIED_REASON ((sl_status_t)0x1208) ///< Pairing failed due to an unspecified reason
#define SL_STATUS_BT_SMP_REPEATED_ATTEMPTS ((sl_status_t)0x1209) ///< Pairing or authentication procedure is disallowed because too little time has elapsed since last pairing request or security request
#define SL_STATUS_BT_SMP_INVALID_PARAMETERS ((sl_status_t)0x120A) ///< The Invalid Parameters error code indicates: the command length is invalid or a parameter is outside of the specified range.
#define SL_STATUS_BT_SMP_DHKEY_CHECK_FAILED ((sl_status_t)0x120B) ///< Indicates to the remote device that the DHKey Check value received doesn't match the one calculated by the local device.
#define SL_STATUS_BT_SMP_NUMERIC_COMPARISON_FAILED ((sl_status_t)0x120C) ///< Indicates that the confirm values in the numeric comparison protocol do not match.
#define SL_STATUS_BT_SMP_BREDR_PAIRING_IN_PROGRESS ((sl_status_t)0x120D) ///< Indicates that the pairing over the LE transport failed due to a Pairing Request sent over the BR/EDR transport in process.
#define SL_STATUS_BT_SMP_CROSS_TRANSPORT_KEY_DERIVATION_GENERATION_NOT_ALLOWED ((sl_status_t)0x120E) ///< Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport.
#define SL_STATUS_BT_SMP_KEY_REJECTED ((sl_status_t)0x120F) ///< Indicates that the device chose not to accept a distributed key.
// Bluetooth Mesh status codes
#define SL_STATUS_BT_MESH_ALREADY_EXISTS ((sl_status_t)0x0501) ///< Returned when trying to add a key or some other unique resource with an ID which already exists
#define SL_STATUS_BT_MESH_DOES_NOT_EXIST ((sl_status_t)0x0502) ///< Returned when trying to manipulate a key or some other resource with an ID which does not exist
#define SL_STATUS_BT_MESH_LIMIT_REACHED ((sl_status_t)0x0503) ///< Returned when an operation cannot be executed because a pre-configured limit for keys, key bindings, elements, models, virtual addresses, provisioned devices, or provisioning sessions is reached
#define SL_STATUS_BT_MESH_INVALID_ADDRESS ((sl_status_t)0x0504) ///< Returned when trying to use a reserved address or add a "pre-provisioned" device using an address already used by some other device
#define SL_STATUS_BT_MESH_MALFORMED_DATA ((sl_status_t)0x0505) ///< In a BGAPI response, the user supplied malformed data; in a BGAPI event, the remote end responded with malformed or unrecognized data
#define SL_STATUS_BT_MESH_ALREADY_INITIALIZED ((sl_status_t)0x0506) ///< An attempt was made to initialize a subsystem that was already initialized.
#define SL_STATUS_BT_MESH_NOT_INITIALIZED ((sl_status_t)0x0507) ///< An attempt was made to use a subsystem that wasn't initialized yet. Call the subsystem's init function first.
#define SL_STATUS_BT_MESH_NO_FRIEND_OFFER ((sl_status_t)0x0508) ///< Returned when trying to establish a friendship as a Low Power Node, but no acceptable friend offer message was received.
#define SL_STATUS_BT_MESH_PROV_LINK_CLOSED ((sl_status_t)0x0509) ///< Provisioning link was unexpectedly closed before provisioning was complete.
#define SL_STATUS_BT_MESH_PROV_INVALID_PDU ((sl_status_t)0x050A) ///< An unrecognized provisioning PDU was received.
#define SL_STATUS_BT_MESH_PROV_INVALID_PDU_FORMAT ((sl_status_t)0x050B) ///< A provisioning PDU with wrong length or containing field values that are out of bounds was received.
#define SL_STATUS_BT_MESH_PROV_UNEXPECTED_PDU ((sl_status_t)0x050C) ///< An unexpected (out of sequence) provisioning PDU was received.
#define SL_STATUS_BT_MESH_PROV_CONFIRMATION_FAILED ((sl_status_t)0x050D) ///< The computed confirmation value did not match the expected value.
#define SL_STATUS_BT_MESH_PROV_OUT_OF_RESOURCES ((sl_status_t)0x050E) ///< Provisioning could not be continued due to insufficient resources.
#define SL_STATUS_BT_MESH_PROV_DECRYPTION_FAILED ((sl_status_t)0x050F) ///< The provisioning data block could not be decrypted.
#define SL_STATUS_BT_MESH_PROV_UNEXPECTED_ERROR ((sl_status_t)0x0510) ///< An unexpected error happened during provisioning.
#define SL_STATUS_BT_MESH_PROV_CANNOT_ASSIGN_ADDR ((sl_status_t)0x0511) ///< Device could not assign unicast addresses to all of its elements.
#define SL_STATUS_BT_MESH_ADDRESS_TEMPORARILY_UNAVAILABLE ((sl_status_t)0x0512) ///< Returned when trying to reuse an address of a previously deleted device before an IV Index Update has been executed.
#define SL_STATUS_BT_MESH_ADDRESS_ALREADY_USED ((sl_status_t)0x0513) ///< Returned when trying to assign an address that is used by one of the devices in the Device Database, or by the Provisioner itself.
#define SL_STATUS_BT_MESH_PUBLISH_NOT_CONFIGURED ((sl_status_t)0x0514) ///< Application key or publish address are not set
#define SL_STATUS_BT_MESH_APP_KEY_NOT_BOUND ((sl_status_t)0x0515) ///< Application key is not bound to a model
// Bluetooth Mesh foundation status codes
#define SL_STATUS_BT_MESH_FOUNDATION_INVALID_ADDRESS ((sl_status_t)0x1301) ///< Returned when address in request was not valid
#define SL_STATUS_BT_MESH_FOUNDATION_INVALID_MODEL ((sl_status_t)0x1302) ///< Returned when model identified is not found for a given element
#define SL_STATUS_BT_MESH_FOUNDATION_INVALID_APP_KEY ((sl_status_t)0x1303) ///< Returned when the key identified by AppKeyIndex is not stored in the node
#define SL_STATUS_BT_MESH_FOUNDATION_INVALID_NET_KEY ((sl_status_t)0x1304) ///< Returned when the key identified by NetKeyIndex is not stored in the node
#define SL_STATUS_BT_MESH_FOUNDATION_INSUFFICIENT_RESOURCES ((sl_status_t)0x1305) ///< Returned when The node cannot serve the request due to insufficient resources
#define SL_STATUS_BT_MESH_FOUNDATION_KEY_INDEX_EXISTS ((sl_status_t)0x1306) ///< Returned when the key identified is already stored in the node and the new NetKey value is different
#define SL_STATUS_BT_MESH_FOUNDATION_INVALID_PUBLISH_PARAMS ((sl_status_t)0x1307) ///< Returned when the model does not support the publish mechanism
#define SL_STATUS_BT_MESH_FOUNDATION_NOT_SUBSCRIBE_MODEL ((sl_status_t)0x1308) ///< Returned when the model does not support the subscribe mechanism
#define SL_STATUS_BT_MESH_FOUNDATION_STORAGE_FAILURE ((sl_status_t)0x1309) ///< Returned when storing of the requested parameters failed
#define SL_STATUS_BT_MESH_FOUNDATION_NOT_SUPPORTED ((sl_status_t)0x130A) ///< Returned when requested setting is not supported
#define SL_STATUS_BT_MESH_FOUNDATION_CANNOT_UPDATE ((sl_status_t)0x130B) ///< Returned when the requested update operation cannot be performed due to general constraints
#define SL_STATUS_BT_MESH_FOUNDATION_CANNOT_REMOVE ((sl_status_t)0x130C) ///< Returned when the requested delete operation cannot be performed due to general constraints
#define SL_STATUS_BT_MESH_FOUNDATION_CANNOT_BIND ((sl_status_t)0x130D) ///< Returned when the requested bind operation cannot be performed due to general constraints
#define SL_STATUS_BT_MESH_FOUNDATION_TEMPORARILY_UNABLE ((sl_status_t)0x130E) ///< Returned when The node cannot start advertising with Node Identity or Proxy since the maximum number of parallel advertising is reached
#define SL_STATUS_BT_MESH_FOUNDATION_CANNOT_SET ((sl_status_t)0x130F) ///< Returned when the requested state cannot be set
#define SL_STATUS_BT_MESH_FOUNDATION_UNSPECIFIED ((sl_status_t)0x1310) ///< Returned when an unspecified error took place
#define SL_STATUS_BT_MESH_FOUNDATION_INVALID_BINDING ((sl_status_t)0x1311) ///< Returned when the NetKeyIndex and AppKeyIndex combination is not valid for a Config AppKey Update
// -----------------------------------------------------------------------------
// Wi-Fi Errors
#define SL_STATUS_WIFI_INVALID_KEY ((sl_status_t)0x0B01) ///< Invalid firmware keyset
#define SL_STATUS_WIFI_FIRMWARE_DOWNLOAD_TIMEOUT ((sl_status_t)0x0B02) ///< The firmware download took too long
#define SL_STATUS_WIFI_UNSUPPORTED_MESSAGE_ID ((sl_status_t)0x0B03) ///< Unknown request ID or wrong interface ID used
#define SL_STATUS_WIFI_WARNING ((sl_status_t)0x0B04) ///< The request is successful but some parameters have been ignored
#define SL_STATUS_WIFI_NO_PACKET_TO_RECEIVE ((sl_status_t)0x0B05) ///< No Packets waiting to be received
#define SL_STATUS_WIFI_SLEEP_GRANTED ((sl_status_t)0x0B08) ///< The sleep mode is granted
#define SL_STATUS_WIFI_SLEEP_NOT_GRANTED ((sl_status_t)0x0B09) ///< The WFx does not go back to sleep
#define SL_STATUS_WIFI_SECURE_LINK_MAC_KEY_ERROR ((sl_status_t)0x0B10) ///< The SecureLink MAC key was not found
#define SL_STATUS_WIFI_SECURE_LINK_MAC_KEY_ALREADY_BURNED ((sl_status_t)0x0B11) ///< The SecureLink MAC key is already installed in OTP
#define SL_STATUS_WIFI_SECURE_LINK_RAM_MODE_NOT_ALLOWED ((sl_status_t)0x0B12) ///< The SecureLink MAC key cannot be installed in RAM
#define SL_STATUS_WIFI_SECURE_LINK_FAILED_UNKNOWN_MODE ((sl_status_t)0x0B13) ///< The SecureLink MAC key installation failed
#define SL_STATUS_WIFI_SECURE_LINK_EXCHANGE_FAILED ((sl_status_t)0x0B14) ///< SecureLink key (re)negotiation failed
#define SL_STATUS_WIFI_WRONG_STATE ((sl_status_t)0x0B18) ///< The device is in an inappropriate state to perform the request
#define SL_STATUS_WIFI_CHANNEL_NOT_ALLOWED ((sl_status_t)0x0B19) ///< The request failed due to regulatory limitations
#define SL_STATUS_WIFI_NO_MATCHING_AP ((sl_status_t)0x0B1A) ///< The connection request failed because no suitable AP was found
#define SL_STATUS_WIFI_CONNECTION_ABORTED ((sl_status_t)0x0B1B) ///< The connection request was aborted by host
#define SL_STATUS_WIFI_CONNECTION_TIMEOUT ((sl_status_t)0x0B1C) ///< The connection request failed because of a timeout
#define SL_STATUS_WIFI_CONNECTION_REJECTED_BY_AP ((sl_status_t)0x0B1D) ///< The connection request failed because the AP rejected the device
#define SL_STATUS_WIFI_CONNECTION_AUTH_FAILURE ((sl_status_t)0x0B1E) ///< The connection request failed because the WPA handshake did not complete successfully
#define SL_STATUS_WIFI_RETRY_EXCEEDED ((sl_status_t)0x0B1F) ///< The request failed because the retry limit was exceeded
#define SL_STATUS_WIFI_TX_LIFETIME_EXCEEDED ((sl_status_t)0x0B20) ///< The request failed because the MSDU life time was exceeded
// -----------------------------------------------------------------------------
// MVP Driver and MVP Math status codes
#define SL_STATUS_COMPUTE_DRIVER_FAULT ((sl_status_t)0x1501) ///< Critical fault
#define SL_STATUS_COMPUTE_DRIVER_ALU_NAN ((sl_status_t)0x1502) ///< ALU operation output NaN
#define SL_STATUS_COMPUTE_DRIVER_ALU_OVERFLOW ((sl_status_t)0x1503) ///< ALU numeric overflow
#define SL_STATUS_COMPUTE_DRIVER_ALU_UNDERFLOW ((sl_status_t)0x1504) ///< ALU numeric underflow
#define SL_STATUS_COMPUTE_DRIVER_STORE_CONVERSION_OVERFLOW ((sl_status_t)0x1505) ///< Overflow during array store
#define SL_STATUS_COMPUTE_DRIVER_STORE_CONVERSION_UNDERFLOW ((sl_status_t)0x1506) ///< Underflow during array store conversion
#define SL_STATUS_COMPUTE_DRIVER_STORE_CONVERSION_INFINITY ((sl_status_t)0x1507) ///< Infinity encountered during array store conversion
#define SL_STATUS_COMPUTE_DRIVER_STORE_CONVERSION_NAN ((sl_status_t)0x1508) ///< NaN encountered during array store conversion
#define SL_STATUS_COMPUTE_MATH_NAN ((sl_status_t)0x1512) ///< MATH NaN encountered
#define SL_STATUS_COMPUTE_MATH_INFINITY ((sl_status_t)0x1513) ///< MATH Infinity encountered
#define SL_STATUS_COMPUTE_MATH_OVERFLOW ((sl_status_t)0x1514) ///< MATH numeric overflow
#define SL_STATUS_COMPUTE_MATH_UNDERFLOW ((sl_status_t)0x1515) ///< MATH numeric underflow
// Zigbee status codes
#define SL_STATUS_ZIGBEE_PACKET_HANDOFF_DROPPED ((sl_status_t)0x0C01) ///< Packet is dropped by packet-handoff callbacks
#define SL_STATUS_ZIGBEE_DELIVERY_FAILED ((sl_status_t)0x0C02) ///< The APS layer attempted to send or deliver a message and failed
#define SL_STATUS_ZIGBEE_MAX_MESSAGE_LIMIT_REACHED ((sl_status_t)0x0C03) ///< The maximum number of in-flight messages ::EMBER_APS_UNICAST_MESSAGE_COUNT has been reached
#define SL_STATUS_ZIGBEE_BINDING_IS_ACTIVE ((sl_status_t)0x0C04) ///< The application is trying to delete or overwrite a binding that is in use
#define SL_STATUS_ZIGBEE_ADDRESS_TABLE_ENTRY_IS_ACTIVE ((sl_status_t)0x0C05) ///< The application is trying to overwrite an address table entry that is in use
#define SL_STATUS_ZIGBEE_MOVE_FAILED ((sl_status_t)0x0C06) ///< After moving, a mobile node's attempt to re-establish contact with the network failed
#define SL_STATUS_ZIGBEE_NODE_ID_CHANGED ((sl_status_t)0x0C07) ///< The local node ID has changed. The application can get the new node ID by calling ::sl_zigbee_get_node_id()
#define SL_STATUS_ZIGBEE_INVALID_SECURITY_LEVEL ((sl_status_t)0x0C08) ///< The chosen security level is not supported by the stack
#define SL_STATUS_ZIGBEE_IEEE_ADDRESS_DISCOVERY_IN_PROGRESS ((sl_status_t)0x0C09) ///< An error occurred when trying to encrypt at the APS Level
#define SL_STATUS_ZIGBEE_APS_ENCRYPTION_ERROR ((sl_status_t)0x0C0A) ///< An error occurred when trying to encrypt at the APS Level
#define SL_STATUS_ZIGBEE_SECURITY_STATE_NOT_SET ((sl_status_t)0x0C0B) ///< There was an attempt to form or join a network with security without calling ::sl_zigbee_set_initial_security_state() first
#define SL_STATUS_ZIGBEE_TOO_SOON_FOR_SWITCH_KEY ((sl_status_t)0x0C0C) ///< There was an attempt to broadcast a key switch too quickly after broadcasting the next network key. The Trust Center must wait at least a period equal to the broadcast timeout so that all routers have a chance to receive the broadcast of the new network key
#define SL_STATUS_ZIGBEE_SIGNATURE_VERIFY_FAILURE ((sl_status_t)0x0C0D) ///< The received signature corresponding to the message that was passed to the CBKE Library failed verification and is not valid
#define SL_STATUS_ZIGBEE_KEY_NOT_AUTHORIZED ((sl_status_t)0x0C0E) ///< The message could not be sent because the link key corresponding to the destination is not authorized for use in APS data messages
#define SL_STATUS_ZIGBEE_BINDING_HAS_CHANGED ((sl_status_t)0x0C0F) ///< The application tried to use a binding that has been remotely modified and the change has not yet been reported to the application
#define SL_STATUS_ZIGBEE_TRUST_CENTER_SWAP_EUI_HAS_CHANGED ((sl_status_t)0x0C10) ///< The EUI of the Trust center has changed due to a successful rejoin after TC Swapout
#define SL_STATUS_ZIGBEE_TRUST_CENTER_SWAP_EUI_HAS_NOT_CHANGED ((sl_status_t)0x0C11) ///< A Trust Center Swapout Rejoin has occurred without the EUI of the TC changing
#define SL_STATUS_ZIGBEE_INSUFFICIENT_RANDOM_DATA ((sl_status_t)0x0C12) ///< An attempt to generate random bytes failed because of insufficient random data from the radio
#define SL_STATUS_ZIGBEE_SOURCE_ROUTE_FAILURE ((sl_status_t)0x0C13) ///< A Zigbee route error command frame was received indicating that a source routed message from this node failed en route
#define SL_STATUS_ZIGBEE_MANY_TO_ONE_ROUTE_FAILURE ((sl_status_t)0x0C14) ///< A Zigbee route error command frame was received indicating that a message sent to this node along a many-to-one route failed en route
#define SL_STATUS_ZIGBEE_STACK_AND_HARDWARE_MISMATCH ((sl_status_t)0x0C15) ///< A critical and fatal error indicating that the version of the stack trying to run does not match with the chip it's running on
#define SL_STATUS_ZIGBEE_PAN_ID_CHANGED ((sl_status_t)0x0C16) ///< The local PAN ID has changed. The application can get the new PAN ID by calling ::emberGetPanId()
#define SL_STATUS_ZIGBEE_CHANNEL_CHANGED ((sl_status_t)0x0C17) ///< The channel has changed.
#define SL_STATUS_ZIGBEE_NETWORK_OPENED ((sl_status_t)0x0C18) ///< The network has been opened for joining.
#define SL_STATUS_ZIGBEE_NETWORK_CLOSED ((sl_status_t)0x0C19) ///< The network has been closed for joining.
#define SL_STATUS_ZIGBEE_RECEIVED_KEY_IN_THE_CLEAR ((sl_status_t)0x0C1A) ///< An attempt was made to join a Secured Network using a pre-configured key, but the Trust Center sent back a Network Key in-the-clear when an encrypted Network Key was required. (::EMBER_REQUIRE_ENCRYPTED_KEY)
#define SL_STATUS_ZIGBEE_NO_NETWORK_KEY_RECEIVED ((sl_status_t)0x0C1B) ///< An attempt was made to join a Secured Network, but the device did not receive a Network Key.
#define SL_STATUS_ZIGBEE_NO_LINK_KEY_RECEIVED ((sl_status_t)0x0C1C) ///< After a device joined a Secured Network, a Link Key was requested (::EMBER_GET_LINK_KEY_WHEN_JOINING) but no response was ever received.
#define SL_STATUS_ZIGBEE_PRECONFIGURED_KEY_REQUIRED ((sl_status_t)0x0C1D) ///< An attempt was made to join a Secured Network without a pre-configured key, but the Trust Center sent encrypted data using a pre-configured key.
#define SL_STATUS_ZIGBEE_EZSP_ERROR ((sl_status_t)0x0C1E) ///< A Zigbee EZSP error has occured. Track the origin and corresponding EzspStatus for more info.
// -----------------------------------------------------------------------------
// Data Types
/** @brief define global status variable. */
typedef uint32_t sl_status_t;
// -----------------------------------------------------------------------------
// Functions
#ifdef __cplusplus
extern "C" {
#endif
/********************************************************************************************************
* sl_status_get_string_n()
*
* @brief Get a copy of the status string associated to the status code passed, up to
* 'buffer_length' length, if the string associated to the status code is enabled. If not,
* the error code number, in hex, prefixed by "SL_STATUS_" will be copied in the buffer
* instead.
* For example, the buffer would either contain "SL_STATUS_FAIL" if that status string is
* enabled, or "SL_STATUS_0x0001" if the string is disabled, as SL_STATUS_FAIL's
* value is 0x0001.
*
* @param status The status code from which to obtain the status string.
*
* @param buffer Pointer to a buffer in which the status string will be copied. A terminating
* null-character will be appended after the copied status string.
*
* @param buffer_length Maximum number of characters that can be written in the buffer, including the
* terminating null-character. If the status string would be longer than the
* available length, it will be truncated and a null-terminating character will
* be the last character contained in the buffer.
*
* @return The number of characters that would have been written if the buffer_length had been
* sufficiently large, not counting the terminating null character.
* If the status code is invalid, 0 or a negative number is returned.
* Notice that only when this returned value is strictly positive and less than
* buffer_length, the status string has been completely written in the buffer.
*******************************************************************************************************/
int32_t sl_status_get_string_n(sl_status_t status, char *buffer, uint32_t buffer_length);
/********************************************************************************************************
* sl_status_print()
*
* @brief Print, through printf, the string associated to the passed status code. If the string
* associated to the status code is enabled, the status string will be printed, for example
* "SL_STATUS_OK". If the string associated to the status code is disabled, the status number,
* in hex, prefixed by "SL_STATUS_" will be printed instead, for example "SL_STATUS_0x0000",
* as SL_STATUS_OK's value is 0x0000.
*
* @param status The status code of which to print the status string.
*******************************************************************************************************/
void sl_status_print(sl_status_t status);
#ifdef __cplusplus
}
#endif
/** @} (end addtogroup status) */
#endif /* SL_STATUS_H */

View File

@@ -0,0 +1,108 @@
/***************************************************************************//**
* @file sli_cmsis_os2_ext_task_register.h
* @brief Abstraction for Task Registers (Thread Local Variables)
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SLI_CMSIS_OS2_EXT_TASK_REGISTER_H
#define SLI_CMSIS_OS2_EXT_TASK_REGISTER_H
#if defined(SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#endif
// Validate the chosen RTOS
#if !defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && !defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
#error "The task register API currently only supports FreeRTOS or MicriumOS"
#endif
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
#include "FreeRTOS.h"
#include "task.h"
// Validate maximum of task registers
#if configNUM_SDK_THREAD_LOCAL_STORAGE_POINTERS > 255
#error "The task register API currently only supports a maximum of 255 registers"
#endif
// Check if the user has overwritten the configNUM_THREAD_LOCAL_STORAGE_POINTERS config
#if configNUM_THREAD_LOCAL_STORAGE_POINTERS < (configNUM_USER_THREAD_LOCAL_STORAGE_POINTERS \
+ configNUM_SDK_THREAD_LOCAL_STORAGE_POINTERS)
#error "Please use the configUSER_NUM_THREAD_LOCAL_STORAGE_POINTERS to configure the local storage pointers"
#endif
#elif defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
#include "os.h"
#endif
#include "sl_status.h"
#include "cmsis_os2.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
typedef uint8_t sli_task_register_id_t;
#elif defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
typedef OS_REG_ID sli_task_register_id_t;
#endif
/***************************************************************************//**
* Get the task register ID.
*
* @param[out] reg_id The task register id
* @return sl_status_t The status result
******************************************************************************/
sl_status_t sli_osTaskRegisterNew(sli_task_register_id_t *reg_id);
/***************************************************************************//**
* Get the task register value.
*
* @param thread_id CMSIS-RTOS2 thread identification
* @param reg_id Task register ID
* @param[out] value Value of the task register requested
* @return sl_status_t The status result
******************************************************************************/
sl_status_t sli_osTaskRegisterGetValue(const osThreadId_t thread_id,
const sli_task_register_id_t reg_id,
uint32_t *value);
/***************************************************************************//**
* Set the task register to the provided value.
*
* @param thread_id CMSIS-RTOS2 thread identification
* @param reg_id Task register ID
* @param[out] value Value of the task register to set
* @return sl_status_t The status result
******************************************************************************/
sl_status_t sli_osTaskRegisterSetValue(const osThreadId_t thread_id,
const sli_task_register_id_t reg_id,
const uint32_t value);
#ifdef __cplusplus
}
#endif
#endif // SLI_CMSIS_OS2_EXT_TASK_REGISTER_H

View File

@@ -0,0 +1,131 @@
/***************************************************************************//**
* @file
* @brief Code Classification API (Internal)
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef _SLI_CODE_CLASSIFICATION_H_
#define _SLI_CODE_CLASSIFICATION_H_
// Standard Code Classes
#define SL_CODE_CLASS_TIME_CRITICAL timecritical
/******************************************************************************/
/* Helper Macros */
/******************************************************************************/
// Stringize tokens
#define _SL_CC_STRINGIZE(X) #X
#define _SL_CC_XSTRINGIZE(X) _SL_CC_STRINGIZE(X)
#define _SL_CC_CONCAT3(A, B, C) A B C
#define _SL_CC_CONCAT4(A, B, C, D) A B C D
/******************************************************************************/
/* Compiler Specific Macros */
/******************************************************************************/
// The directive that is built is dependent on the compiler. Section names are
// appended with an identifier generated from __COUNTER__ and __LINE__ so that
// functions are more likely to be separated into unique sections. Doing this
// allows the linker to discard unused functions with more granularity.
#if defined(__GNUC__) && !(defined(__llvm__) || defined(SLI_CODE_CLASSIFICATION_DISABLE))
// With GCC, __attribute__ can be used to specify the input section of
// functions.
#define _SL_CC_SECTION(section_name, count, line) \
__attribute__((section(_SL_CC_CONCAT3(_SL_CC_XSTRINGIZE(section_name), _SL_CC_XSTRINGIZE(count), _SL_CC_XSTRINGIZE(line)))))
#elif defined(__ICCARM__) && !defined(SLI_CODE_CLASSIFICATION_DISABLE)
// With IAR, _Pragma can be used to specify the input section of
// functions.
#define _SL_CC_SECTION(section_name, count, line) \
_Pragma(_SL_CC_XSTRINGIZE(_SL_CC_CONCAT4(location =, _SL_CC_XSTRINGIZE(section_name), _SL_CC_XSTRINGIZE(count), _SL_CC_XSTRINGIZE(line))))
#elif defined(__llvm__) && !defined(SLI_CODE_CLASSIFICATION_DISABLE)
// With llvm, __attribute__ can be used to specify the input section of
// functions.
// However the syntax of the string within the section directive is
// dependent on the specifics of the target backend (e.g. osx)
#if defined(__MACH__) && defined(SLI_CODE_CLASSIFICATION_OSX_ENABLE)
// code classifcation is not supported on OSX and can have weird
// interactions for executable code so it is disabled by default
// since it can be useful for code analysis allow it as an opt-in feature
#define _SL_CC_SECTION(section_name, count, line) \
__attribute__((section("sl_cc,code_class" _SL_CC_XSTRINGIZE(count) _SL_CC_XSTRINGIZE(line))))
#else
#define _SL_CC_SECTION(section_name, count, line)
#endif // defined(__MACH__)
#elif defined(SLI_CODE_CLASSIFICATION_DISABLE)
#define _SL_CC_SECTION(section_name, count, line)
#else
#error "(sli_code_classification.h): Code classification does not support \
the chosen compiler."
#endif // __GNUC__
/******************************************************************************/
/* Compiler Generic Macros */
/******************************************************************************/
// Build the linker section name based on the name of the component and the
// code classes.
#define _SL_CODE_CLASS_SECTION_CONCAT1(component, p1) \
text_ ## component ## _ ## p1
#define _SL_CODE_CLASS_SECTION_CONCAT2(component, p1, p2) \
text_ ## component ## _ ## p1 ## _ ## p2
// Build the compiler specific directives
#define _SL_CODE_CLASS1(component, c1) \
_SL_CC_SECTION(_SL_CODE_CLASS_SECTION_CONCAT1(component, c1), __COUNTER__, __LINE__)
#define _SL_CODE_CLASS2(component, c1, c2) \
_SL_CC_SECTION(_SL_CODE_CLASS_SECTION_CONCAT2(component, c1, c2), __COUNTER__, __LINE__)
// Utilities to dispatch a macro with the correct number of parameters.
// Update COUNT_N and COUNT macros if the upper limit of code class
// combinations increases.
#define _SL_CC_COUNT_N(_1, _2, N, ...) N
#define _SL_CC_COUNT(...) _SL_CC_COUNT_N(__VA_ARGS__, 2, 1)
#define _SL_CC_IDENTITY(N) N
#define _SL_CC_APPLY(macro, ...) _SL_CC_IDENTITY(macro(__VA_ARGS__))
// Dispatch _SL_CODE_CLASSX with the correct number of parameters.
#define _SL_CC_DISPATCH(N) _SL_CODE_CLASS ## N
/******************************************************************************/
/* Macro API (Internal) */
/******************************************************************************/
// Variadic macro to specify the code class membership of a function.
#define SL_CODE_CLASSIFY(component, ...) \
_SL_CC_IDENTITY(_SL_CC_APPLY(_SL_CC_DISPATCH, _SL_CC_COUNT(__VA_ARGS__)))(component, __VA_ARGS__)
#endif // _SLI_CODE_CLASSIFICATION_H_

View File

@@ -0,0 +1,76 @@
/***************************************************************************//**
* @file
* @brief Assert API
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_assert.h"
#include <stdbool.h>
/***************************************************************************//**
* @addtogroup assert
* @details
* This module contains functions to control the ASSERT peripheral of Silicon
* Labs 32-bit MCUs and SoCs.
* @{
******************************************************************************/
#if defined(DEBUG_EFM) && !defined(DEBUG_EFM_USER)
/***************************************************************************//**
* @brief
* EFM internal assert handling.
*
* This function is invoked through EFM_ASSERT() macro usage only and should
* not be used explicitly.
*
* This implementation enters an indefinite loop, allowing
* the use of a debugger to determine a cause of failure. By defining
* DEBUG_EFM_USER to the preprocessor for all files, a user-defined version
* of this function must be defined and will be invoked instead, possibly
* providing output of assertion location.
*
* @note
* This function is not used unless DEBUG_EFM is defined
* during preprocessing of EFM_ASSERT() usage.
*
* @param[in] file
* Name of the source file where assertion failed.
*
* @param[in] line
* A line number in the source file where assertion failed.
******************************************************************************/
void assertEFM(const char *file, int line)
{
(void)file; /* Unused parameter */
(void)line; /* Unused parameter */
while (true) {
}
}
#endif /* DEBUG_EFM && !DEBUG_EFM_USER */
/** @} (end addtogroup assert) */

View File

@@ -0,0 +1,61 @@
/***************************************************************************//**
* @file
* @brief CMSIS OS2 Common
*******************************************************************************
* # License
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include <stddef.h>
#include "sl_assert.h"
#include "sl_status.h"
#include "cmsis_os2.h"
/***************************************************************************//**
* Convert OsStatus from CMSIS-RTOS2 to sl_status type.
******************************************************************************/
sl_status_t sl_cmsis_os_convert_status(osStatus_t os_status)
{
switch (os_status) {
case osOK:
return SL_STATUS_OK;
case osError:
return SL_STATUS_FAIL;
case osErrorTimeout:
return SL_STATUS_TIMEOUT;
case osErrorResource:
return SL_STATUS_NOT_AVAILABLE;
case osErrorParameter:
return SL_STATUS_INVALID_PARAMETER;
case osErrorNoMemory:
return SL_STATUS_NO_MORE_RESOURCE;
case osErrorISR:
return SL_STATUS_ISR;
case osStatusReserved:
default:
EFM_ASSERT(0);
return SL_STATUS_FAIL;
}
}

View File

@@ -0,0 +1,395 @@
/***************************************************************************//**
* @file
* @brief Core API implemented for CortexM
*******************************************************************************
* # License
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_core.h"
#include "sl_core_config.h"
#include "sl_common.h"
#include "em_device.h"
/**************************************************************************//**
* @addtogroup sl_core
* @{
*****************************************************************************/
/*******************************************************************************
************************** STRUCTS ****************************************
******************************************************************************/
/// A Cycle Counter Instance.
typedef struct {
uint32_t start; /*!< Cycle counter at start of recording. */
uint32_t cycles; /*!< Cycles elapsed in last recording. */
uint32_t max; /*!< Max recorded cycles since last reset or init. */
} dwt_cycle_counter_handle_t;
/*******************************************************************************
*************************** LOCAL VARIABLES *******************************
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
// cycle counter to record atomic sections
dwt_cycle_counter_handle_t atomic_cycle_counter = { 0 };
// cycle counter to record critical sections
dwt_cycle_counter_handle_t critical_cycle_counter = { 0 };
#endif
/** @endcond */
/*******************************************************************************
*************************** LOCAL FUNCTIONS *******************************
******************************************************************************/
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
static void cycle_counter_start(dwt_cycle_counter_handle_t *handle);
static void cycle_counter_stop(dwt_cycle_counter_handle_t *handle);
#endif
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Disable interrupts.
******************************************************************************/
SL_WEAK void CORE_CriticalDisableIrq(void)
{
__disable_irq();
}
/***************************************************************************//**
* @brief
* Enable interrupts.
* @note
* __ISB() makes sure pending interrupts are executed before returning.
* This can be a problem if the first instruction after changing the BASEPRI
* or PRIMASK assumes that the pending interrupts have already been processed.
******************************************************************************/
SL_WEAK void CORE_CriticalEnableIrq(void)
{
__enable_irq();
__ISB();
}
/***************************************************************************//**
* @brief
* Enter a CRITICAL section.
******************************************************************************/
SL_WEAK CORE_irqState_t CORE_EnterCritical(void)
{
CORE_irqState_t irqState = __get_PRIMASK();
__disable_irq();
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
if (irqState == 0U) {
cycle_counter_start(&critical_cycle_counter);
}
#endif
return irqState;
}
/***************************************************************************//**
* @brief
* Exit a CRITICAL section.
* @note
* __ISB() makes sure pending interrupts are executed before returning.
* This can be a problem if the first instruction after changing the BASEPRI
* or PRIMASK assumes that the pending interrupts have already been processed.
******************************************************************************/
SL_WEAK void CORE_ExitCritical(CORE_irqState_t irqState)
{
if (irqState == 0U) {
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
cycle_counter_stop(&critical_cycle_counter);
#endif
__enable_irq();
__ISB();
}
}
/***************************************************************************//**
* @brief
* Brief interrupt enable/disable sequence to allow handling of
* pending interrupts.
******************************************************************************/
SL_WEAK void CORE_YieldCritical(void)
{
if ((__get_PRIMASK() & 1U) != 0U) {
__enable_irq();
__ISB();
__disable_irq();
}
}
/***************************************************************************//**
* @brief
* Disable interrupts.
******************************************************************************/
SL_WEAK void CORE_AtomicDisableIrq(void)
{
#ifndef __CM0PLUS_REV
__set_BASEPRI(CORE_ATOMIC_BASE_PRIORITY_LEVEL << (8UL - __NVIC_PRIO_BITS));
#else
__disable_irq();
#endif
}
/***************************************************************************//**
* @brief
* Enable interrupts.
* @note
* __ISB() makes sure pending interrupts are executed before returning.
* This can be a problem if the first instruction after changing the BASEPRI
* or PRIMASK assumes that the pending interrupts have already been processed.
******************************************************************************/
SL_WEAK void CORE_AtomicEnableIrq(void)
{
#ifndef __CM0PLUS_REV
__set_BASEPRI(0);
#else
__enable_irq();
#endif
__ISB();
}
/***************************************************************************//**
* @brief
* Enter an ATOMIC section.
******************************************************************************/
SL_WEAK CORE_irqState_t CORE_EnterAtomic(void)
{
#ifndef __CM0PLUS_REV
CORE_irqState_t irqState = __get_BASEPRI();
__set_BASEPRI(CORE_ATOMIC_BASE_PRIORITY_LEVEL << (8U - __NVIC_PRIO_BITS));
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
if ((irqState & (CORE_ATOMIC_BASE_PRIORITY_LEVEL << (8U - __NVIC_PRIO_BITS)))
!= (CORE_ATOMIC_BASE_PRIORITY_LEVEL << (8U - __NVIC_PRIO_BITS))) {
cycle_counter_start(&atomic_cycle_counter);
}
#endif
return irqState;
#else
CORE_irqState_t irqState = __get_PRIMASK();
__disable_irq();
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
if (irqState == 0U) {
cycle_counter_start(&critical_cycle_counter);
}
#endif
return irqState;
#endif
}
/***************************************************************************//**
* @brief
* Exit an ATOMIC section.
* @note
* __ISB() makes sure pending interrupts are executed before returning.
* This can be a problem if the first instruction after changing the BASEPRI
* or PRIMASK assumes that the pending interrupts have already been processed.
******************************************************************************/
SL_WEAK void CORE_ExitAtomic(CORE_irqState_t irqState)
{
#ifndef __CM0PLUS_REV
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
if ((irqState & (CORE_ATOMIC_BASE_PRIORITY_LEVEL << (8U - __NVIC_PRIO_BITS)))
!= (CORE_ATOMIC_BASE_PRIORITY_LEVEL << (8U - __NVIC_PRIO_BITS))) {
cycle_counter_stop(&atomic_cycle_counter);
}
#endif
__set_BASEPRI(irqState);
__ISB();
#else
if (irqState == 0U) {
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
cycle_counter_stop(&critical_cycle_counter);
#endif
__enable_irq();
__ISB();
}
#endif
}
/***************************************************************************//**
* @brief
* Brief interrupt enable/disable sequence to allow handling of
* pending interrupts.
******************************************************************************/
SL_WEAK void CORE_YieldAtomic(void)
{
#ifndef __CM0PLUS_REV
CORE_irqState_t basepri = __get_BASEPRI();
if (basepri >= (CORE_ATOMIC_BASE_PRIORITY_LEVEL << (8U - __NVIC_PRIO_BITS))) {
__set_BASEPRI(0);
__ISB();
__set_BASEPRI(basepri);
}
#else
if ((__get_PRIMASK() & 1U) != 0U) {
__enable_irq();
__ISB();
__disable_irq();
}
#endif
}
/***************************************************************************//**
* @brief
* Check whether the current CPU operation mode is handler mode.
******************************************************************************/
SL_WEAK bool CORE_InIrqContext(void)
{
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0U;
}
/***************************************************************************//**
* @brief
* Check if interrupts are disabled.
******************************************************************************/
SL_WEAK bool CORE_IrqIsDisabled(void)
{
#ifndef __CM0PLUS_REV
return ((__get_PRIMASK() & 1U) == 1U)
|| (__get_BASEPRI() >= (CORE_ATOMIC_BASE_PRIORITY_LEVEL
<< (8U - __NVIC_PRIO_BITS)));
#else
return (__get_PRIMASK() & 1U == 1U);
#endif
}
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
/***************************************************************************//**
* @brief
* Start a recording.
*
* @param[in] handle
* Pointer to initialized counter handle.
*
* @note SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
******************************************************************************/
static void cycle_counter_start(dwt_cycle_counter_handle_t *handle)
{
handle->start = DWT->CYCCNT;
}
#endif //(SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
/***************************************************************************//**
* @brief
* Stop a recording.
*
* @param[in] handle
* Pointer to initialized counter handle.
*
* @note SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
******************************************************************************/
static void cycle_counter_stop(dwt_cycle_counter_handle_t *handle)
{
handle->cycles = DWT->CYCCNT - handle->start;
if (handle->cycles > handle->max) {
handle->max = handle->cycles;
}
}
#endif //(SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
/***************************************************************************//**
* @brief
* Returns the max time spent in critical section.
******************************************************************************/
uint32_t CORE_get_max_time_critical_section(void)
{
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
return critical_cycle_counter.max;
#else
return 0U;
#endif //(SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
}
/***************************************************************************//**
* @brief
* Returns the max time spent in atomic section.
******************************************************************************/
uint32_t CORE_get_max_time_atomic_section(void)
{
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
return atomic_cycle_counter.max;
#else
return 0U;
#endif //(SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
}
/***************************************************************************//**
* @brief
* Clears the max time spent in atomic section.
******************************************************************************/
void CORE_clear_max_time_critical_section(void)
{
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
critical_cycle_counter.max = 0;
#endif //(SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
}
/***************************************************************************//**
* @brief
* Clears the max time spent in atomic section.
******************************************************************************/
void CORE_clear_max_time_atomic_section(void)
{
#if (SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
atomic_cycle_counter.max = 0;
#endif //(SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING == 1)
}
/***************************************************************************//**
* @brief
* Reset chip routine.
******************************************************************************/
void CORE_ResetSystem(void)
{
// Ensure all outstanding memory accesses including buffered writes are
// completed before reset
__DSB();
// Keep priority group unchanged
SCB->AIRCR = (0x5FAUL << SCB_AIRCR_VECTKEY_Pos)
| (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk)
| SCB_AIRCR_SYSRESETREQ_Msk;
// Ensure completion of memory access
__DSB();
// Wait until reset
for (;; ) {
__NOP();
}
}
/** @} (end addtogroup sl_core) */

View File

@@ -0,0 +1,190 @@
/***************************************************************************//**
* @file
* @brief Single Link List
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_assert.h"
#include "sl_slist.h"
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
/***************************************************************************//**
* Initializes a singly-linked list.
******************************************************************************/
void sl_slist_init(sl_slist_node_t **head)
{
*head = 0;
}
/***************************************************************************//**
* Add given item at beginning of list.
******************************************************************************/
void sl_slist_push(sl_slist_node_t **head,
sl_slist_node_t *item)
{
EFM_ASSERT((item != NULL) && (head != NULL));
item->node = *head;
*head = item;
}
/***************************************************************************//**
* Add item at end of list.
******************************************************************************/
void sl_slist_push_back(sl_slist_node_t **head,
sl_slist_node_t *item)
{
sl_slist_node_t **node_ptr = head;
EFM_ASSERT((item != NULL) && (head != NULL));
while (*node_ptr != NULL) {
node_ptr = &((*node_ptr)->node);
}
item->node = NULL;
*node_ptr = item;
}
/***************************************************************************//**
* Removes and returns first element of list.
******************************************************************************/
sl_slist_node_t *sl_slist_pop(sl_slist_node_t **head)
{
sl_slist_node_t *item;
EFM_ASSERT(head != NULL);
item = *head;
if (item == NULL) {
return (NULL);
}
*head = item->node;
item->node = NULL;
return (item);
}
/***************************************************************************//**
* Insert item after given item.
******************************************************************************/
void sl_slist_insert(sl_slist_node_t *item,
sl_slist_node_t *pos)
{
EFM_ASSERT((item != NULL) && (pos != NULL));
item->node = pos->node;
pos->node = item;
}
/***************************************************************************//**
* Add item at end of list.
******************************************************************************/
void sl_slist_join(sl_slist_node_t **head_list_1,
sl_slist_node_t **head_list_2)
{
sl_slist_node_t **node_ptr = head_list_1;
EFM_ASSERT((head_list_2 != NULL)
&& (head_list_1 != NULL));
while (*node_ptr != NULL) {
node_ptr = &((*node_ptr)->node);
}
*node_ptr = *head_list_2;
*head_list_2 = NULL;
}
/***************************************************************************//**
* Remove item from list.
******************************************************************************/
void sl_slist_remove(sl_slist_node_t **head,
sl_slist_node_t *item)
{
sl_slist_node_t **node_ptr;
EFM_ASSERT((item != NULL) && (head != NULL));
for (node_ptr = head; *node_ptr != NULL; node_ptr = &((*node_ptr)->node)) {
if (*node_ptr == item) {
*node_ptr = item->node;
item->node = NULL;
return;
}
}
}
/***************************************************************************//**
* Sorts list items.
******************************************************************************/
void sl_slist_sort(sl_slist_node_t **head,
bool (*cmp_fnct)(sl_slist_node_t *item_l,
sl_slist_node_t *item_r))
{
bool swapped;
sl_slist_node_t **pp_item_l;
EFM_ASSERT((head != NULL) && (cmp_fnct != NULL));
do {
swapped = false;
pp_item_l = head;
// Loop until end of list is found.
while ((*pp_item_l != NULL) && ((*pp_item_l)->node != NULL)) {
sl_slist_node_t *p_item_r = (*pp_item_l)->node;
bool ordered;
// Call provided compare fnct.
ordered = cmp_fnct(*pp_item_l, p_item_r);
if (ordered == false) {
// If order is not correct, swap items.
sl_slist_node_t *p_tmp = p_item_r->node;
// Swap the two items.
p_item_r->node = *pp_item_l;
(*pp_item_l)->node = p_tmp;
*pp_item_l = p_item_r;
pp_item_l = &(p_item_r->node);
// Indicate a swap has been done.
swapped = true;
} else {
pp_item_l = &((*pp_item_l)->node);
}
}
// Re-loop until no items have been swapped.
} while (swapped == true);
}

View File

@@ -0,0 +1,115 @@
/***************************************************************************//**
* @file
* @brief SystemCall API
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
/***************************************************************************//**
* @addtogroup systemcalls
* @details
* This module reimplements the syscalls that don't have the definition in the
* bare metal project.
* This prevents linker warnings.
* @{
******************************************************************************/
#include "sl_compiler.h"
struct stat;
struct timeval;
struct timezone;
__WEAK int _close(int file)
{
(void)file;
return -1;
}
__WEAK void _exit(int status)
{
(void)status;
/* Convince GCC that this function never returns. */
for (;; ) {
;
}
}
__WEAK int _fstat(int file, struct stat *st)
{
(void)file;
(void)(void *)st;
return 0;
}
__WEAK int _getpid(void)
{
return 1;
}
__WEAK int _isatty(int file)
{
(void)file;
return 1;
}
__WEAK int _kill(int pid, int sig)
{
(void)pid;
(void)sig;
return -1;
}
__WEAK int _lseek(int file, int ptr, int dir)
{
(void)file;
(void)ptr;
(void)dir;
return 0;
}
__WEAK int _read(int file, char *ptr, int len)
{
(void)file;
(void)(void *)ptr;
(void)len;
return 0;
}
__WEAK int _write(int file, const char *ptr, int len)
{
(void)file;
(void)(const void *)ptr;
(void)len;
return 0;
}
__WEAK int _gettimeofday(struct timeval *tv, struct timezone *tz)
{
(void)(void *)tv;
(void)(void *)tz;
return 0;
}

View File

@@ -0,0 +1,143 @@
/***************************************************************************//**
* @file sli_cmsis_os2_ext_task_register.c
* @brief Abstraction for Task Registers (Thread Local Variables)
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_assert.h"
#include "sli_cmsis_os2_ext_task_register.h"
#include "sl_cmsis_os2_common.h"
/*******************************************************************************
*************************** LOCAL VARIABLES ********************************
******************************************************************************/
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
/***************************************************************************//**
* Get a task register ID
******************************************************************************/
sl_status_t sli_osTaskRegisterNew(sli_task_register_id_t *reg_id)
{
sl_status_t status = SL_STATUS_FAIL;
if (reg_id == NULL) {
return SL_STATUS_FAIL;
}
#if defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
RTOS_ERR err;
*reg_id = OSTaskRegGetID(&err);
if (RTOS_ERR_CODE_GET(err) == RTOS_ERR_NONE) {
status = SL_STATUS_OK;
}
#elif defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
static uint8_t register_count = 0;
if (register_count > (configNUM_SDK_THREAD_LOCAL_STORAGE_POINTERS - 1)) {
return SL_STATUS_FAIL;
}
*reg_id = register_count + configNUM_USER_THREAD_LOCAL_STORAGE_POINTERS;
++register_count;
status = SL_STATUS_OK;
#else
#error "Task registers abstraction only supports MicriumOS or FreeRTOS"
#endif
return status;
}
/***************************************************************************//**
* Get the task register
******************************************************************************/
sl_status_t sli_osTaskRegisterGetValue(const osThreadId_t thread_id,
const sli_task_register_id_t reg_id,
uint32_t *value)
{
sl_status_t status = SL_STATUS_FAIL;
#if defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
RTOS_ERR err;
osThread_t *thread;
if (value == NULL) {
return SL_STATUS_FAIL;
}
if (thread_id != NULL) {
thread = (osThread_t *)thread_id;
*value = OSTaskRegGet(&thread->tcb, reg_id, &err);
} else {
*value = OSTaskRegGet(NULL, reg_id, &err);
}
if (RTOS_ERR_CODE_GET(err) == RTOS_ERR_NONE) {
status = SL_STATUS_OK;
}
#elif defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
*value = (uint32_t)pvTaskGetThreadLocalStoragePointer(thread_id, reg_id);
status = SL_STATUS_OK;
#else
#error "Task registers abstraction only supports MicriumOS or FreeRTOS"
#endif
return status;
}
/***************************************************************************//**
* Set the task register
******************************************************************************/
sl_status_t sli_osTaskRegisterSetValue(const osThreadId_t thread_id,
const sli_task_register_id_t reg_id,
const uint32_t value)
{
sl_status_t status = SL_STATUS_FAIL;
#if defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
RTOS_ERR err;
osThread_t *thread;
if (thread_id != NULL) {
thread = (osThread_t *)thread_id;
OSTaskRegSet(&thread->tcb, reg_id, (OS_REG)value, &err);
} else {
OSTaskRegSet(NULL, reg_id, (OS_REG)value, &err);
}
if (RTOS_ERR_CODE_GET(err) == RTOS_ERR_NONE) {
status = SL_STATUS_OK;
}
#elif defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
vTaskSetThreadLocalStoragePointer(thread_id, reg_id, (void *)value);
status = SL_STATUS_OK;
#else
#error "Task registers abstraction only supports MicriumOS or FreeRTOS"
#endif
return status;
}

View File

@@ -0,0 +1,40 @@
/***************************************************************************//**
* @file
* @brief GCC startup file
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
/* The startup files contain a stack and heap symbol in addition
* to the vector table. The size of these internal stack and heap
* objects depend on the build system providing two macros on the
* commandline called __STACK_SIZE and __HEAP_SIZE.
*
* We provide alternative stack and heap symbols in the sl_memory_region.c
* file which can be configured in a separate config file. Go to
* sl_memory_manager_config.h to configure the stack and heap size. */
#define __STACK_SIZE 0x0
#define __HEAP_SIZE 0x0

View File

@@ -0,0 +1,39 @@
/***************************************************************************//**
* @file
* @brief Heap and stack memory
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_MEMORY_H
#define SL_MEMORY_H
#include "sl_memory_manager_region.h"
#ifndef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_2024_6
#warning "This file is deprecated as of Simplicity SDK 2024.6. Content was moved to sl_memory_manager.h."
#endif
#endif // SL_MEMORY_H

View File

@@ -0,0 +1,39 @@
/***************************************************************************//**
* @file
* @brief Memory region types
*******************************************************************************
* # License
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_REGION_H
#define SL_REGION_H
#include "sl_memory_manager_region.h"
#ifndef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_2024_6
#warning "This file is deprecated as of Simplicity SDK 2024.6. Content was moved to sl_memory_manager.h."
#endif
#endif

View File

@@ -0,0 +1,191 @@
/***************************************************************************//**
* @file
* @brief Button Driver
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_BUTTON_H
#define SL_BUTTON_H
#include "sl_common.h"
#include "sl_status.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup button Button API
* @brief Generic Button API
* @{
******************************************************************************/
/*******************************************************************************
****************************** DEFINES ************************************
******************************************************************************/
#define BUTTON_ERROR 0xFFFF ///< Error when trying to return state
/*******************************************************************************
***************************** DATA TYPES *********************************
******************************************************************************/
typedef uint8_t sl_button_mode_t; ///< BUTTON mode
typedef uint8_t sl_button_state_t; ///< BUTTON state
typedef struct sl_button sl_button_t; ///< BUTTON Instance structure
/// A BUTTON instance
typedef struct sl_button {
void *context; ///< The context for this BUTTON instance
sl_status_t (*init)(const sl_button_t *handle); ///< Member function to initialize BUTTON instance
void (*poll)(const sl_button_t *handle); ///< Member function to poll BUTTON
void (*enable)(const sl_button_t *handle); ///< Member function to enable BUTTON
void (*disable)(const sl_button_t *handle); ///< Member function to disable BUTTON
sl_button_state_t (*get_state)(const sl_button_t *handle); ///< Member function to retrieve BUTTON state
} sl_button;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* Button driver init. This function should be called before calling any other
* button function. Sets up the GPIO. Sets the mode of operation. Sets up the
* interrupts based on the mode of operation.
*
* @param[in] handle Pointer to button instance
*
* @return Status Code:
* - SL_STATUS_OK
******************************************************************************/
sl_status_t sl_button_init(const sl_button_t *handle);
/***************************************************************************//**
* Get button state.
*
* @param[in] handle Pointer to button instance
*
* @return Button state Current state of the button
******************************************************************************/
sl_button_state_t sl_button_get_state(const sl_button_t *handle);
/***************************************************************************//**
* Enable the button.
*
* @param[in] handle Pointer to button instance
*
******************************************************************************/
void sl_button_enable(const sl_button_t *handle);
/***************************************************************************//**
* Disable the button.
*
* @param[in] handle Pointer to button instance
*
******************************************************************************/
void sl_button_disable(const sl_button_t *handle);
/***************************************************************************//**
* Poll the button.
*
* @param[in] handle Pointer to button instance
******************************************************************************/
void sl_button_poll_step(const sl_button_t *handle);
/***************************************************************************//**
* A callback called in interrupt context whenever a button changes its state.
*
* @remark Can be implemented by the application if required. This function
* can contain the functionality to be executed in response to changes of state
* in each of the buttons, or callbacks to appropriate functionality.
*
* @note The button state should not be updated in this function, it is updated
* by specific button driver prior to arriving here
*
@param[out] handle Pointer to button instance
******************************************************************************/
void sl_button_on_change(const sl_button_t *handle);
/** @} (end addtogroup button) */
// ******** THE REST OF THE FILE IS DOCUMENTATION ONLY !***********************
/// @addtogroup button Button API
/// @{
///
/// @details
///
/// @n @section buttondrv_intro Introduction
///
/// The button driver is a platfom level software module that manages the initialization
/// and reading of various types of buttons. There is currently one type of button
/// supported by the button driver:
///
/// @li @ref simple_button
///
/// All button functions are called through the generic driver, which then references
/// functions in the simple button and other potential future button drivers.
///
/// @n @section buttondrv_config Configuration
///
/// All button instances are configured with an @ref sl_button_t struct and a type specific
/// context struct. These structs are automatically generated after a button is set up
/// using Simplicity Studio's wizard, along with a function definition for initializing all
/// LEDs of that type. Specific setup for the simple button is in the following section.
///
/// - [Simple Button Configuration](/gecko-platform/<docspace-docleaf-version>/platform-driver/simple-button#simple-button-configuration)
///
/// @n @section buttondrv_usage Usage
///
/// Once the button structs are defined, the common button functions can be called being
/// passed an instance of sl_button_t, which will be redirected to calling the type specific
/// version of that function. The common functions include the following:
///
/// @li @ref sl_button_init
/// @li @ref sl_button_get_state
/// @li @ref sl_button_poll_step
/// @li @ref sl_button_on_change
///
/// @ref sl_button_init must be called before attempting to read the state of the button.
///
/// The button driver can either be used with interrupt mode, polling or polling with debounce.
/// In the case of using interrupt mode, @ref sl_button_on_change can be implemented by the
/// application if required. This function can contain functionality to be executed in response
/// to button event or callbacks to appropriate functionality.
/// In the case of polling and polling with debounce mode, @ref sl_button_poll_step is used to
/// update the state, and needs to be called from a tick function or similar by the user.
/// These mode can be configured per button instance in the instance specific config file.
///
/// Both the interrupt and polling methods obtain the button state for the user by calling
/// @ref sl_button_get_state.
///
/// @} end group button ********************************************************/
#ifdef __cplusplus
}
#endif
#endif // SL_BUTTON_H

View File

@@ -0,0 +1,225 @@
/***************************************************************************//**
* @file
* @brief Simple Button Driver
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SIMPLE_BUTTON_H
#define SL_SIMPLE_BUTTON_H
#include "sl_button.h"
#include "sl_gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup button
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup simple_button Simple Button Driver
* @details Simple Button Driver module provides APIs to initalize and read
* simple buttons. Subsequent sections provide more insight into button
* driver configuration and usage.
* @{
******************************************************************************/
/*******************************************************************************
****************************** DEFINES ************************************
******************************************************************************/
#define SL_SIMPLE_BUTTON_MODE_POLL 0U ///< BUTTON input capture using polling
#define SL_SIMPLE_BUTTON_MODE_POLL_AND_DEBOUNCE 1U ///< BUTTON input capture using polling and debouncing
#define SL_SIMPLE_BUTTON_MODE_INTERRUPT 2U ///< BUTTON input capture using interrupt
#define SL_SIMPLE_BUTTON_DISABLED 2U ///< BUTTON state is disabled
#define SL_SIMPLE_BUTTON_PRESSED 1U ///< BUTTON state is pressed
#define SL_SIMPLE_BUTTON_RELEASED 0U ///< BUTTON state is released
#define SL_SIMPLE_BUTTON_GET_STATE(context) (((sl_simple_button_context_t *)(context))->state) ///< BUTTON member function to get state
#define SL_SIMPLE_BUTTON_GET_PORT(context) (((sl_simple_button_context_t *)(context))->port) ///< BUTTON member function to get port
#define SL_SIMPLE_BUTTON_GET_PIN(context) (((sl_simple_button_context_t *)(context))->pin) ///< BUTTON member function to get pin
#define SL_SIMPLE_BUTTON_GET_MODE(context) (((sl_simple_button_context_t *)(context))->mode) ///< BUTTON member function to get mode
/*******************************************************************************
***************************** DATA TYPES *********************************
******************************************************************************/
/// A Simple BUTTON instance
typedef struct {
sl_button_state_t state; ///< Current button state
uint16_t history; ///< History of button states
sl_gpio_port_t port; ///< Button port
uint8_t pin; ///< Button pin
sl_button_mode_t mode; ///< Mode of operation
} sl_simple_button_context_t;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* Initialize the simple button driver.
*
* @param[in] handle Pointer to button handle:
* - sl_button_t
*
* @return Status Code:
* - SL_STATUS_OK
******************************************************************************/
sl_status_t sl_simple_button_init(const sl_button_t *handle);
/***************************************************************************//**
* Get the current state of the simple button.
*
* @param[in] handle Pointer to button handle:
* - sl_button_t
*
* @return Button State: Current state of the button
* - SL_SIMPLE_BUTTON_PRESSED
* - SL_SIMPLE_BUTTON_RELEASED
******************************************************************************/
sl_button_state_t sl_simple_button_get_state(const sl_button_t *handle);
/***************************************************************************//**
* Poll the simple button. (button mode - poll / poll and debonuce)
*
* @param[in] handle Pointer to button handle:
* - sl_button_t
******************************************************************************/
void sl_simple_button_poll_step(const sl_button_t *handle);
/***************************************************************************//**
* Enable the simple button.
*
* @param[in] handle Pointer to button handle:
* - sl_button_t
******************************************************************************/
void sl_simple_button_enable(const sl_button_t *handle);
/***************************************************************************//**
* Disable the simple button.
*
* @param[in] handle Pointer to button handle:
* - sl_button_t
******************************************************************************/
void sl_simple_button_disable(const sl_button_t *handle);
/** @} (end addtogroup simple_button) */
/** @} (end addtogroup button) */
// ******** THE REST OF THE FILE IS DOCUMENTATION ONLY !***********************
/// @addtogroup simple_button Simple Button Driver
/// @{
///
/// @details
///
///
/// @n @section simple_button_intro Introduction
///
/// The Simple Button driver is a module of the button driver that provides the functionality
/// to initialize and read simple buttons.
///
/// @n @section simple_button_config Simple Button Configuration
///
/// Simple buttons use the @ref sl_button_t struct and their @ref sl_simple_button_context_t
/// struct. These are automatically generated into the following files, as well as
/// instance specific headers with macro definitions in them. The samples below
/// are for a single instance called "inst0".
///
/// @code{.c}
///// sl_simple_button_instances.c
///
///#include "sl_simple_button.h"
///#include "sl_simple_button_inst0_config.h"
///
///sl_simple_button_context_t simple_inst0_context = {
/// .state = 0,
/// .history = 0,
/// .port = SL_SIMPLE_BUTTON_INST0_PORT,
/// .pin = SL_SIMPLE_BUTTON_INST0_PIN,
/// .mode = SL_SIMPLE_BUTTON_INST0_MODE,
///};
///
///const sl_button_t sl_button_inst0 = {
/// .context = &simple_inst0_context,
/// .init = sl_simple_button_init,
/// .get_state = sl_simple_button_get_state,
/// .poll = sl_simple_button_poll_step,
///};
///
///const sl_button_t *sl_simple_button_array[] = {&sl_button_inst0};
///const uint8_t simple_button_count = 1;
///
///void sl_simple_button_init_instances(void)
///{
/// sl_button_init(&sl_button_inst0);
///}
///
///void sl_simple_button_poll_instances(void)
///{
/// sl_button_poll_step(&sl_button_inst0);
///}
/// @endcode
///
/// @note The sl_simple_button_instances.c file is shown with only one instance, but if more
/// were in use they would all appear in this .c file.
///
/// @code{.c}
///// sl_simple_button_instances.h
///
///#ifndef SL_SIMPLE_BUTTON_INSTANCES_H
///#define SL_SIMPLE_BUTTON_INSTANCES_H
///
///#include "sl_simple_button.h"
///
///extern const sl_button_t sl_button_inst0;
///
///void sl_simple_button_init_instances(void);
///void sl_simple_button_poll_instances(void);
///
///#endif // SL_SIMPLE_BUTTON_INSTANCES_H
/// @endcode
///
/// @note The sl_simple_button_instances.h file is shown with only one instance, but if more
/// were in use they would all appear in this .h file.
///
/// @n @section simple_button_usage Simple Button Usage
///
/// The simple button driver has no differences in its usage from the common button driver.
/// See @ref buttondrv_usage.
///
/// @} end group simple_button ********************************************************/
#ifdef __cplusplus
}
#endif
#endif // SL_SIMPLE_BUTTON_H

View File

@@ -0,0 +1,76 @@
/***************************************************************************//**
* @file
* @brief Button Driver
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_button.h"
#include <stddef.h>
sl_status_t sl_button_init(const sl_button_t *handle)
{
if (handle->init != NULL) {
return handle->init(handle);
} else {
return SL_STATUS_NULL_POINTER;
}
}
sl_button_state_t sl_button_get_state(const sl_button_t *handle)
{
if (handle->get_state != NULL) {
return handle->get_state(handle);
} else {
return (sl_button_state_t)BUTTON_ERROR;
}
}
void sl_button_poll_step(const sl_button_t *handle)
{
if (handle->poll != NULL) {
handle->poll(handle);
}
}
void sl_button_enable(const sl_button_t *handle)
{
if (handle->enable != NULL) {
handle->enable(handle);
}
}
void sl_button_disable(const sl_button_t *handle)
{
if (handle->disable != NULL) {
handle->disable(handle);
}
}
SL_WEAK void sl_button_on_change(const sl_button_t *handle)
{
(void)handle;
}

View File

@@ -0,0 +1,205 @@
/***************************************************************************//**
* @file
* @brief Simple Button Driver
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_simple_button.h"
#include "sl_simple_button_config.h"
#include "sl_clock_manager.h"
#if (SL_SIMPLE_BUTTON_DEBOUNCE_BITS < 1U)
#undef SL_SIMPLE_BUTTON_DEBOUNCE_BITS
#define SL_SIMPLE_BUTTON_DEBOUNCE_BITS 1U
#endif
#if (SL_SIMPLE_BUTTON_DEBOUNCE_BITS > 15U)
#undef SL_SIMPLE_BUTTON_DEBOUNCE_BITS
#define SL_SIMPLE_BUTTON_DEBOUNCE_BITS 15U
#endif
static const uint16_t check_press = (uint16_t)(0xffff << SL_SIMPLE_BUTTON_DEBOUNCE_BITS);
static const uint16_t check_release = (uint16_t)(~(0x1 << SL_SIMPLE_BUTTON_DEBOUNCE_BITS));
static const uint16_t debounce_window = (uint16_t)(0xffff << (SL_SIMPLE_BUTTON_DEBOUNCE_BITS + 1));
/***************************************************************************//**
* An internal callback called in interrupt context whenever a button changes
* its state. (mode - SL_SIMPLE_BUTTON_MODE_INTERRUPT)
*
* @note The button state is updated by this function. The application callback
* should not update it again.
*
* @param[in] interrupt_no Interrupt number (pin number)
* @param[in] ctx Pointer to button handle
******************************************************************************/
static void sli_simple_button_on_change(uint8_t interrupt_no, void *ctx)
{
(void)interrupt_no;
sl_button_t *button = (sl_button_t *)ctx;
sl_simple_button_context_t *simple_button = button->context;
sl_gpio_t gpio = {
.port = simple_button->port,
.pin = simple_button->pin
};
bool pin_value;
if (simple_button->state != SL_SIMPLE_BUTTON_DISABLED) {
sl_gpio_get_pin_input(&gpio, &pin_value);
simple_button->state = ((bool)pin_value == SL_SIMPLE_BUTTON_POLARITY);
sl_button_on_change(button);
}
}
sl_status_t sl_simple_button_init(const sl_button_t *handle)
{
int32_t interrupt_em4, interrupt_ext;
sl_status_t status;
sl_button_t *button = (sl_button_t *)handle;
sl_simple_button_context_t *simple_button = button->context;
sl_gpio_t gpio = {
.port = simple_button->port,
.pin = simple_button->pin
};
bool pin_value;
sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_GPIO);
sl_gpio_set_pin_mode(&gpio, SL_SIMPLE_BUTTON_GPIO_MODE, SL_SIMPLE_BUTTON_GPIO_DOUT);
sl_gpio_get_pin_input(&gpio, &pin_value);
simple_button->state = ((bool)pin_value == SL_SIMPLE_BUTTON_POLARITY);
if (simple_button->mode == SL_SIMPLE_BUTTON_MODE_INTERRUPT) {
interrupt_em4 = SL_GPIO_INTERRUPT_UNAVAILABLE;
interrupt_ext = SL_GPIO_INTERRUPT_UNAVAILABLE;
// Try to register an EM4WU interrupt for the given pin
status = sl_gpio_configure_wakeup_em4_interrupt(&gpio,
&interrupt_em4,
SL_SIMPLE_BUTTON_POLARITY,
(sl_gpio_irq_callback_t)sli_simple_button_on_change,
button);
if (interrupt_em4 == SL_GPIO_INTERRUPT_UNAVAILABLE) {
// if the pin not EM4WU-compatible, instead register a regualr interrupt
status = sl_gpio_configure_external_interrupt(&gpio,
&interrupt_ext,
SL_GPIO_INTERRUPT_RISING_FALLING_EDGE,
(sl_gpio_irq_callback_t)sli_simple_button_on_change,
button);
EFM_ASSERT(status == SL_STATUS_OK);
} else {
// If the pin is EM4WU-compatible, setup the pin as an EM4WU pin
// Since EM4WU interrupts are level-sensitive and not edge-sensitive, also register a regular edge-sensitive interrupt to capture the other edge
uint8_t flags;
if (SL_SIMPLE_BUTTON_POLARITY == 0) {
flags = SL_GPIO_INTERRUPT_RISING_EDGE;
} else if (SL_SIMPLE_BUTTON_POLARITY == 1) {
flags = SL_GPIO_INTERRUPT_FALLING_EDGE;
}
status = sl_gpio_configure_external_interrupt(&gpio,
&interrupt_ext,
flags,
(sl_gpio_irq_callback_t)sli_simple_button_on_change,
button);
EFM_ASSERT(status == SL_STATUS_OK);
}
}
return SL_STATUS_OK;
}
sl_button_state_t sl_simple_button_get_state(const sl_button_t *handle)
{
sl_button_t *button = (sl_button_t *)handle;
sl_simple_button_context_t *simple_button = button->context;
return simple_button->state;
}
void sl_simple_button_poll_step(const sl_button_t *handle)
{
sl_button_t *button = (sl_button_t *)handle;
sl_simple_button_context_t *simple_button = button->context;
bool button_press, pin_value;
sl_gpio_t gpio = {
.port = simple_button->port,
.pin = simple_button->pin
};
if (simple_button->state == SL_SIMPLE_BUTTON_DISABLED) {
return;
}
sl_gpio_get_pin_input(&gpio, &pin_value);
button_press = (bool)pin_value;
if (simple_button->mode == SL_SIMPLE_BUTTON_MODE_POLL_AND_DEBOUNCE) {
uint16_t history = simple_button->history;
history = (history << 1) | (button_press ^ SL_SIMPLE_BUTTON_POLARITY) | (debounce_window);
if (history == check_press) {
simple_button->state = SL_SIMPLE_BUTTON_PRESSED;
}
if (history == check_release) {
simple_button->state = SL_SIMPLE_BUTTON_RELEASED;
}
simple_button->history = history;
} else if (simple_button->mode == SL_SIMPLE_BUTTON_MODE_POLL) {
simple_button->state = (button_press == SL_SIMPLE_BUTTON_POLARITY);
}
}
void sl_simple_button_enable(const sl_button_t *handle)
{
sl_button_t *button = (sl_button_t *)handle;
sl_simple_button_context_t *simple_button = button->context;
// Return if the button is not disabled
if (simple_button->state != SL_SIMPLE_BUTTON_DISABLED) {
return;
}
// Clear history
simple_button->history = 0;
// Reinit button
sl_simple_button_init(handle);
}
void sl_simple_button_disable(const sl_button_t *handle)
{
sl_button_t *button = (sl_button_t *)handle;
sl_simple_button_context_t *simple_button = button->context;
// Return if the button is disabled
if (simple_button->state == SL_SIMPLE_BUTTON_DISABLED) {
return;
}
if (simple_button->mode == SL_SIMPLE_BUTTON_MODE_INTERRUPT) {
sl_gpio_deconfigure_external_interrupt(simple_button->pin);
}
// Disable the button
simple_button->state = SL_SIMPLE_BUTTON_DISABLED;
}

View File

@@ -0,0 +1,521 @@
/***************************************************************************//**
* @file
* @brief General Purpose IO (GPIO) driver API
*******************************************************************************
* # License
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_GPIO_H
#define SL_GPIO_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include "sl_status.h"
#include "sl_device_gpio.h"
#ifndef EM_GPIO_H
#define gpioPortA 0
#define gpioPortB 1
#define gpioPortC 2
#define gpioPortD 3
#define gpioPortE 4
#define gpioPortF 5
#define gpioPortG 6
#define gpioPortH 7
#define gpioPortI 8
#define gpioPortJ 9
#define gpioPortK 10
#endif
/* *INDENT-OFF* */
// *****************************************************************************
/// @addtogroup gpio GPIO - General Purpose Input Output
/// @brief General Purpose Input Output driver
///
/// @li @ref gpio_intro
///
///@n @section gpio_intro Introduction
/// This module contains functions to control the GPIO peripheral of Silicon Labs 32-bit MCUs and SoCs.
/// The GPIO driver is used for external and EM4 interrupt configuration, port and pin configuration.
/// as well as manages the interrupt handler.
///
/// @{
// *****************************************************************************
/* *INDENT-ON* */
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/// GPIO Pin directions.
SL_ENUM(sl_gpio_pin_direction_t) {
/// Input direction.
SL_GPIO_PIN_DIRECTION_IN = 0,
/// Output direction.
SL_GPIO_PIN_DIRECTION_OUT
};
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Structure for GPIO port and pin configuration.
******************************************************************************/
typedef struct {
sl_gpio_mode_t mode;
sl_gpio_pin_direction_t direction;
} sl_gpio_pin_config_t;
/*******************************************************************************
******************************* TYPEDEFS **********************************
******************************************************************************/
/***************************************************************************//**
* GPIO interrupt callback function pointer.
*
* @param int_no The pin interrupt number to which the callback function is invoked for.
* @param context Pointer to callback context.
******************************************************************************/
typedef void (*sl_gpio_irq_callback_t)(uint8_t int_no, void *context);
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* Initialization of GPIO driver module.
*
* @return SL_STATUS_OK if initialization is successful.
******************************************************************************/
sl_status_t sl_gpio_init(void);
/***************************************************************************//**
* Sets the pin direction of GPIO pin.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[in] pin_dir Pin direction of GPIO pin.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMATER if any of the port, pin, direction parameters are invalid.
* SL_STATUS_INVALID_STATE if GPIO configuration is in lock state.
******************************************************************************/
sl_status_t sl_gpio_set_pin_direction(const sl_gpio_t *gpio,
sl_gpio_pin_direction_t pin_dir);
/***************************************************************************//**
* Set the pin mode and set/clear the pin for GPIO pin.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[in] mode The desired pin mode.
* @param[in] output_value Value to set/clear for pin output on the port.
* Determines the pull-up/pull-down direction of the pin for
* some input mode configurations.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if any of the port, pin, mode parameters are invalid.
* SL_STATUS_INVALID_STATE if GPIO configuration is in locked state.
******************************************************************************/
sl_status_t sl_gpio_set_pin_mode(const sl_gpio_t *gpio,
sl_gpio_mode_t mode,
bool output_value);
/***************************************************************************//**
* Gets the current configuration selected pin on selected port.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[out] pin_config Pointer to pin configuration such as mode and direction.
* Pointer acts as an output and returns the configuration of
* selected pin on selected port.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if any of the port, pin parameters are invalid.
* SL_STATUS_NULL_POINTER if pin_config is passed as null.
******************************************************************************/
sl_status_t sl_gpio_get_pin_config(const sl_gpio_t *gpio,
sl_gpio_pin_config_t *pin_config);
/***************************************************************************//**
* Sets the selected pin of the selected port.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
******************************************************************************/
sl_status_t sl_gpio_set_pin(const sl_gpio_t *gpio);
/***************************************************************************//**
* Clears the selected pin of the selected port.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
******************************************************************************/
sl_status_t sl_gpio_clear_pin(const sl_gpio_t *gpio);
/***************************************************************************//**
* Toggles the state of selected pin on selected port.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
******************************************************************************/
sl_status_t sl_gpio_toggle_pin(const sl_gpio_t *gpio);
/***************************************************************************//**
* Gets the output state of selected pin on selected port.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[out] pin_value Pointer to return output state of selected pin on selected port
* when configured to output mode.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
* SL_STATUS_NULL_POINTER if pin_value passed as null.
******************************************************************************/
sl_status_t sl_gpio_get_pin_output(const sl_gpio_t *gpio,
bool *pin_value);
/***************************************************************************//**
* Gets the input state of selected pin on selected port.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[out] pin_value Pointer to return input state of selected pin on selected port
* when configured to input mode.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
* SL_STATUS_NULL_POINTER if pin_value passed as null.
******************************************************************************/
sl_status_t sl_gpio_get_pin_input(const sl_gpio_t *gpio,
bool *pin_value);
/***************************************************************************//**
* Sets the selected pin(s) of selected port.
*
* @param[in] port The GPIO port to access.
* @param[in] pins Bit mask for pins to set.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if port is invalid.
******************************************************************************/
sl_status_t sl_gpio_set_port(sl_gpio_port_t port,
uint32_t pins);
/***************************************************************************//**
* Clears the selected pin(s) of selected port.
*
* @param[in] port The GPIO Port to access.
* @param[in] pins Bit mask for bits to clear.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if port is invalid.
******************************************************************************/
sl_status_t sl_gpio_clear_port(sl_gpio_port_t port,
uint32_t pins);
/***************************************************************************//**
* Gets the output state of pins of selected port.
*
* @param[in] gpio The GPIO Port to access.
* @param[out] port_value Pointer to return output state of pins on selected port.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if port is invalid.
* SL_STATUS_NULL_POINTER if port_value passed as null.
******************************************************************************/
sl_status_t sl_gpio_get_port_output(sl_gpio_port_t port,
uint32_t *port_value);
/***************************************************************************//**
* Gets the input state of pins of selected port.
*
* @param[in] gpio The GPIO Port to access.
* @param[out] port_value Pointer to return output state of pins on selected port.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if port is invalid.
* SL_STATUS_NULL_POINTER if port_value passed as null.
******************************************************************************/
sl_status_t sl_gpio_get_port_input(sl_gpio_port_t port,
uint32_t *port_value);
/***************************************************************************//**
* Configures the GPIO pin interrupt.
*
* @details By default, this function can be used to register a callback which shall be called upon
* interrupt generated for a given pin interrupt number and enables interrupt.
* This function configures and enables the external interrupt and performs
* callback registration.
* It is recommended to use sl_gpio_deconfigure_external_interrupt()
* to disable the interrupt and unregister the callback.
* see @ref sl_gpio_deconfigure_external_interrupt for more information.
* If a valid interrupt number is provided, operation will proceed accordingly.
* Otherwise, a valid interrupt number will be generated based on provided port and
* pin and used for subsequent operations.
*
* @note If the user has a valid interrupt number to provide as input, it can be used.
* If the user does not have an interrupt number, they can pass -1 (SL_GPIO_INTERRUPT_UNAVAILABLE)
* as value to variable int_no.
* The int_no parameter serves even as an output, a pointer to convey the interrupt number
* for cases where user lacks an interrupt number.
* @note the pin number can be selected freely within a group.
* Interrupt numbers are divided into 4 groups (int_no / 4) and valid pin
* number within the interrupt groups are:
* 0: pins 0-3 (interrupt number 0-3)
* 1: pins 4-7 (interrupt number 4-7)
* 2: pins 8-11 (interrupt number 8-11)
* 3: pins 12-15 (interrupt number 12-15)
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[in/out] int_no Pointer to interrupt number to trigger.
* Pointer that serves as both an input and an output to return int_no
* when the user lacks an int_no.
* @param[in] flags Interrupt flags for interrupt configuration.
* Determines the interrupt to get trigger based on rising/falling edge.
* @param[in] gpio_callback A pointer to gpio callback function.
* @param[in] context A pointer to the callback context.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if any of the port, pin, flag parameters are invalid.
* SL_STATUS_NULL_POINTER if the int_no is passed as NULL.
* SL_STATUS_NOT_FOUND if there's no available interrupt number.
******************************************************************************/
sl_status_t sl_gpio_configure_external_interrupt(const sl_gpio_t *gpio,
int32_t *int_no,
sl_gpio_interrupt_flag_t flags,
sl_gpio_irq_callback_t gpio_callback,
void *context);
/***************************************************************************//**
* Deconfigures the GPIO external pin interrupt.
*
* @details This function can be used to deconfigure the external GPIO interrupt.
* This function performs callback unregistration, clears and disables the
* given interrupt.
*
* @note the pin number can be selected freely within a group.
* Interrupt numbers are divided into 4 groups (int_no / 4) and valid pin
* number within the interrupt groups are:
* 0: pins 0-3 (interrupt number 0-3)
* 1: pins 4-7 (interrupt number 4-7)
* 2: pins 8-11 (interrupt number 8-11)
* 3: pins 12-15 (interrupt number 12-15)
*
* @param[in] int_no Interrupt number to unregister and disable.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if int_no is invalid.
******************************************************************************/
sl_status_t sl_gpio_deconfigure_external_interrupt(int32_t int_no);
/***************************************************************************//**
* Enables one or more GPIO Interrupts.
*
* @param[in] int_mask Mask for GPIO Interrupt sources to enable.
*
* @return SL_STATUS_OK if there's no error.
******************************************************************************/
sl_status_t sl_gpio_enable_interrupts(uint32_t int_mask);
/***************************************************************************//**
* Disables one or more GPIO Interrupts.
*
* @param[in] int_mask Mask for GPIO Interrupt sources to disable.
*
* @return SL_STATUS_OK if there's no error.
******************************************************************************/
sl_status_t sl_gpio_disable_interrupts(uint32_t int_mask);
/***************************************************************************//**
* Configuration EM4WU pins as external level-sensitive interrupts.
*
* @details By default, this function performs callback registration, enables GPIO pin wake-up from EM4,
* sets the wake-up polarity, enables GPIO pin retention and enables the EM4 wake-up interrupt.
* It is recommended to use sl_gpio_deconfigure_wakeup_em4_interrupt()
* to unregister the callback and disable the em4 interrupt as well as GPIO pin wake-up from EM4.
* It is recommended to use sl_gpio_set_pin_em4_retention() to enable/disable the GPIO pin retention.
* see @ref sl_gpio_deconfigure_wakeup_em4_interrupt() and @ref sl_gpio_set_pin_em4_retention().
* If a valid EM4 wake-up interrupt number is provided, operation will proceed accordingly.
* Otherwise, a valid EM4 interrupt number will be generated based on provided EM4 configured
* port and pin and used for subsequent operations.
*
* @note If the user has a valid em4 interrupt number to provide as input, it can be used.
* If the user does not have an interrupt number, they can pass -1 (SL_GPIO_INTERRUPT_UNAVAILABLE)
* as value to variable em4_int_no.
* The em4_int_no parameter serves even as an output, a pointer to convey the em4 interrupt number
* for cases where user lacks an em4 interrupt number.
* @note There are specific ports and pins mapped to an existent EM4WU interrupt
* Each EM4WU signal is connected to a fixed pin and port.
* Based on chip, EM4 wake up interrupts configured port and pin might vary.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[in/out] em4_int_no Pointer to interrupt number to trigger.
* Pointer that serves as both an input and an output to return em4_int_no
* when the user lacks an em4_int_no.
* @param[in] polarity Determines the wakeup polarity.
* true = Active high level-sensitive interrupt.
* false = Active low level-sensitive interrupt.
* @param[in] gpio_callback A pointer to callback.
* @param[in] context A pointer to callback context.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if any of the port, pin parameters are invalid.
* SL_STATUS_NULL_POINTER if the int_no is passed as NULL.
* SL_STATUS_NOT_FOUND if there's no available interrupt number.
******************************************************************************/
sl_status_t sl_gpio_configure_wakeup_em4_interrupt(const sl_gpio_t *gpio,
int32_t *em4_int_no,
bool polarity,
sl_gpio_irq_callback_t gpio_callback,
void *context);
/***************************************************************************//**
* Utilize this function to deconfigure the EM4 GPIO pin interrupt.
* It serves to unregister a callback, disable/clear interrupt and clear em4 wakeup source.
*
* @details This function performs callback unregistration, clears and disables given em4
* interrupt and disables GPIO pin wake-up from EM4.
*
* @param[in] em4_int_no EM4 wakeup interrupt number.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if em4_int_no is invalid.
******************************************************************************/
sl_status_t sl_gpio_deconfigure_wakeup_em4_interrupt(int32_t em4_int_no);
/***************************************************************************//**
* Enable EM4 GPIO pin Wake-up bit.
* Sets the wakeup and polarity of the EM4 wakeup.
*
* @param[in] em4_int_mask Mask for setting desired EM4 wake up interrupt to enable.
* Mask contains the bitwise logic OR of which EM4 wake up interrupt to
* enable.
* @param[in] em4_polarity_mask Mask for setting the wake up polarity for the EM4 wake up interrupt.
* Mask contains the bitwise logic OR of EM4 wake-up interrupt polarity.
*
* @return SL_STATUS_OK if there's no error.
******************************************************************************/
sl_status_t sl_gpio_enable_pin_em4_wakeup(uint32_t em4_int_mask,
uint32_t em4_polarity_mask);
/***************************************************************************//**
* Disabled the GPIO wake up from EM4.
*
* @param[in] pinmask Mask for clearing desired EM4 wake up interrupt to disable.
* Mask contains the bitwise logic OR of which EM4 wake up interrupt to
* disable.
*
* @return SL_STATUS_OK if there's no error.
******************************************************************************/
sl_status_t sl_gpio_disable_pin_em4_wakeup(uint32_t em4_int_mask);
/***************************************************************************//**
* Enable/Disable GPIO pin retention of output enable, output value, pull enable, and pull direction in EM4.
*
* @param[in] enable true - enables EM4 pin retention.
* false - disables EM4 pin retention.
*
* @return SL_STATUS_OK if there's no error.
******************************************************************************/
sl_status_t sl_gpio_set_pin_em4_retention(bool enable);
/***************************************************************************//**
* Sets slewrate for selected port.
*
* @param[in] port The GPIO port to configure.
* @param[in] slewrate The slewrate to configure the GPIO port.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if port is invalid.
******************************************************************************/
sl_status_t sl_gpio_set_slew_rate(sl_gpio_port_t port,
uint8_t slewrate);
/***************************************************************************//**
* Gets slewrate for selected port.
*
* @param[in] port The GPIO port to get slewrate.
* @param[out] slewrate Pointer to store the slewrate of selected port.
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_INVALID_PARAMETER if port is invalid.
* SL_STATUS_NULL_POINTER if slewrate is passed as null.
******************************************************************************/
sl_status_t sl_gpio_get_slew_rate(sl_gpio_port_t port,
uint8_t *slewrate);
/***************************************************************************//**
* Locks the GPIO Configuration.
*
* @note This API locks the functionalities such as sl_gpio_set_pin_mode(),
* sl_gpio_configure_external_interrupt() and sl_gpio_configure_wakeup_em4_interrupt().
* After locking the GPIO configuration, use sl_gpio_unlock API to unlock
* the GPIO configuration to use mentioned functionalities.
*
* @return SL_STATUS_OK if there's no error.
******************************************************************************/
sl_status_t sl_gpio_lock(void);
/***************************************************************************//**
* Unlocks the GPIO Configuration.
*
* @note After locking the GPIO configuration it is recommended to unlock the GPIO configuration
* using sl_gpio_unlock(). You can determine if the GPIO configuration is locked or unlocked
* by using the sl_gpio_is_locked() function.
* Before using certain functions like sl_gpio_set_pin_mode(),
* sl_gpio_configure_external_interrupt(), and sl_gpio_configure_wakeup_em4_interrupt(),
* it's important to check if the GPIO configuration lock is unlocked.
*
* @return SL_STATUS_OK if there's no error.
******************************************************************************/
sl_status_t sl_gpio_unlock(void);
/***************************************************************************//**
* Gets current GPIO Lock status.
*
* @note This function helps check the current status of GPIO configuration.
*
* @param[out] state Pointer to current state of GPIO configuration (lock/unlock).
*
* @return SL_STATUS_OK if there's no error.
* SL_STATUS_NULL_POINTER if state is passed as null.
******************************************************************************/
sl_status_t sl_gpio_is_locked(bool *state);
/** @} (end addtogroup gpio driver) */
#ifdef __cplusplus
}
#endif
#endif /* SL_GPIO_H */

View File

@@ -0,0 +1,824 @@
/***************************************************************************//**
* @file
* @brief General Purpose IO (GPIO) driver API
*******************************************************************************
* # License
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include <stddef.h>
#include "sl_core.h"
#include "sl_common.h"
#include "sl_interrupt_manager.h"
#include "sl_clock_manager.h"
#include "sl_hal_gpio.h"
#include "sl_gpio.h"
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
/// Define for supporting gpiointerrupt porting
#define SL_GPIO_PORT_INTERRUPT (0xFF)
/// Pin direction validation.
#define SL_GPIO_DIRECTION_IS_VALID(direction) (direction <= SL_GPIO_PIN_DIRECTION_OUT)
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
typedef struct {
// Pin interrupt number in range 0 to 15.
uint32_t int_no;
// Pointer to callback function.
void *callback;
// Pointer to callback context.
void *context;
} sl_gpio_callback_desc_t;
typedef struct {
// An array of user callbacks for external interrupts.
// We have external interrupts configured from 0 to 15 bits.
sl_gpio_callback_desc_t callback_ext[SL_HAL_GPIO_INTERRUPT_MAX];
// An array of user callbacks for EM4 interrupts.
// We have EM4 interrupts configured from 16 to 31 bits.
sl_gpio_callback_desc_t callback_em4[SL_HAL_GPIO_INTERRUPT_MAX];
} sl_gpio_callbacks_t;
/*******************************************************************************
******************************** GLOBALS **********************************
******************************************************************************/
// Variable to manage and organize the callback functions for External and EM4 interrupts.
static sl_gpio_callbacks_t gpio_interrupts = { 0 };
/*******************************************************************************
****************************** LOCAL FUCTIONS *****************************
******************************************************************************/
static void sl_gpio_dispatch_interrupt(uint32_t iflags);
/***************************************************************************//**
* Driver GPIO Initialization.
******************************************************************************/
sl_status_t sl_gpio_init()
{
sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_GPIO);
if (sl_interrupt_manager_is_irq_disabled(GPIO_ODD_IRQn)) {
sl_interrupt_manager_clear_irq_pending(GPIO_ODD_IRQn);
sl_interrupt_manager_enable_irq(GPIO_ODD_IRQn);
}
if (sl_interrupt_manager_is_irq_disabled(GPIO_EVEN_IRQn)) {
sl_interrupt_manager_clear_irq_pending(GPIO_EVEN_IRQn);
sl_interrupt_manager_enable_irq(GPIO_EVEN_IRQn);
}
return SL_STATUS_OK;
}
/***************************************************************************//**
* Sets the pin direction for GPIO pin.
******************************************************************************/
sl_status_t sl_gpio_set_pin_direction(const sl_gpio_t *gpio,
sl_gpio_pin_direction_t pin_direction)
{
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin) || !SL_GPIO_DIRECTION_IS_VALID(pin_direction)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
if (sl_hal_gpio_get_lock_status() != 0) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_STATE;
}
CORE_ENTER_ATOMIC();
if (pin_direction == SL_GPIO_PIN_DIRECTION_OUT) {
sl_hal_gpio_set_pin_mode(gpio, SL_GPIO_MODE_PUSH_PULL, 1);
} else if (pin_direction == SL_GPIO_PIN_DIRECTION_IN) {
sl_hal_gpio_set_pin_mode(gpio, SL_GPIO_MODE_INPUT, 0);
}
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Sets the mode for GPIO pin and pin direction.
******************************************************************************/
sl_status_t sl_gpio_set_pin_mode(const sl_gpio_t *gpio,
sl_gpio_mode_t mode,
bool output_value)
{
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_MODE_IS_VALID(mode) || !SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
if (sl_hal_gpio_get_lock_status() != 0) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_STATE;
}
CORE_ENTER_ATOMIC();
sl_hal_gpio_set_pin_mode(gpio, mode, output_value);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Gets the current configuration selected pin on selected port.
******************************************************************************/
sl_status_t sl_gpio_get_pin_config(const sl_gpio_t *gpio,
sl_gpio_pin_config_t *pin_config)
{
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL || pin_config == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
pin_config->mode = sl_hal_gpio_get_pin_mode(gpio);
switch (pin_config->mode) {
case SL_GPIO_MODE_INPUT:
case SL_GPIO_MODE_INPUT_PULL:
case SL_GPIO_MODE_INPUT_PULL_FILTER:
pin_config->direction = SL_GPIO_PIN_DIRECTION_IN;
break;
case SL_GPIO_MODE_DISABLED:
case SL_GPIO_MODE_PUSH_PULL:
case SL_GPIO_MODE_PUSH_PULL_ALTERNATE:
case SL_GPIO_MODE_WIRED_OR:
case SL_GPIO_MODE_WIRED_OR_PULL_DOWN:
case SL_GPIO_MODE_WIRED_AND:
case SL_GPIO_MODE_WIRED_AND_FILTER:
case SL_GPIO_MODE_WIRED_AND_PULLUP:
case SL_GPIO_MODE_WIRED_AND_PULLUP_FILTER:
case SL_GPIO_MODE_WIRED_AND_ALTERNATE:
case SL_GPIO_MODE_WIRED_AND_ALTERNATE_FILTER:
case SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP:
case SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP_FILTER:
pin_config->direction = SL_GPIO_PIN_DIRECTION_OUT;
break;
default:
CORE_EXIT_ATOMIC();
EFM_ASSERT(false);
return SL_STATUS_INVALID_MODE;
}
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Sets the DOUT of selected pin on selected port.
******************************************************************************/
sl_status_t sl_gpio_set_pin(const sl_gpio_t *gpio)
{
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
sl_hal_gpio_set_pin(gpio);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Clears the DOUT of selected pin on selected port.
******************************************************************************/
sl_status_t sl_gpio_clear_pin(const sl_gpio_t *gpio)
{
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
sl_hal_gpio_clear_pin(gpio);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Toggles the DOUT of selected pin on selected port.
******************************************************************************/
sl_status_t sl_gpio_toggle_pin(const sl_gpio_t *gpio)
{
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
sl_hal_gpio_toggle_pin(gpio);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Gets the output state of selected pin on selected port.
******************************************************************************/
sl_status_t sl_gpio_get_pin_output(const sl_gpio_t *gpio,
bool *pin_value)
{
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL || pin_value == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
*pin_value = sl_hal_gpio_get_pin_output(gpio);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Gets the input state of selected pin on selected port.
******************************************************************************/
sl_status_t sl_gpio_get_pin_input(const sl_gpio_t *gpio,
bool *pin_value)
{
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL || pin_value == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
*pin_value = sl_hal_gpio_get_pin_input(gpio);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Sets the selected pin(s) on selected port.
******************************************************************************/
sl_status_t sl_gpio_set_port(sl_gpio_port_t port,
uint32_t pins)
{
CORE_DECLARE_IRQ_STATE;
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
sl_hal_gpio_set_port(port, pins);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Clears the selected pin on selected port.
******************************************************************************/
sl_status_t sl_gpio_clear_port(sl_gpio_port_t port,
uint32_t pins)
{
CORE_DECLARE_IRQ_STATE;
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
sl_hal_gpio_clear_port(port, pins);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Gets the output state of pins of selected port.
******************************************************************************/
sl_status_t sl_gpio_get_port_output(sl_gpio_port_t port,
uint32_t *port_value)
{
CORE_DECLARE_IRQ_STATE;
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
if (port_value == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
CORE_ENTER_ATOMIC();
*port_value = sl_hal_gpio_get_port_output(port);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Gets the input state of pins of selected port.
******************************************************************************/
sl_status_t sl_gpio_get_port_input(sl_gpio_port_t port,
uint32_t *port_value)
{
CORE_DECLARE_IRQ_STATE;
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
if (port_value == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
CORE_ENTER_ATOMIC();
*port_value = sl_hal_gpio_get_port_input(port);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Configuring the GPIO external pin interrupt.
* This API can be used to configure interrupt and to register the callback.
******************************************************************************/
sl_status_t sl_gpio_configure_external_interrupt(const sl_gpio_t *gpio,
int32_t *int_no,
sl_gpio_interrupt_flag_t flags,
sl_gpio_irq_callback_t gpio_callback,
void *context)
{
uint32_t enabled_interrupts;
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL || int_no == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin) && (gpio->port != SL_GPIO_PORT_INTERRUPT)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
if (!SL_GPIO_FLAG_IS_VALID(flags)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
if (gpio->port != SL_GPIO_PORT_INTERRUPT) {
*int_no = sl_hal_gpio_configure_external_interrupt(gpio, *int_no, flags);
}
if (*int_no == SL_GPIO_INTERRUPT_UNAVAILABLE && gpio->port == SL_GPIO_PORT_INTERRUPT) {
enabled_interrupts = sl_hal_gpio_get_enabled_interrupts();
*int_no = sl_hal_gpio_get_external_interrupt_number(gpio->pin, enabled_interrupts);
}
if (*int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) {
// Callback registration.
gpio_interrupts.callback_ext[*int_no].callback = (void *)gpio_callback;
gpio_interrupts.callback_ext[*int_no].context = context;
if (gpio->port != SL_GPIO_PORT_INTERRUPT) {
sl_hal_gpio_enable_interrupts(1 << *int_no);
}
} else {
CORE_EXIT_ATOMIC();
return SL_STATUS_NOT_FOUND;
}
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Deconfigures the GPIO external pin interrupt.
* This API can be used to deconfigure the interrupt and to unregister the callback.
******************************************************************************/
sl_status_t sl_gpio_deconfigure_external_interrupt(int32_t int_no)
{
CORE_DECLARE_IRQ_STATE;
if (!((int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) && (int_no <= SL_HAL_GPIO_INTERRUPT_MAX) && (int_no >= 0))) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
// Clear pending interrupt.
sl_hal_gpio_clear_interrupts(1 << int_no);
sl_hal_gpio_disable_interrupts(1 << int_no);
// Callback deregistration.
gpio_interrupts.callback_ext[int_no].callback = NULL;
gpio_interrupts.callback_ext[int_no].context = NULL;
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Enables one or more GPIO interrupts.
******************************************************************************/
sl_status_t sl_gpio_enable_interrupts(uint32_t flags)
{
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_ATOMIC();
sl_hal_gpio_enable_interrupts(flags);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Disables one or more GPIO interrupts.
******************************************************************************/
sl_status_t sl_gpio_disable_interrupts(uint32_t flags)
{
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_ATOMIC();
sl_hal_gpio_disable_interrupts(flags);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Configures the EM4WU pin as external level interrupts for waking up from EM mode.
* Registering/unregistering the callbacks and Configuring the EM4 interrupts to enable/disable
******************************************************************************/
sl_status_t sl_gpio_configure_wakeup_em4_interrupt(const sl_gpio_t *gpio,
int32_t *em4_int_no,
bool polarity,
sl_gpio_irq_callback_t gpio_callback,
void *context)
{
CORE_DECLARE_IRQ_STATE;
if (gpio == NULL || em4_int_no == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin) && (gpio->port != SL_GPIO_PORT_INTERRUPT)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
if (gpio->port != SL_GPIO_PORT_INTERRUPT) {
*em4_int_no = sl_hal_gpio_configure_wakeup_em4_external_interrupt(gpio, *em4_int_no, polarity);
}
if (*em4_int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) {
// Callback registration.
gpio_interrupts.callback_em4[*em4_int_no].callback = (void *)gpio_callback;
gpio_interrupts.callback_em4[*em4_int_no].context = context;
if (gpio->port != SL_GPIO_PORT_INTERRUPT) {
sl_hal_gpio_enable_interrupts(1 << (*em4_int_no + SL_HAL_GPIO_EM4WUEN_SHIFT));
}
} else {
CORE_EXIT_ATOMIC();
return SL_STATUS_NOT_FOUND;
}
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Deconfigures the EM4 GPIO pin interrupt.
* Unregisters a callback, disable/clear interrupt and clear em4 wakeup source
******************************************************************************/
sl_status_t sl_gpio_deconfigure_wakeup_em4_interrupt(int32_t em4_int_no)
{
CORE_DECLARE_IRQ_STATE;
if (!((em4_int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) && (em4_int_no <= SL_HAL_GPIO_INTERRUPT_MAX) && (em4_int_no >= 0))) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
// Clear any pending interrupt.
sl_hal_gpio_clear_interrupts(1 << (em4_int_no + SL_HAL_GPIO_EM4WUEN_SHIFT));
sl_hal_gpio_disable_pin_em4_wakeup(1 << (em4_int_no + SL_HAL_GPIO_EM4WUEN_SHIFT));
sl_hal_gpio_disable_interrupts(1 << (em4_int_no + SL_HAL_GPIO_EM4WUEN_SHIFT));
/* Callback deregistration */
gpio_interrupts.callback_em4[em4_int_no].callback = NULL;
gpio_interrupts.callback_em4[em4_int_no].context = NULL;
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Sets GPIO EM4 Wake up interrupt to Enable and EM4 Wake up interrupt polarity
******************************************************************************/
sl_status_t sl_gpio_enable_pin_em4_wakeup(uint32_t em4_int_mask,
uint32_t em4_polarity_mask)
{
uint32_t int_mask = 0;
uint32_t polarity_mask = 0;
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_ATOMIC();
// Enable EM4WU function and set polarity.
int_mask |= (em4_int_mask << _GPIO_EM4WUEN_EM4WUEN_SHIFT);
polarity_mask |= (em4_polarity_mask << _GPIO_EM4WUEN_EM4WUEN_SHIFT);
sl_hal_gpio_enable_pin_em4_wakeup(int_mask, polarity_mask);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Clears GPIO EM4 Wake up enable
******************************************************************************/
sl_status_t sl_gpio_disable_pin_em4_wakeup(uint32_t em4_int_mask)
{
uint32_t int_mask = 0;
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_ATOMIC();
// Disable EM4WU function.
int_mask |= (em4_int_mask << _GPIO_EM4WUEN_EM4WUEN_SHIFT);
sl_hal_gpio_disable_pin_em4_wakeup(int_mask);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Enable GPIO pin retention of output enable, output value, pull direction, pull enable in EM4
******************************************************************************/
sl_status_t sl_gpio_set_pin_em4_retention(bool enable)
{
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_ATOMIC();
sl_hal_gpio_set_pin_em4_retention(enable);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Sets slewrate for selected port.
******************************************************************************/
sl_status_t sl_gpio_set_slew_rate(sl_gpio_port_t port,
uint8_t slewrate)
{
CORE_DECLARE_IRQ_STATE;
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
CORE_ENTER_ATOMIC();
sl_hal_gpio_set_slew_rate(port, slewrate);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Gets slewrate for selected port.
******************************************************************************/
sl_status_t sl_gpio_get_slew_rate(sl_gpio_port_t port,
uint8_t *slewrate)
{
CORE_DECLARE_IRQ_STATE;
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
EFM_ASSERT(false);
return SL_STATUS_INVALID_PARAMETER;
}
if (slewrate == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
CORE_ENTER_ATOMIC();
*slewrate = sl_hal_gpio_get_slew_rate(port);
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Locks the GPIO Configuration
******************************************************************************/
sl_status_t sl_gpio_lock(void)
{
sl_hal_gpio_lock();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Unlocks the GPIO Configuration
******************************************************************************/
sl_status_t sl_gpio_unlock(void)
{
sl_hal_gpio_unlock();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Gets the GPIO State
******************************************************************************/
sl_status_t sl_gpio_is_locked(bool *state)
{
uint32_t status;
CORE_DECLARE_IRQ_STATE;
if (state == NULL) {
EFM_ASSERT(false);
return SL_STATUS_NULL_POINTER;
}
CORE_ENTER_ATOMIC();
status = sl_hal_gpio_get_lock_status();
if (status) {
// true - GPIO configuration registers are locked.
*state = true;
} else {
// false - GPIO configuration registers are unlocked.
*state = false;
}
CORE_EXIT_ATOMIC();
return SL_STATUS_OK;
}
/***************************************************************************//**
* Function calls users callback for registered pin interrupts.
*
* @details This function is called when GPIO interrupts are handled by the IRQHandlers.
* Function gets even or odd interrupt flags and calls user callback
* registered for that pin. Function iterates on flags starting from MSB.
*
* @param iflags Interrupt flags which shall be handled by the dispatcher.
******************************************************************************/
static void sl_gpio_dispatch_interrupt(uint32_t iflags)
{
uint32_t irq_idx;
sl_gpio_callback_desc_t *callback;
sl_gpio_irq_callback_t func;
// Check for flags set in IF register.
while (iflags != 0) {
irq_idx = SL_CTZ(iflags);
iflags &= ~(1UL << irq_idx);
if (irq_idx <= SL_HAL_GPIO_INTERRUPT_MAX) {
callback = &gpio_interrupts.callback_ext[irq_idx];
} else {
callback = &gpio_interrupts.callback_em4[irq_idx - SL_HAL_GPIO_EM4WUEN_SHIFT];
irq_idx = irq_idx - SL_HAL_GPIO_EM4WUEN_SHIFT;
}
// Call user callback.
if (callback->callback) {
func = (sl_gpio_irq_callback_t)(callback->callback);
func((uint8_t)irq_idx, callback->context);
}
}
}
/***************************************************************************//**
* GPIO EVEN interrupt handler. Interrupt handler clears all IF even flags and
* call the dispatcher passing the flags which triggered the interrupt.
******************************************************************************/
void GPIO_EVEN_IRQHandler(void)
{
uint32_t even_flags;
// Gets all enabled and pending even interrupts.
even_flags = sl_hal_gpio_get_enabled_pending_interrupts() & SL_HAL_GPIO_INT_IF_EVEN_MASK;
// Clears only even interrupts.
sl_hal_gpio_clear_interrupts(even_flags);
sl_gpio_dispatch_interrupt(even_flags);
}
/***************************************************************************//**
* @brief
* GPIO ODD interrupt handler. Interrupt handler clears all IF odd flags and
* call the dispatcher passing the flags which triggered the interrupt.
******************************************************************************/
void GPIO_ODD_IRQHandler(void)
{
uint32_t odd_flags;
// Gets all enabled and pending odd interrupts.
odd_flags = sl_hal_gpio_get_enabled_pending_interrupts() & SL_HAL_GPIO_INT_IF_ODD_MASK;
// Clears only odd interrupts.
sl_hal_gpio_clear_interrupts(odd_flags);
sl_gpio_dispatch_interrupt(odd_flags);
}

View File

@@ -0,0 +1,183 @@
/***************************************************************************//**
* @file
* @brief LED Driver
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_LED_H
#define SL_LED_H
#include <stdint.h>
#include "sl_status.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup led LED Driver
* @brief Generic LED Driver
* @{
******************************************************************************/
/*******************************************************************************
****************************** DEFINES ************************************
******************************************************************************/
#define SL_LED_CURRENT_STATE_OFF 0U ///< LED state off
#define SL_LED_CURRENT_STATE_ON 1U ///< LED state on
/*******************************************************************************
***************************** DATA TYPES **********************************
******************************************************************************/
typedef uint8_t sl_led_state_t; ///< LED state
/// A LED instance
typedef struct {
void *context; ///< The context for this LED instance
sl_status_t (*init)(void *context); ///< Member function to initialize LED instance
void (*turn_on)(void *context); ///< Member function to turn on LED
void (*turn_off)(void *context); ///< Member function to turn off LED
void (*toggle)(void *context); ///< Member function to toggle LED
sl_led_state_t (*get_state)(void *context); ///< Member function to retrieve LED state
} sl_led_t;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* Initialize the LED driver. Call this function before any other LED
* function. Initializes the selected LED GPIO, mode, and polarity.
*
* @param[in] led_handle Pointer to instance of sl_led_t to initialize
*
* @return Status Code:
* - SL_STATUS_OK
******************************************************************************/
sl_status_t sl_led_init(const sl_led_t *led_handle);
/***************************************************************************//**
* Turn on the LED.
*
* @param[in] led_handle Pointer to instance of sl_led_t to turn on
******************************************************************************/
void sl_led_turn_on(const sl_led_t *led_handle);
/***************************************************************************//**
* Turn off the LED.
*
* @param[in] led_handle Pointer to instance of sl_led_t to turn off
******************************************************************************/
void sl_led_turn_off(const sl_led_t *led_handle);
/***************************************************************************//**
* Toggle the LED. Turn it on if it is off, and off if it is on.
*
* @param[in] led_handle Pointer to instance of sl_led_t to toggle
******************************************************************************/
void sl_led_toggle(const sl_led_t *led_handle);
/***************************************************************************//**
* Get the current state of the LED.
*
* @param[in] led_handle Pointer to instance of sl_led_t to check
*
* @return sl_led_state_t Current state of LED. 1 for on, 0 for off
******************************************************************************/
sl_led_state_t sl_led_get_state(const sl_led_t *led_handle);
/** @} (end group led) */
// ******** THE REST OF THE FILE IS DOCUMENTATION ONLY !***********************
/// @addtogroup led LED Driver
/// @{
///
/// @details
///
///
/// @n @section leddrv_intro Introduction
///
/// The LED driver is a platfom level software module that manages the control of
/// various types of LEDs. There are currently two types of LEDs supported by the
/// LED driver:
///
/// @li @ref simple_led
/// @li @ref simple_rgbw_pwm_led
///
/// The common LED functions are called through the generic LED driver, while other
/// functions specific to a certain type of LED are called directly through their own
/// driver.
///
/// @n @section leddrv_config Configuration
///
/// All LED instances are configured using an @ref sl_led_t struct along with a
/// type-specific context struct, and sometimes additional structs. For `sl_led_XXX`
/// functions, the `sl_led_t *led_handle` is used, while for `sl_simple_led_XXX`
/// functions, the `sl_simple_led_context_t *context` is used.
///
/// These structs are automatically generated when an LED is set up using Simplicity
/// Studio's wizard. Specific configuration setups for the various LED types are
/// described in the following sections.
///
/// - [Simple LED Configuration](/gecko-platform/<docspace-docleaf-version>/platform-driver/simple-led#simple-led-configuration)
/// - [RGBW PWM LED Configuration](/gecko-platform/<docspace-docleaf-version>/platform-driver/simple-rgb-pwm-led#rgb-pwm-led-configuration)
///
/// @n @section leddrv_usage Usage
///
/// Once the LED structs are defined, the common LED functions can be called being passed an instance
/// of sl_led_t, which will be redirected to calling the type specific version of that function. The
/// common functions include the following:
///
/// @li @ref sl_led_init
/// @li @ref sl_led_turn_on
/// @li @ref sl_led_turn_off
/// @li @ref sl_led_toggle
/// @li @ref sl_led_get_state
///
/// These functions allow for initializing the LED, turning it on and off, toggling it, and retrieving
/// its current state (on/off). Other functions specific to certain types of LEDs are called through
/// their respective APIs. The usages of the different types of LEDs are described in detail in the
/// following sections:
///
/// @li @ref simple_led_usage
/// @li @ref rgbw_led_usage
///
/// Ensure that the appropriate context type is used in the function calls:
/// - Use `sl_led_t *led_handle` for `sl_led_XXX` functions.
/// - Use `sl_simple_led_context_t *context` for `sl_simple_led_XXX` functions.
///
/// These distinctions are handled by the Simplicity Studio auto-generated code.
///
/// @} end group led ********************************************************/
#ifdef __cplusplus
}
#endif
#endif // SL_LED_H

View File

@@ -0,0 +1,226 @@
/***************************************************************************//**
* @file
* @brief Simple LED Driver
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SIMPLE_LED_H
#define SL_SIMPLE_LED_H
#include "sl_led.h"
#include "sl_gpio.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup led
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup simple_led Simple LED Driver
* @brief Simple LED Driver can be used to execute basic LED functionalities
* such as on, off, toggle, or retrive the on/off status on Silicon Labs
* devices. Subsequent sections provide more insight into this module.
* @{
******************************************************************************/
/*******************************************************************************
****************************** DEFINES ************************************
******************************************************************************/
#define SL_SIMPLE_LED_POLARITY_ACTIVE_LOW 0U ///< LED Active polarity Low
#define SL_SIMPLE_LED_POLARITY_ACTIVE_HIGH 1U ///< LED Active polarity High
/*******************************************************************************
***************************** DATA TYPES **********************************
******************************************************************************/
typedef uint8_t sl_led_polarity_t; ///< LED GPIO polarities (active high/low)
/// A Simple LED instance
typedef struct {
sl_gpio_port_t port; ///< LED port
uint8_t pin; ///< LED pin
sl_led_polarity_t polarity; ///< Initial state of LED
} sl_simple_led_context_t;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* Initialize the simple LED driver.
*
* @param[in] led_handle Pointer to simple-led specific data:
* - sl_simple_led_context_t
*
* @return Status Code:
* - SL_STATUS_OK
******************************************************************************/
sl_status_t sl_simple_led_init(void *led_handle);
/***************************************************************************//**
* Turn on a simple LED.
*
* @param[in] led_handle Pointer to simple-led specific data:
* - sl_simple_led_context_t
*
******************************************************************************/
void sl_simple_led_turn_on(void *led_handle);
/***************************************************************************//**
* Turn off a simple LED.
*
* @param[in] led_handle Pointer to simple-led specific data:
* - sl_simple_led_context_t
*
******************************************************************************/
void sl_simple_led_turn_off(void *led_handle);
/***************************************************************************//**
* Toggle a simple LED.
*
* @param[in] led_handle Pointer to simple-led specific data:
* - sl_simple_led_context_t
*
******************************************************************************/
void sl_simple_led_toggle(void *led_handle);
/***************************************************************************//**
* Get the current state of the simple LED.
*
* @param[in] led_handle Pointer to simple-led specific data:
* - sl_simple_led_context_t
*
* @return sl_led_state_t Current state of simple LED. 1 for on, 0 for off
******************************************************************************/
sl_led_state_t sl_simple_led_get_state(void *led_handle);
/** @} (end group simple_led) */
/** @} (end group led) */
// ******** THE REST OF THE FILE IS DOCUMENTATION ONLY !***********************
/// @addtogroup simple_led Simple LED Driver
/// @{
///
/// @details
///
///
/// @n @section simple_led_intro Introduction
///
/// The Simple LED driver is a module of the LED driver that provides the functionality
/// to control simple on/off LEDs.
///
/// @n @section simple_led_config Simple LED Configuration
///
/// Simple LEDs use the @ref sl_led_t struct and their @ref sl_simple_led_context_t
/// struct. These are automatically generated into the following files, as well as
/// instance specific headers with macro definitions in them. The samples below
/// are for a single instance called "inst0".
///
/// @code{.c}
///// sl_simple_led_instances.c
///
///#include "sl_simple_led.h"
///#include "sl_gpio.h"
///#include "sl_simple_led_inst0_config.h"
///
///sl_simple_led_context_t simple_inst0_context = {
/// .port = SL_SIMPLE_LED_INST0_PORT,
/// .pin = SL_SIMPLE_LED_INST0_PIN,
/// .polarity = SL_SIMPLE_LED_INST0_POLARITY,
///};
///
///const sl_led_t sl_led_inst0 = {
/// .context = &simple_inst0_context,
/// .init = sl_simple_led_init,
/// .turn_on = sl_simple_led_turn_on,
/// .turn_off = sl_simple_led_turn_off,
/// .toggle = sl_simple_led_toggle,
/// .get_state = sl_simple_led_get_state,
///};
///
///void sl_simple_led_init_instances(void)
///{
/// sl_led_init(&sl_led_inst0);
///}
/// @endcode
///
/// @note The sl_simple_led_instances.c file is shown with only one instance, but if more
/// were in use they would all appear in this .c file.
///
/// @code{.c}
///// sl_simple_led_instances.h
///
///#ifndef SL_SIMPLE_LED_INSTANCES_H
///#define SL_SIMPLE_LED_INSTANCES_H
///
///#include "sl_simple_led.h"
///
///extern const sl_led_t sl_led_inst0;
///
///void sl_simple_led_init_instances(void);
///
///#endif // SL_SIMPLE_LED_INIT_H
/// @endcode
///
/// @note The sl_simple_led_instances.h file is shown with only one instance, but if more
/// were in use they would all appear in this .h file.
///
/// @n @section simple_led_usage Simple LED Usage
///
/// The simple LED driver is for LEDs with basic on off functionality, and there
/// are no additional functions beyond those in the common driver. The LEDs can be
/// turned on and off, toggled, and their on/off state can be retrieved. The following
/// code shows how to control these LEDs. An LED should always be initialized before
/// calling any other functions with it.
///
/// @code{.c}
///// initialize simple LED
///sl_simple_led_init(&simple_led_inst0);
///
///// turn on simple LED, turn off simple LED, and toggle the simple LED
///sl_simple_led_turn_on(&simple_led_inst0);
///sl_simple_led_turn_off(&simple_led_inst0);
///sl_simple_led_toggle(&simple_led_inst0);
///
///// get the state of the simple LED
///sl_led_state_t state = sl_simple_led_get_state(&simple_led_instance0);
/// @endcode
///
/// @} end group simple_led ********************************************************/
#ifdef __cplusplus
}
#endif
#endif // SL_SIMPLE_LED_H

View File

@@ -0,0 +1,56 @@
/***************************************************************************//**
* @file
* @brief LED Driver
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_led.h"
sl_status_t sl_led_init(const sl_led_t *led_handle)
{
return led_handle->init(led_handle->context);
}
void sl_led_turn_on(const sl_led_t *led_handle)
{
led_handle->turn_on(led_handle->context);
}
void sl_led_turn_off(const sl_led_t *led_handle)
{
led_handle->turn_off(led_handle->context);
}
void sl_led_toggle(const sl_led_t *led_handle)
{
led_handle->toggle(led_handle->context);
}
sl_led_state_t sl_led_get_state(const sl_led_t *led_handle)
{
return led_handle->get_state(led_handle->context);
}

View File

@@ -0,0 +1,104 @@
/***************************************************************************//**
* @file
* @brief Simple LED Driver
*******************************************************************************
* # License
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_simple_led.h"
#include "sl_gpio.h"
#include "sl_clock_manager.h"
sl_status_t sl_simple_led_init(void *context)
{
sl_simple_led_context_t *led = context;
sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_GPIO);
sl_gpio_t gpio;
gpio.port = led->port;
gpio.pin = led->pin;
sl_gpio_set_pin_mode(&gpio,
SL_GPIO_MODE_PUSH_PULL,
!led->polarity);
return SL_STATUS_OK;
}
void sl_simple_led_turn_on(void *context)
{
sl_simple_led_context_t *led = context;
sl_gpio_t gpio;
gpio.port = led->port;
gpio.pin = led->pin;
if (led->polarity == SL_SIMPLE_LED_POLARITY_ACTIVE_LOW) {
sl_gpio_clear_pin(&gpio);
} else {
sl_gpio_set_pin(&gpio);
}
}
void sl_simple_led_turn_off(void *context)
{
sl_simple_led_context_t *led = context;
sl_gpio_t gpio;
gpio.port = led->port;
gpio.pin = led->pin;
if (led->polarity == SL_SIMPLE_LED_POLARITY_ACTIVE_LOW) {
sl_gpio_set_pin(&gpio);
} else {
sl_gpio_clear_pin(&gpio);
}
}
void sl_simple_led_toggle(void *context)
{
sl_simple_led_context_t *led = context;
sl_gpio_t gpio;
gpio.port = led->port;
gpio.pin = led->pin;
sl_gpio_toggle_pin(&gpio);
}
sl_led_state_t sl_simple_led_get_state(void *context)
{
sl_simple_led_context_t *led = context;
sl_led_state_t value;
sl_gpio_t gpio;
bool pin_value;
gpio.port = led->port;
gpio.pin = led->pin;
sl_gpio_get_pin_output(&gpio, &pin_value);
value = (sl_led_state_t)pin_value;
if (led->polarity == SL_SIMPLE_LED_POLARITY_ACTIVE_LOW) {
return !value;
} else {
return value;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
/***************************************************************************//**
* @file
* @brief Emlib peripheral API "assert" implementation.
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_ASSERT_H
#define EM_ASSERT_H
#include "sl_assert.h"
#endif /* EM_ASSERT_H */

View File

@@ -0,0 +1,473 @@
/***************************************************************************//**
* @file
* @brief Backup Real Time Counter (BURTC) peripheral API
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_BURTC_H
#define EM_BURTC_H
#include "em_device.h"
#if defined(BURTC_PRESENT)
#include <stdbool.h>
#include "sl_assert.h"
#include "em_bus.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup burtc
* @{
******************************************************************************/
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
/** BURTC clock divisors. These values are valid for the BURTC prescaler. */
#define burtcClkDiv_1 1 /**< Divide clock by 1. */
#define burtcClkDiv_2 2 /**< Divide clock by 2. */
#define burtcClkDiv_4 4 /**< Divide clock by 4. */
#define burtcClkDiv_8 8 /**< Divide clock by 8. */
#define burtcClkDiv_16 16 /**< Divide clock by 16. */
#define burtcClkDiv_32 32 /**< Divide clock by 32. */
#define burtcClkDiv_64 64 /**< Divide clock by 64. */
#define burtcClkDiv_128 128 /**< Divide clock by 128. */
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
#if defined(_SILICON_LABS_32B_SERIES_0)
/** BURTC clock selection. */
typedef enum {
/** Ultra low frequency (1 kHz) clock. */
burtcClkSelULFRCO = BURTC_CTRL_CLKSEL_ULFRCO,
/** Low frequency RC oscillator. */
burtcClkSelLFRCO = BURTC_CTRL_CLKSEL_LFRCO,
/** Low frequency crystal oscillator. */
burtcClkSelLFXO = BURTC_CTRL_CLKSEL_LFXO
} BURTC_ClkSel_TypeDef;
/** BURTC mode of operation. */
typedef enum {
/** Disable BURTC */
burtcModeDisable = BURTC_CTRL_MODE_DISABLE,
/** Enable and start BURTC counter in EM0 to EM2. */
burtcModeEM2 = BURTC_CTRL_MODE_EM2EN,
/** Enable and start BURTC counter in EM0 to EM3. */
burtcModeEM3 = BURTC_CTRL_MODE_EM3EN,
/** Enable and start BURTC counter in EM0 to EM4. */
burtcModeEM4 = BURTC_CTRL_MODE_EM4EN,
} BURTC_Mode_TypeDef;
/** BURTC low power mode. */
typedef enum {
/** Low Power Mode is disabled. */
burtcLPDisable = BURTC_LPMODE_LPMODE_DISABLE,
/** Low Power Mode is always enabled. */
burtcLPEnable = BURTC_LPMODE_LPMODE_ENABLE,
/** Low Power Mode when system enters backup mode. */
burtcLPBU = BURTC_LPMODE_LPMODE_BUEN
} BURTC_LP_TypeDef;
#endif
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
#if defined(_SILICON_LABS_32B_SERIES_0)
/** BURTC initialization structure for Series 0 devices. */
typedef struct {
bool enable; /**< Enable BURTC after initialization (starts counter). */
BURTC_Mode_TypeDef mode; /**< Configure energy mode operation. */
bool debugRun; /**< If true, counter will keep running under debug halt. */
BURTC_ClkSel_TypeDef clkSel; /**< Select clock source. */
uint32_t clkDiv; /**< Clock divider; for ULFRCO 1Khz or 2kHz operation. */
uint32_t lowPowerComp; /**< Number of least significant clock bits to ignore in low power mode. */
bool timeStamp; /**< Enable time stamp on entering backup power domain. */
bool compare0Top; /**< Set if Compare Value 0 is also top value (counter restart). */
BURTC_LP_TypeDef lowPowerMode; /**< Low power operation mode, requires LFXO or LFRCO. */
} BURTC_Init_TypeDef;
/** Default configuration for BURTC initialization structure. */
#define BURTC_INIT_DEFAULT \
{ \
true, \
burtcModeEM2, \
false, \
burtcClkSelULFRCO, \
burtcClkDiv_1, \
0, \
true, \
false, \
burtcLPDisable, \
}
#elif defined(_SILICON_LABS_32B_SERIES_2)
/** BURTC initialization structure for Series 2 devices. */
typedef struct {
bool start; /**< Start BURTC after initialization */
bool debugRun; /**< If true, counter will keep running under debug halt */
uint32_t clkDiv; /**< Clock divider. Supported range is 1-32768 */
bool compare0Top; /**< Set if Compare Value 0 is also top value (counter restart) */
bool em4comp; /**< Enable EM4 wakeup on compare match. */
bool em4overflow; /**< Enable EM4 wakeup on counter overflow. */
} BURTC_Init_TypeDef;
/** Default configuration for BURTC init structure */
#define BURTC_INIT_DEFAULT \
{ \
true, \
false, \
1, \
0, \
false, \
false, \
}
#endif
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Clear one or more pending BURTC interrupts.
*
* @param[in] flags
* BURTC interrupt sources to clear. Use a set of interrupt flags OR-ed
* together to clear multiple interrupt sources for the BURTC module
* (BURTC_IFS_nnn).
******************************************************************************/
__STATIC_INLINE void BURTC_IntClear(uint32_t flags)
{
#if defined(BURTC_HAS_SET_CLEAR)
BURTC->IF_CLR = flags;
#else
BURTC->IFC = flags;
#endif
}
/***************************************************************************//**
* @brief
* Disable one or more BURTC interrupts.
*
* @param[in] flags
* BURTC interrupt sources to disable. Use a set of interrupt flags OR-ed
* together to disable multiple interrupt sources for the BURTC module
* (BURTC_IFS_nnn).
******************************************************************************/
__STATIC_INLINE void BURTC_IntDisable(uint32_t flags)
{
#if defined(BURTC_HAS_SET_CLEAR)
BURTC->IEN_CLR = flags;
#else
BURTC->IEN &= ~(flags);
#endif
}
/***************************************************************************//**
* @brief
* Enable one or more BURTC interrupts.
*
* @note
* Depending on use, a pending interrupt may already be set prior to
* enabling the interrupt. Consider using BURTC_IntClear() prior to enabling
* if a pending interrupt should be ignored.
*
* @param[in] flags
* BURTC interrupt sources to enable. Use a set of interrupt flags OR-ed
* together to set multiple interrupt sources for the BURTC module
* (BURTC_IFS_nnn).
******************************************************************************/
__STATIC_INLINE void BURTC_IntEnable(uint32_t flags)
{
#if defined(BURTC_HAS_SET_CLEAR)
BURTC->IEN_SET = flags;
#else
BURTC->IEN |= flags;
#endif
}
/***************************************************************************//**
* @brief
* Get pending BURTC interrupt flags.
*
* @note
* This function does not clear the event bits.
*
* @return
* Pending BURTC interrupt sources. Returns a set of interrupt flags OR-ed
* together for multiple interrupt sources in the BURTC module (BURTC_IFS_nnn).
******************************************************************************/
__STATIC_INLINE uint32_t BURTC_IntGet(void)
{
return BURTC->IF;
}
/***************************************************************************//**
* @brief
* Get enabled and pending BURTC interrupt flags.
*
* @note
* The event bits are not cleared by the use of this function.
*
* @return
* Pending BURTC interrupt sources that is also enabled. Returns a set of
* interrupt flags OR-ed together for multiple interrupt sources in the
* BURTC module (BURTC_IFS_nnn).
******************************************************************************/
__STATIC_INLINE uint32_t BURTC_IntGetEnabled(void)
{
uint32_t tmp;
/* Get enabled interrupts */
tmp = BURTC->IEN;
/* Return set interrupts */
return BURTC->IF & tmp;
}
/***************************************************************************//**
* @brief
* Set one or more pending BURTC interrupts from SW.
*
* @param[in] flags
* BURTC interrupt sources to set to pending. Use a set of interrupt flags
* OR-ed together to set multiple interrupt sources for the BURTC module
* (BURTC_IFS_nnn).
******************************************************************************/
__STATIC_INLINE void BURTC_IntSet(uint32_t flags)
{
#if defined(BURTC_HAS_SET_CLEAR)
BURTC->IF_SET = flags;
#else
BURTC->IFS = flags;
#endif
}
/***************************************************************************//**
* @brief
* Status of BURTC RAM, timestamp and LP Mode
*
* @return A mask logically OR-ed status bits
******************************************************************************/
__STATIC_INLINE uint32_t BURTC_Status(void)
{
return BURTC->STATUS;
}
#if defined(BURTC_CMD_CLRSTATUS)
/***************************************************************************//**
* @brief
* Clear and reset BURTC status register
******************************************************************************/
__STATIC_INLINE void BURTC_StatusClear(void)
{
BURTC->CMD = BURTC_CMD_CLRSTATUS;
}
#endif
/***************************************************************************//**
* @brief
* Wait for the BURTC to complete all synchronization of register changes
* and commands.
******************************************************************************/
__STATIC_INLINE void BURTC_SyncWait(void)
{
#if defined(_SILICON_LABS_32B_SERIES_2)
while ((BURTC->EN != 0U) && (BURTC->SYNCBUSY != 0U)) {
/* Wait for previous synchronization to finish */
}
#else
while (BURTC->SYNCBUSY != 0U) {
/* Wait for previous synchronization to finish */
}
#endif
}
#if defined(_SILICON_LABS_32B_SERIES_2)
/***************************************************************************//**
* @brief
* Start BURTC counter.
*
* This function will send a start command to the BURTC peripheral. The BURTC
* peripheral will use some LF clock ticks before the command is executed.
* The @ref BURTC_SyncWait() function can be used to wait for the start command
* to be executed.
*
* @note
* This function requires the BURTC to be enabled.
******************************************************************************/
__STATIC_INLINE void BURTC_Start(void)
{
BURTC_SyncWait();
BURTC->CMD = BURTC_CMD_START;
}
/***************************************************************************//**
* @brief
* Stop the BURTC counter.
*
* This function will send a stop command to the BURTC peripheral. The BURTC
* peripheral will use some LF clock ticks before the command is executed.
* The @ref BURTC_SyncWait() function can be used to wait for the stop command
* to be executed.
*
* @note
* This function requires the BURTC to be enabled.
******************************************************************************/
__STATIC_INLINE void BURTC_Stop(void)
{
BURTC_SyncWait();
BURTC->CMD = BURTC_CMD_STOP;
}
#endif
/***************************************************************************//**
* @brief Get BURTC counter.
*
* @return
* BURTC counter value
******************************************************************************/
__STATIC_INLINE uint32_t BURTC_CounterGet(void)
{
return BURTC->CNT;
}
#if defined(_SILICON_LABS_32B_SERIES_0)
/***************************************************************************//**
* @brief Get BURTC timestamp for entering BU.
*
* @return
* BURTC Time Stamp value
******************************************************************************/
__STATIC_INLINE uint32_t BURTC_TimestampGet(void)
{
return BURTC->TIMESTAMP;
}
/***************************************************************************//**
* @brief Freeze register updates until enabled.
* @param[in] enable If true, registers are not updated until enabled again.
******************************************************************************/
__STATIC_INLINE void BURTC_FreezeEnable(bool enable)
{
BUS_RegBitWrite(&BURTC->FREEZE, _BURTC_FREEZE_REGFREEZE_SHIFT, enable);
}
/***************************************************************************//**
* @brief Shut down power to retention register bank.
* @param[in] enable
* If true, shuts off power to retention registers.
* @note
* When power retention is disabled, it can't be enabled again (until
* reset).
******************************************************************************/
__STATIC_INLINE void BURTC_Powerdown(bool enable)
{
BUS_RegBitWrite(&BURTC->POWERDOWN, _BURTC_POWERDOWN_RAM_SHIFT, enable);
}
/***************************************************************************//**
* @brief
* Set a value in one of the retention registers.
*
* @param[in] num
* Register to set
* @param[in] data
* Value to put into register
******************************************************************************/
__STATIC_INLINE void BURTC_RetRegSet(uint32_t num, uint32_t data)
{
EFM_ASSERT(num <= 127);
BURTC->RET[num].REG = data;
}
/***************************************************************************//**
* @brief
* Read a value from one of the retention registers.
*
* @param[in] num
* Retention Register to read
*
* @return
* Value of the retention register
******************************************************************************/
__STATIC_INLINE uint32_t BURTC_RetRegGet(uint32_t num)
{
EFM_ASSERT(num <= 127);
return BURTC->RET[num].REG;
}
#endif
/***************************************************************************//**
* @brief
* Lock BURTC registers, which will protect from writing new config settings.
******************************************************************************/
__STATIC_INLINE void BURTC_Lock(void)
{
BURTC->LOCK = 0x0;
}
/***************************************************************************//**
* @brief
* Unlock BURTC registers, which will enable write access to change configuration.
******************************************************************************/
__STATIC_INLINE void BURTC_Unlock(void)
{
BURTC->LOCK = BURTC_LOCK_LOCKKEY_UNLOCK;
}
void BURTC_Reset(void);
void BURTC_Init(const BURTC_Init_TypeDef *burtcInit);
void BURTC_Enable(bool enable);
void BURTC_CounterReset(void);
void BURTC_CompareSet(unsigned int comp, uint32_t value);
uint32_t BURTC_CompareGet(unsigned int comp);
#if defined(_BURTC_CTRL_MASK)
uint32_t BURTC_ClockFreqGet(void);
#endif
/** @} (end addtogroup burtc) */
#ifdef __cplusplus
}
#endif
#endif /* BURTC_PRESENT */
#endif /* EM_BURTC_H */

View File

@@ -0,0 +1,350 @@
/***************************************************************************//**
* @file
* @brief RAM and peripheral bit-field set and clear API
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_BUS_H
#define EM_BUS_H
#include "sl_assert.h"
#include "sl_core.h"
#include "em_device.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup bus BUS - Bitfield Read/Write
* @brief BUS register and RAM bit/field read/write API
* @details
* API to perform bit-band and field set/clear access to RAM and peripherals.
* @{
******************************************************************************/
/***************************************************************************//**
* @brief
* Perform a single-bit write operation on a 32-bit word in RAM.
*
* @details
* This function uses Cortex-M bit-banding hardware to perform an atomic
* read-modify-write operation on a single bit write on a 32-bit word in RAM.
* See the reference manual for more details about bit-banding.
*
* @note
* This function is atomic on Cortex-M cores with bit-banding support. Bit-
* banding is a multi cycle read-modify-write bus operation. RAM bit-banding is
* performed using the memory alias region at BITBAND_RAM_BASE.
*
* @param[in] addr An ddress of a 32-bit word in RAM.
*
* @param[in] bit A bit position to write, 0-31.
*
* @param[in] val A value to set bit to, 0 or 1.
******************************************************************************/
__STATIC_INLINE void BUS_RamBitWrite(volatile uint32_t *addr,
unsigned int bit,
unsigned int val)
{
#if defined(BITBAND_RAM_BASE)
uint32_t aliasAddr =
BITBAND_RAM_BASE + (((uint32_t)addr - SRAM_BASE) * (uint32_t) 32) + (bit * (uint32_t) 4);
*(volatile uint32_t *)aliasAddr = (uint32_t)val;
#else
uint32_t tmp = *addr;
/* Make sure val is not more than 1 because only one bit needs to be set. */
*addr = (tmp & ~(1UL << bit)) | ((val & 1UL) << bit);
#endif
}
/***************************************************************************//**
* @brief
* Perform a single-bit read operation on a 32-bit word in RAM.
*
* @details
* This function uses Cortex-M bit-banding hardware to perform an atomic
* read operation on a single register bit. See the
* reference manual for more details about bit-banding.
*
* @note
* This function is atomic on Cortex-M cores with bit-banding support.
* RAM bit-banding is performed using the memory alias region
* at BITBAND_RAM_BASE.
*
* @param[in] addr RAM address.
*
* @param[in] bit A bit position to read, 0-31.
*
* @return
* The requested bit shifted to bit position 0 in the return value.
******************************************************************************/
__STATIC_INLINE unsigned int BUS_RamBitRead(volatile const uint32_t *addr,
unsigned int bit)
{
#if defined(BITBAND_RAM_BASE)
uint32_t aliasAddr =
BITBAND_RAM_BASE + (((uint32_t)addr - SRAM_BASE) * (uint32_t) 32) + (bit * (uint32_t) 4);
return *(volatile uint32_t *)aliasAddr;
#else
return ((*addr) >> bit) & 1UL;
#endif
}
/***************************************************************************//**
* @brief
* Perform a single-bit write operation on a peripheral register.
*
* @details
* This function uses Cortex-M bit-banding hardware to perform an atomic
* read-modify-write operation on a single register bit. See the
* reference manual for more details about bit-banding.
*
* @note
* This function is atomic on Cortex-M cores with bit-banding support. Bit-
* banding is a multi cycle read-modify-write bus operation. Peripheral register
* bit-banding is performed using the memory alias region at BITBAND_PER_BASE.
*
* @param[in] addr A peripheral register address.
*
* @param[in] bit A bit position to write, 0-31.
*
* @param[in] val A value to set bit to, 0 or 1.
******************************************************************************/
__STATIC_INLINE void BUS_RegBitWrite(volatile uint32_t *addr,
unsigned int bit,
unsigned int val)
{
EFM_ASSERT(bit < 32U);
#if defined(PER_REG_BLOCK_SET_OFFSET) && defined(PER_REG_BLOCK_CLR_OFFSET)
uint32_t aliasAddr;
if (val != 0U) {
aliasAddr = (uint32_t)addr + PER_REG_BLOCK_SET_OFFSET;
} else {
aliasAddr = (uint32_t)addr + PER_REG_BLOCK_CLR_OFFSET;
}
*(volatile uint32_t *)aliasAddr = 1UL << bit;
#elif defined(BITBAND_PER_BASE)
uint32_t aliasAddr =
BITBAND_PER_BASE + (((uint32_t)addr - PER_MEM_BASE) * (uint32_t) 32) + (bit * (uint32_t) 4);
*(volatile uint32_t *)aliasAddr = (uint32_t)val;
#else
uint32_t tmp = *addr;
/* Make sure val is not more than 1 because only one bit needs to be set. */
*addr = (tmp & ~(1 << bit)) | ((val & 1) << bit);
#endif
}
/***************************************************************************//**
* @brief
* Perform a single-bit read operation on a peripheral register.
*
* @details
* This function uses Cortex-M bit-banding hardware to perform an atomic
* read operation on a single register bit. See the
* reference manual for more details about bit-banding.
*
* @note
* This function is atomic on Cortex-M cores with bit-banding support.
* Peripheral register bit-banding is performed using the memory alias
* region at BITBAND_PER_BASE.
*
* @param[in] addr A peripheral register address.
*
* @param[in] bit A bit position to read, 0-31.
*
* @return
* The requested bit shifted to bit position 0 in the return value.
******************************************************************************/
__STATIC_INLINE unsigned int BUS_RegBitRead(volatile const uint32_t *addr,
unsigned int bit)
{
#if defined(BITBAND_PER_BASE)
uint32_t aliasAddr =
BITBAND_PER_BASE + (((uint32_t)addr - PER_MEM_BASE) * (uint32_t)32) + (bit * (uint32_t) 4);
return *(volatile uint32_t *)aliasAddr;
#else
return ((*addr) >> bit) & 1UL;
#endif
}
/***************************************************************************//**
* @brief
* Perform a masked set operation on a peripheral register address.
*
* @details
* A peripheral register masked set provides a single-cycle and atomic set
* operation of a bit-mask in a peripheral register. All 1s in the mask are
* set to 1 in the register. All 0s in the mask are not changed in the
* register.
* RAMs and special peripherals are not supported. See the
* reference manual for more details about the peripheral register field set.
*
* @note
* This function is single-cycle and atomic on cores with peripheral bit set
* and clear support. It uses the memory alias region at PER_BITSET_MEM_BASE.
*
* @param[in] addr A peripheral register address.
*
* @param[in] mask A mask to set.
******************************************************************************/
__STATIC_INLINE void BUS_RegMaskedSet(volatile uint32_t *addr,
uint32_t mask)
{
#if defined(PER_REG_BLOCK_SET_OFFSET)
uint32_t aliasAddr = (uint32_t)addr + PER_REG_BLOCK_SET_OFFSET;
*(volatile uint32_t *)aliasAddr = mask;
#elif defined(PER_BITSET_MEM_BASE)
uint32_t aliasAddr = PER_BITSET_MEM_BASE + ((uint32_t)addr - PER_MEM_BASE);
*(volatile uint32_t *)aliasAddr = mask;
#else
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
*addr |= mask;
CORE_EXIT_CRITICAL();
#endif
}
/***************************************************************************//**
* @brief
* Perform a masked clear operation on the peripheral register address.
*
* @details
* A peripheral register masked clear provides a single-cycle and atomic clear
* operation of a bit-mask in a peripheral register. All 1s in the mask are
* set to 0 in the register.
* All 0s in the mask are not changed in the register.
* RAMs and special peripherals are not supported. See the
* reference manual for more details about the peripheral register field clear.
*
* @note
* This function is single-cycle and atomic on cores with peripheral bit set
* and clear support. It uses the memory alias region at PER_BITCLR_MEM_BASE.
*
* @param[in] addr A peripheral register address.
*
* @param[in] mask A mask to clear.
******************************************************************************/
__STATIC_INLINE void BUS_RegMaskedClear(volatile uint32_t *addr,
uint32_t mask)
{
#if defined(PER_REG_BLOCK_CLR_OFFSET)
uint32_t aliasAddr = (uint32_t)addr + PER_REG_BLOCK_CLR_OFFSET;
*(volatile uint32_t *)aliasAddr = mask;
#elif defined(PER_BITCLR_MEM_BASE)
uint32_t aliasAddr = PER_BITCLR_MEM_BASE + ((uint32_t)addr - PER_MEM_BASE);
*(volatile uint32_t *)aliasAddr = mask;
#else
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
*addr &= ~mask;
CORE_EXIT_CRITICAL();
#endif
}
/***************************************************************************//**
* @brief
* Perform peripheral register masked write.
*
* @details
* This function first reads the peripheral register and updates only bits
* that are set in the mask with content of val. Typically, the mask is a
* bit-field in the register and the value val is within the mask.
*
* @note
* The read-modify-write operation is executed in a critical section to
* guarantee atomicity. Note that atomicity can only be guaranteed if register
* is modified only by the core, and not by other peripherals (like DMA).
*
* @param[in] addr A peripheral register address.
*
* @param[in] mask A peripheral register mask.
*
* @param[in] val A peripheral register value. The value must be shifted to the
correct bit position in the register corresponding to the field
defined by the mask parameter. The register value must be
contained in the field defined by the mask parameter. The
register value is masked to prevent involuntary spillage.
******************************************************************************/
#if defined(__GNUC__) && __GNUC__ >= 10
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-null-dereference"
#endif
__STATIC_INLINE void BUS_RegMaskedWrite(volatile uint32_t *addr,
uint32_t mask,
uint32_t val)
{
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
EFM_ASSERT(addr != 0);
*addr = (*addr & ~mask) | (val & mask);
CORE_EXIT_CRITICAL();
}
#if defined(__GNUC__) && __GNUC__ >= 10
#pragma GCC diagnostic pop
#endif
/***************************************************************************//**
* @brief
* Perform a peripheral register masked read.
*
* @details
* Read an unshifted and masked value from a peripheral register.
*
* @note
* This operation is not hardware accelerated.
*
* @param[in] addr A peripheral register address.
*
* @param[in] mask A peripheral register mask.
*
* @return
* An unshifted and masked register value.
******************************************************************************/
__STATIC_INLINE uint32_t BUS_RegMaskedRead(volatile const uint32_t *addr,
uint32_t mask)
{
return *addr & mask;
}
/** @} (end addtogroup bus) */
#ifdef __cplusplus
}
#endif
#endif /* EM_BUS_H */

View File

@@ -0,0 +1,483 @@
/***************************************************************************//**
* @file
* @brief Chip Errata Workarounds
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_CHIP_H
#define EM_CHIP_H
#include "em_device.h"
#include "sl_common.h"
#if defined(_SILICON_LABS_32B_SERIES) && (_SILICON_LABS_32B_SERIES <= 2)
#include "em_system.h"
#endif
#include "em_bus.h"
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
#include "em_gpio.h"
#endif
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_240)
#include "em_cmu.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup chip CHIP - Chip Errata Workarounds
* @brief Chip errata workaround APIs
* @details
* API to apply chip errata workarounds at initialization and reset.
* @{
******************************************************************************/
/**************************************************************************//**
* @brief
* Chip initialization routine for revision errata workarounds.
*
* @note
* This function must be called immediately in main().
*
* This initialization function configures the device to a state
* as similar to later revisions as possible to improve software compatibility
* with newer parts. See the device-specific errata for details.
*****************************************************************************/
__STATIC_INLINE void CHIP_Init(void)
{
#if defined(MSC_CACHECMD_INVCACHE)
MSC->CACHECMD = MSC_CACHECMD_INVCACHE;
#elif defined(MSC_CMD_INVCACHE)
MSC->CMD = MSC_CMD_INVCACHE;
#endif
#if defined(_SILICON_LABS_32B_SERIES_0) && defined(_EFM32_GECKO_FAMILY)
uint32_t rev;
SYSTEM_ChipRevision_TypeDef chipRev;
volatile uint32_t *reg;
rev = *(volatile uint32_t *)(0x0FE081FC);
/* Engineering Sample calibration setup. */
if ((rev >> 24) == 0) {
reg = (volatile uint32_t *)0x400CA00C;
*reg &= ~(0x70UL);
/* DREG */
reg = (volatile uint32_t *)0x400C6020;
*reg &= ~(0xE0000000UL);
*reg |= ~(7UL << 25);
}
if ((rev >> 24) <= 3) {
/* DREG */
reg = (volatile uint32_t *)0x400C6020;
*reg &= ~(0x00001F80UL);
/* Update CMU reset values. */
reg = (volatile uint32_t *)0x400C8040;
*reg = 0;
reg = (volatile uint32_t *)0x400C8044;
*reg = 0;
reg = (volatile uint32_t *)0x400C8058;
*reg = 0;
reg = (volatile uint32_t *)0x400C8060;
*reg = 0;
reg = (volatile uint32_t *)0x400C8078;
*reg = 0;
}
SYSTEM_ChipRevisionGet(&chipRev);
if (chipRev.major == 0x01) {
/* Rev A errata handling for EM2/3. Must enable DMA clock to get EM2/3 */
/* to work. This will be fixed in later chip revisions and is only needed for rev A. */
if (chipRev.minor == 00) {
reg = (volatile uint32_t *)0x400C8040;
*reg |= 0x2;
}
/* Rev A+B errata handling for I2C when using EM2/3. USART0 clock must be enabled */
/* after waking up from EM2/EM3 to get I2C to work. This will be fixed in */
/* later chip revisions and is only needed for rev A+B. */
if (chipRev.minor <= 0x01) {
reg = (volatile uint32_t *)0x400C8044;
*reg |= 0x1;
}
}
/* Ensure correct ADC/DAC calibration value. */
rev = *(volatile uint32_t *)0x0FE081F0;
if (rev < 0x4C8ABA00) {
uint32_t cal;
/* Enable ADC/DAC clocks. */
reg = (volatile uint32_t *)0x400C8044UL;
*reg |= (1 << 14 | 1 << 11);
/* Retrive calibration values. */
cal = ((*(volatile uint32_t *)(0x0FE081B4UL) & 0x00007F00UL)
>> 8) << 24;
cal |= ((*(volatile uint32_t *)(0x0FE081B4UL) & 0x0000007FUL)
>> 0) << 16;
cal |= ((*(volatile uint32_t *)(0x0FE081B4UL) & 0x00007F00UL)
>> 8) << 8;
cal |= ((*(volatile uint32_t *)(0x0FE081B4UL) & 0x0000007FUL)
>> 0) << 0;
/* ADC0->CAL = 1.25 reference. */
reg = (volatile uint32_t *)0x40002034UL;
*reg = cal;
/* DAC0->CAL = 1.25 reference. */
reg = (volatile uint32_t *)(0x4000402CUL);
cal = *(volatile uint32_t *)0x0FE081C8UL;
*reg = cal;
/* Turn off ADC/DAC clocks. */
reg = (volatile uint32_t *)0x400C8044UL;
*reg &= ~(1 << 14 | 1 << 11);
}
#endif
#if defined(_SILICON_LABS_32B_SERIES_0) && defined(_EFM32_GIANT_FAMILY)
/****************************/
/* Fix for errata CMU_E113. */
uint8_t prodRev;
SYSTEM_ChipRevision_TypeDef chipRev;
prodRev = SYSTEM_GetProdRev();
SYSTEM_ChipRevisionGet(&chipRev);
// All Giant and Leopard parts except Leopard Rev E
if ((prodRev >= 16) && (chipRev.minor >= 3)
&& !((chipRev.major == 2) && (chipRev.minor == 4))) {
/* This fixes an issue with the LFXO on high temperatures. */
*(volatile uint32_t*)0x400C80C0 =
(*(volatile uint32_t*)0x400C80C0 & ~(1 << 6) ) | (1 << 4);
}
#endif
#if defined(_SILICON_LABS_32B_SERIES_0) && defined(_EFM32_HAPPY_FAMILY)
uint8_t prodRev;
prodRev = SYSTEM_GetProdRev();
if (prodRev <= 129) {
/* This fixes a mistaken internal connection between PC0 and PC4. */
/* This disables an internal pull-down on PC4. */
*(volatile uint32_t*)(0x400C6018) = (1 << 26) | (5 << 0);
/* This disables an internal LDO test signal driving PC4. */
*(volatile uint32_t*)(0x400C80E4) &= ~(1 << 24);
}
#endif
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
/****************************
* Fixes for errata GPIO_E201 (slewrate) and
* HFXO high-temperature oscillator startup robustness fix. */
uint32_t port;
uint32_t clkEn;
uint8_t prodRev;
const uint32_t setVal = (0x5 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
| (0x5 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
const uint32_t resetVal = _GPIO_P_CTRL_RESETVALUE
& ~(_GPIO_P_CTRL_SLEWRATE_MASK
| _GPIO_P_CTRL_SLEWRATEALT_MASK);
prodRev = SYSTEM_GetProdRev();
SYSTEM_ChipRevision_TypeDef chipRev;
SYSTEM_ChipRevisionGet(&chipRev);
/* This errata is fixed in hardware from PRODREV 0x8F. */
if (prodRev < 0x8F) {
/* Fixes for errata GPIO_E201 (slewrate). */
/* Save HFBUSCLK enable state and enable GPIO clock. */
clkEn = CMU->HFBUSCLKEN0;
CMU->HFBUSCLKEN0 = clkEn | CMU_HFBUSCLKEN0_GPIO;
/* Update slewrate. */
for (port = 0; port <= GPIO_PORT_MAX; port++) {
GPIO->P[port].CTRL = setVal | resetVal;
}
/* Restore HFBUSCLK enable state. */
CMU->HFBUSCLKEN0 = clkEn;
}
/* This errata is fixed in hardware from PRODREV 0x90. */
if (prodRev < 0x90) {
/* HFXO high-temperature oscillator startup robustness fix. */
CMU->HFXOSTARTUPCTRL =
(CMU->HFXOSTARTUPCTRL & ~_CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK)
| (0x20 << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT);
}
if (chipRev.major == 0x01) {
/* Fix for errata EMU_E210 - Potential Power-Down When Entering EM2 */
*(volatile uint32_t *)(EMU_BASE + 0x164) |= 0x4;
}
/****************************
* Fix for errata DCDC_E206.
* Disable bypass limit enabled temporarily in SystemInit() errata
* workaround. */
BUS_RegBitWrite(&EMU->DCDCCLIMCTRL, _EMU_DCDCCLIMCTRL_BYPLIMEN_SHIFT, 0);
#endif
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_84)
uint8_t prodRev = SYSTEM_GetProdRev();
/* EM2 current fixes for early samples. */
if (prodRev == 0U) {
*(volatile uint32_t *)(EMU_BASE + 0x190UL) = 0x0000ADE8UL;
*(volatile uint32_t *)(EMU_BASE + 0x198UL) |= (0x1UL << 2);
*(volatile uint32_t *)(EMU_BASE + 0x190UL) = 0x0;
}
if (prodRev < 2U) {
*(volatile uint32_t *)(EMU_BASE + 0x164UL) |= (0x1UL << 13);
}
/* Set optimal LFRCOCTRL VREFUPDATE and enable duty cycling of VREF. */
CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~_CMU_LFRCOCTRL_VREFUPDATE_MASK)
| CMU_LFRCOCTRL_VREFUPDATE_64CYCLES
| CMU_LFRCOCTRL_ENVREF;
#endif
#if defined(_SILICON_LABS_32B_SERIES_1) \
&& defined(_EFR_DEVICE) && (_SILICON_LABS_GECKO_INTERNAL_SDID >= 84)
MSC->CTRL |= 0x1UL << 8;
#endif
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_89)
SYSTEM_ChipRevision_TypeDef chipRev;
SYSTEM_ChipRevisionGet(&chipRev);
if ((chipRev.major > 1) || (chipRev.minor >= 3)) {
/* PLFRCO trim values */
*(volatile uint32_t *)(CMU_BASE + 0x28CUL) = 608;
*(volatile uint32_t *)(CMU_BASE + 0x290UL) = 356250;
*(volatile uint32_t *)(CMU_BASE + 0x2F0UL) = 0x04000118;
*(volatile uint32_t *)(CMU_BASE + 0x2F8UL) = 0x08328400;
}
#endif
/* Charge redist setup (fixed value): LCD->DBGCTRL.CHGRDSTSTR = 1 (reset: 0). */
#if defined(_LCD_DISPCTRL_CHGRDST_MASK)
#if defined(_SILICON_LABS_32B_SERIES_1)
CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_LE;
CMU->LFACLKEN0 |= CMU_LFACLKEN0_LCD;
*(volatile uint32_t *)(LCD_BASE + 0x034) |= (0x1UL << 12);
CMU->LFACLKEN0 &= ~CMU_LFACLKEN0_LCD;
CMU->HFBUSCLKEN0 &= ~CMU_HFBUSCLKEN0_LE;
#endif
#endif
#if defined(_SILICON_LABS_32B_SERIES_1) \
&& !defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80) \
&& !defined(ERRATA_FIX_EMU_E220_DECBOD_IGNORE)
/* First part of the EMU_E220 DECBOD Errata fix. DECBOD Reset can occur
* during voltage scaling after EM2/3 wakeup. Second part is in em_emu.c */
*(volatile uint32_t *)(EMU_BASE + 0x1A4) |= 0x1f << 10;
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
SYSTEM_ChipRevision_TypeDef chipRev;
SYSTEM_ChipRevisionGet(&chipRev);
if (chipRev.major == 0x01 && (HFXO0->STATUS & HFXO_STATUS_ENS) == 0U) {
/* Change HFXO default peak detector settings. */
*(volatile uint32_t*)(HFXO0_BASE + 0x34U) =
(*(volatile uint32_t*)(HFXO0_BASE + 0x34U) & 0xFF8000FFU)
| 0x00178500U;
/* Change HFXO low power control settings. */
*(volatile uint32_t*)(HFXO0_BASE + 0x30U) =
(*(volatile uint32_t*)(HFXO0_BASE + 0x30U) & 0xFFFF0FFFU)
| 0x0000C000U;
/* Change default SQBUF bias current. */
*(volatile uint32_t*)(HFXO0_BASE + 0x30U) |= 0x700;
}
if (chipRev.major == 0x01 && chipRev.minor == 0x0) {
/* Trigger RAM read for each RAM instance */
volatile uint32_t *dmem = (volatile uint32_t *) DMEM_RAM0_RAM_MEM_BASE;
for (uint32_t i = 0U; i < DMEM_NUM_BANK; i++) {
// Force memory read
*dmem;
dmem += (DMEM_BANK0_SIZE / 4U);
}
}
/* Set TRACE clock to intended reset value. */
CMU->TRACECLKCTRL = (CMU->TRACECLKCTRL & ~_CMU_TRACECLKCTRL_CLKSEL_MASK)
| CMU_TRACECLKCTRL_CLKSEL_HFRCOEM23;
#endif
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_205)
#if defined(SL_TRUSTZONE_SECURE)
#define HFRCO_CLK_CFG_CLR_ADDR (0x40012020UL)
#else
#define HFRCO_CLK_CFG_CLR_ADDR (0x50012020UL)
#endif
#define HFRCO_CLK_CFG_CLKOUTDIS0 (0x4UL)
if (SYSTEM_GetProdRev() == 1) {
bool hfrcoClkIsOff = (CMU->CLKEN0 & CMU_CLKEN0_HFRCO0) == 0;
CMU->CLKEN0_SET = CMU_CLKEN0_HFRCO0;
/* Enable HFRCO CLKOUT0. */
*(volatile uint32_t*)(HFRCO_CLK_CFG_CLR_ADDR) = HFRCO_CLK_CFG_CLKOUTDIS0;
if (hfrcoClkIsOff) {
CMU->CLKEN0_CLR = CMU_CLKEN0_HFRCO0;
}
}
#endif
/* PM-3503 */
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_210)
{
bool syscfgClkIsOff = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) == 0);
CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
bool dcdcClkIsOff = ((CMU->CLKEN0 & CMU_CLKEN0_DCDC) == 0);
CMU->CLKEN0_SET = CMU_CLKEN0_DCDC;
bool dcdcIsLock = ((DCDC->LOCKSTATUS & DCDC_LOCKSTATUS_LOCK_LOCKED) != 0);
DCDC->LOCK = DCDC_LOCK_LOCKKEY_UNLOCKKEY;
while (DCDC->SYNCBUSY & DCDC_SYNCBUSY_CTRL) {
/* Wait for previous synchronization to finish */
}
DCDC->CTRL_CLR = DCDC_CTRL_MODE;
while ((DCDC->STATUS & DCDC_STATUS_BYPSW) == 0U) {
/* Wait for BYPASS switch enable. */
}
if (dcdcIsLock) {
DCDC->LOCK = ~DCDC_LOCK_LOCKKEY_UNLOCKKEY;
}
if (dcdcClkIsOff) {
CMU->CLKEN0_CLR = CMU_CLKEN0_DCDC;
}
if (syscfgClkIsOff) {
CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
}
}
#endif
/* PM-5163 */
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_215) \
&& defined(_SILICON_LABS_EFR32_2G4HZ_HP_PA_PRESENT) \
&& (_SILICON_LABS_EFR32_2G4HZ_HP_PA_MAX_OUTPUT_DBM == 20)
SYSTEM_ChipRevision_TypeDef chipRev;
SYSTEM_ChipRevisionGet(&chipRev);
if (chipRev.major == 0x01 && chipRev.minor == 0x00) {
bool hfxo0ClkIsOff = (CMU->CLKEN0 & CMU_CLKEN0_HFXO0) == 0;
CMU->CLKEN0_SET = CMU_CLKEN0_HFXO0;
*(volatile uint32_t*)(HFXO0_BASE + 0x0034UL) =
(*(volatile uint32_t*)(HFXO0_BASE + 0x0034UL) & 0xE3FFFFFFUL)
| 0x0C000000UL;
if (hfxo0ClkIsOff) {
CMU->CLKEN0_CLR = CMU_CLKEN0_HFXO0;
}
}
#endif
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_240)
// Enable ICache out of reset.
CMU->CLKEN1_SET = _CMU_CLKEN1_ICACHE0_MASK;
ICACHE0->CTRL_CLR = _ICACHE_CTRL_CACHEDIS_MASK;
CMU->CLKEN1_CLR = _CMU_CLKEN1_ICACHE0_MASK;
CMU->CLKEN0_SET = _CMU_CLKEN0_HFRCO0_MASK;
if (((HFRCO0->CAL & _HFRCO_CAL_TUNING_MASK) >> _HFRCO_CAL_TUNING_SHIFT) == _HFRCO_CAL_TUNING_MASK) {
CMU_HFRCODPLLBandSet(cmuHFRCODPLLFreq_19M0Hz);
}
CMU->CLKEN0_CLR = _CMU_CLKEN0_HFRCO0_MASK;
#endif
}
/**************************************************************************//**
* @brief
* Chip reset routine with errata workarounds.
*
* @note
* This function should be called to reset the chip. It does not return.
*
* This function applies any errata workarounds needed to cleanly reset the
* device and then performs a system reset. See the device-specific errata for
* details.
*****************************************************************************/
__STATIC_INLINE void CHIP_Reset(void)
{
#if defined(_EFR_DEVICE) && defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
/****************************
* Workaround for errata DCDC_E206.
* Disable radio interference minimization features when resetting */
// Ensure access to EMU registers
EMU->LOCK = EMU_LOCK_LOCKKEY_UNLOCK;
EMU->PWRLOCK = EMU_PWRLOCK_LOCKKEY_LOCK;
// No need to do anything if the DCDC is not powering DVDD
if ((EMU->PWRCFG & _EMU_PWRCFG_PWRCFG_MASK) == EMU_PWRCFG_PWRCFG_DCDCTODVDD) {
// Make sure radio cannot accidentally re-enable features
*(volatile uint32_t *)(0x40084040UL) = 0x1UL;
// If DCDC is in use, disable features
uint32_t dcdcMode = EMU->DCDCCTRL & _EMU_DCDCCTRL_DCDCMODE_MASK;
if ((dcdcMode == EMU_DCDCCTRL_DCDCMODE_LOWNOISE)
|| (dcdcMode == EMU_DCDCCTRL_DCDCMODE_LOWPOWER)) {
BUS_RegBitWrite((volatile uint32_t *)(0x400E3060UL), 28UL, 0);
BUS_RegBitWrite((volatile uint32_t *)(0x400E3074UL), 0, 0);
}
}
#endif
NVIC_SystemReset();
}
/** @} (end addtogroup chip) */
#ifdef __cplusplus
}
#endif
#endif /* EM_CHIP_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
/***************************************************************************//**
* @file
* @brief CMU Compatibility Header
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_CMU_COMPAT_H
#define EM_CMU_COMPAT_H
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
#define CMU_IF_CALRDYIF CMU_IF_CALRDY
#define _CMU_IF_CALRDYIF_SHIFT _CMU_IF_CALRDY_SHIFT
#define _CMU_IF_CALRDYIF_MASK _CMU_IF_CALRDY_MASK
#define _CMU_IF_CALRDYIF_DEFAULT _CMU_IF_CALRDY_DEFAULT
#define CMU_IF_CALRDYIF_DEFAULT CMU_IF_CALRDY_DEFAULT
#define CMU_IF_CALOFIF CMU_IF_CALOF
#define _CMU_IF_CALOFIF_SHIFT _CMU_IF_CALOF_SHIFT
#define _CMU_IF_CALOFIF_MASK _CMU_IF_CALOF_MASK
#define _CMU_IF_CALOFIF_DEFAULT _CMU_IF_CALOF_DEFAULT
#define CMU_IF_CALOFIF_DEFAULT CMU_IF_CALOF_DEFAULT
#define CMU_IEN_CALRDYIEN CMU_IEN_CALRDY
#define _CMU_IEN_CALRDYIEN_SHIFT _CMU_IEN_CALRDY_SHIFT
#define _CMU_IEN_CALRDYIEN_MASK _CMU_IEN_CALRDY_MASK
#define _CMU_IEN_CALRDYIEN_DEFAULT _CMU_IEN_CALRDY_DEFAULT
#define CMU_IEN_CALRDYIEN_DEFAULT CMU_IEN_CALRDY_DEFAULT
#define CMU_IEN_CALOFIEN CMU_IEN_CALOF
#define _CMU_IEN_CALOFIEN_SHIFT _CMU_IEN_CALOF_SHIFT
#define _CMU_IEN_CALOFIEN_MASK _CMU_IEN_CALOF_MASK
#define _CMU_IEN_CALOFIEN_DEFAULT _CMU_IEN_CALOF_DEFAULT
#define CMU_IEN_CALOFIEN_DEFAULT CMU_IEN_CALOF_DEFAULT
#define HFRCO_IF_RDYIF HFRCO_IF_RDY
#define _HFRCO_IF_RDYIF_SHIFT _HFRCO_IF_RDY_SHIFT
#define _HFRCO_IF_RDYIF_MASK _HFRCO_IF_RDY_MASK
#define _HFRCO_IF_RDYIF_DEFAULT _HFRCO_IF_RDY_DEFAULT
#define HFRCO_IF_RDYIF_DEFAULT HFRCO_IF_RDY_DEFAULT
#define HFRCO_IEN_RDYIEN HFRCO_IEN_RDY
#define _HFRCO_IEN_RDYIEN_SHIFT _HFRCO_IEN_RDY_SHIFT
#define _HFRCO_IEN_RDYIEN_MASK _HFRCO_IEN_RDY_MASK
#define _HFRCO_IEN_RDYIEN_DEFAULT _HFRCO_IEN_RDY_DEFAULT
#define HFRCO_IEN_RDYIEN_DEFAULT HFRCO_IEN_RDY_DEFAULT
#define LFRCO_IF_RDYIF LFRCO_IF_RDY
#define _LFRCO_IF_RDYIF_SHIFT _LFRCO_IF_RDY_SHIFT
#define _LFRCO_IF_RDYIF_MASK _LFRCO_IF_RDY_MASK
#define _LFRCO_IF_RDYIF_DEFAULT _LFRCO_IF_RDY_DEFAULT
#define LFRCO_IF_RDYIF_DEFAULT LFRCO_IF_RDY_DEFAULT
#define LFRCO_IF_POSEDGEIF LFRCO_IF_POSEDGE
#define _LFRCO_IF_POSEDGEIF_SHIFT _LFRCO_IF_POSEDGE_SHIFT
#define _LFRCO_IF_POSEDGEIF_MASK _LFRCO_IF_POSEDGE_MASK
#define _LFRCO_IF_POSEDGEIF_DEFAULT _LFRCO_IF_POSEDGE_DEFAULT
#define LFRCO_IF_POSEDGEIF_DEFAULT LFRCO_IF_POSEDGE_DEFAULT
#define LFRCO_IF_NEGEDGEIF LFRCO_IF_NEGEDGE
#define _LFRCO_IF_NEGEDGEIF_SHIFT _LFRCO_IF_NEGEDGE_SHIFT
#define _LFRCO_IF_NEGEDGEIF_MASK _LFRCO_IF_NEGEDGE_MASK
#define _LFRCO_IF_NEGEDGEIF_DEFAULT _LFRCO_IF_NEGEDGE_DEFAULT
#define LFRCO_IF_NEGEDGEIF_DEFAULT LFRCO_IF_NEGEDGE_DEFAULT
#define LFRCO_IF_TCDONEIF LFRCO_IF_TCDONE
#define _LFRCO_IF_TCDONEIF_SHIFT _LFRCO_IF_TCDONE_SHIFT
#define _LFRCO_IF_TCDONEIF_MASK _LFRCO_IF_TCDONE_MASK
#define _LFRCO_IF_TCDONEIF_DEFAULT _LFRCO_IF_TCDONE_DEFAULT
#define LFRCO_IF_TCDONEIF_DEFAULT LFRCO_IF_TCDONE_DEFAULT
#define LFRCO_IF_CALDONEIF LFRCO_IF_CALDONE
#define _LFRCO_IF_CALDONEIF_SHIFT _LFRCO_IF_CALDONE_SHIFT
#define _LFRCO_IF_CALDONEIF_MASK _LFRCO_IF_CALDONE_MASK
#define _LFRCO_IF_CALDONEIF_DEFAULT _LFRCO_IF_CALDONE_DEFAULT
#define LFRCO_IF_CALDONEIF_DEFAULT LFRCO_IF_CALDONE_DEFAULT
#define LFRCO_IF_TEMPCHANGEIF LFRCO_IF_TEMPCHANGE
#define _LFRCO_IF_TEMPCHANGEIF_SHIFT _LFRCO_IF_TEMPCHANGE_SHIFT
#define _LFRCO_IF_TEMPCHANGEIF_MASK _LFRCO_IF_TEMPCHANGE_MASK
#define _LFRCO_IF_TEMPCHANGEIF_DEFAULT _LFRCO_IF_TEMPCHANGE_DEFAULT
#define LFRCO_IF_TEMPCHANGEIF_DEFAULT LFRCO_IF_TEMPCHANGE_DEFAULT
#define LFRCO_IF_SCHEDERRIF LFRCO_IF_SCHEDERR
#define _LFRCO_IF_SCHEDERRIF_SHIFT _LFRCO_IF_SCHEDERR_SHIFT
#define _LFRCO_IF_SCHEDERRIF_MASK _LFRCO_IF_SCHEDERR_MASK
#define _LFRCO_IF_SCHEDERRIF_DEFAULT _LFRCO_IF_SCHEDERR_DEFAULT
#define LFRCO_IF_SCHEDERRIF_DEFAULT LFRCO_IF_SCHEDERR_DEFAULT
#define LFRCO_IF_TCOORIF LFRCO_IF_TCOOR
#define _LFRCO_IF_TCOORIF_SHIFT _LFRCO_IF_TCOOR_SHIFT
#define _LFRCO_IF_TCOORIF_MASK _LFRCO_IF_TCOOR_MASK
#define _LFRCO_IF_TCOORIF_DEFAULT _LFRCO_IF_TCOOR_DEFAULT
#define LFRCO_IF_TCOORIF_DEFAULT LFRCO_IF_TCOOR_DEFAULT
#define LFRCO_IF_CALOORIF LFRCO_IF_CALOOR
#define _LFRCO_IF_CALOORIF_SHIFT _LFRCO_IF_CALOOR_SHIFT
#define _LFRCO_IF_CALOORIF_MASK _LFRCO_IF_CALOOR_MASK
#define _LFRCO_IF_CALOORIF_DEFAULT _LFRCO_IF_CALOOR_DEFAULT
#define LFRCO_IF_CALOORIF_DEFAULT LFRCO_IF_CALOOR_DEFAULT
#define LFRCO_IEN_RDYIEN LFRCO_IEN_RDY
#define _LFRCO_IEN_RDYIEN_SHIFT _LFRCO_IEN_RDY_SHIFT
#define _LFRCO_IEN_RDYIEN_MASK _LFRCO_IEN_RDY_MASK
#define _LFRCO_IEN_RDYIEN_DEFAULT _LFRCO_IEN_RDY_DEFAULT
#define LFRCO_IEN_RDYIEN_DEFAULT LFRCO_IEN_RDY_DEFAULT
#define LFRCO_IEN_POSEDGEIEN LFRCO_IEN_POSEDGE
#define _LFRCO_IEN_POSEDGEIEN_SHIFT _LFRCO_IEN_POSEDGE_SHIFT
#define _LFRCO_IEN_POSEDGEIEN_MASK _LFRCO_IEN_POSEDGE_MASK
#define _LFRCO_IEN_POSEDGEIEN_DEFAULT _LFRCO_IEN_POSEDGE_DEFAULT
#define LFRCO_IEN_POSEDGEIEN_DEFAULT LFRCO_IEN_POSEDGE_DEFAULT
#define LFRCO_IEN_NEGEDGEIEN LFRCO_IEN_NEGEDGE
#define _LFRCO_IEN_NEGEDGEIEN_SHIFT _LFRCO_IEN_NEGEDGE_SHIFT
#define _LFRCO_IEN_NEGEDGEIEN_MASK _LFRCO_IEN_NEGEDGE_MASK
#define _LFRCO_IEN_NEGEDGEIEN_DEFAULT _LFRCO_IEN_NEGEDGE_DEFAULT
#define LFRCO_IEN_NEGEDGEIEN_DEFAULT LFRCO_IEN_NEGEDGE_DEFAULT
#define LFRCO_IEN_TCDONEIEN LFRCO_IEN_TCDONE
#define _LFRCO_IEN_TCDONEIEN_SHIFT _LFRCO_IEN_TCDONE_SHIFT
#define _LFRCO_IEN_TCDONEIEN_MASK _LFRCO_IEN_TCDONE_MASK
#define _LFRCO_IEN_TCDONEIEN_DEFAULT _LFRCO_IEN_TCDONE_DEFAULT
#define LFRCO_IEN_TCDONEIEN_DEFAULT LFRCO_IEN_TCDONE_DEFAULT
#define LFRCO_IEN_CALDONEIEN LFRCO_IEN_CALDONE
#define _LFRCO_IEN_CALDONEIEN_SHIFT _LFRCO_IEN_CALDONE_SHIFT
#define _LFRCO_IEN_CALDONEIEN_MASK _LFRCO_IEN_CALDONE_MASK
#define _LFRCO_IEN_CALDONEIEN_DEFAULT _LFRCO_IEN_CALDONE_DEFAULT
#define LFRCO_IEN_CALDONEIEN_DEFAULT LFRCO_IEN_CALDONE_DEFAULT
#define LFRCO_IEN_TEMPCHANGEIEN LFRCO_IEN_TEMPCHANGE
#define _LFRCO_IEN_TEMPCHANGEIEN_SHIFT _LFRCO_IEN_TEMPCHANGE_SHIFT
#define _LFRCO_IEN_TEMPCHANGEIEN_MASK _LFRCO_IEN_TEMPCHANGE_MASK
#define _LFRCO_IEN_TEMPCHANGEIEN_DEFAULT _LFRCO_IEN_TEMPCHANGE_DEFAULT
#define LFRCO_IEN_TEMPCHANGEIEN_DEFAULT LFRCO_IEN_TEMPCHANGE_DEFAULT
#define LFRCO_IEN_SCHEDERRIEN LFRCO_IEN_SCHEDERR
#define _LFRCO_IEN_SCHEDERRIEN_SHIFT _LFRCO_IEN_SCHEDERR_SHIFT
#define _LFRCO_IEN_SCHEDERRIEN_MASK _LFRCO_IEN_SCHEDERR_MASK
#define _LFRCO_IEN_SCHEDERRIEN_DEFAULT _LFRCO_IEN_SCHEDERR_DEFAULT
#define LFRCO_IEN_SCHEDERRIEN_DEFAULT LFRCO_IEN_SCHEDERR_DEFAULT
#define LFRCO_IEN_TCOORIEN LFRCO_IEN_TCOOR
#define _LFRCO_IEN_TCOORIEN_SHIFT _LFRCO_IEN_TCOOR_SHIFT
#define _LFRCO_IEN_TCOORIEN_MASK _LFRCO_IEN_TCOOR_MASK
#define _LFRCO_IEN_TCOORIEN_DEFAULT _LFRCO_IEN_TCOOR_DEFAULT
#define LFRCO_IEN_TCOORIEN_DEFAULT LFRCO_IEN_TCOOR_DEFAULT
#define LFRCO_IEN_CALOORIEN LFRCO_IEN_CALOOR
#define _LFRCO_IEN_CALOORIEN_SHIFT _LFRCO_IEN_CALOOR_SHIFT
#define _LFRCO_IEN_CALOORIEN_MASK _LFRCO_IEN_CALOOR_MASK
#define _LFRCO_IEN_CALOORIEN_DEFAULT _LFRCO_IEN_CALOOR_DEFAULT
#define LFRCO_IEN_CALOORIEN_DEFAULT LFRCO_IEN_CALOOR_DEFAULT
#endif /* _SILICON_LABS_32B_SERIES_2_CONFIG_2 */
#endif

View File

@@ -0,0 +1,36 @@
/***************************************************************************//**
* @file
* @brief General purpose utilities.
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_COMMON_H
#define EM_COMMON_H
#include "em_device.h"
#include "sl_common.h"
#endif /* EM_COMMON_H */

View File

@@ -0,0 +1,174 @@
/***************************************************************************//**
* @file
* @brief Core interrupt handling API (Device Specific)
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_CORE_H
#define EM_CORE_H
#include "em_device.h"
#include "em_core_generic.h"
#include "sl_common.h"
/***************************************************************************//**
* @addtogroup core
* @{
******************************************************************************/
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
/** Number of words in a NVIC mask set. */
#define CORE_NVIC_REG_WORDS ((EXT_IRQ_COUNT + 31) / 32)
/** Number of entries in a default interrupt vector table. */
#define CORE_DEFAULT_VECTOR_TABLE_ENTRIES (EXT_IRQ_COUNT + 16)
/** Highest priority for core interrupt. */
#define CORE_INTERRUPT_HIGHEST_PRIORITY 0
/** Default priority for core interrupt. */
#define CORE_INTERRUPT_DEFAULT_PRIORITY 5
/** Lowest priority for core interrupt. */
#define CORE_INTERRUPT_LOWEST_PRIORITY 7
// Compile time sanity check.
#if (CORE_NVIC_REG_WORDS > 3)
#error "em_core: Unexpected NVIC external interrupt count."
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
************************ MACRO API ***************************************
******************************************************************************/
//
// NVIC mask section macro API.
//
/** Allocate storage for NVIC interrupt masks for use by
* CORE_ENTER/EXIT_NVIC() macros. */
#define CORE_DECLARE_NVIC_STATE CORE_nvicMask_t nvicState
/** Allocate storage for NVIC interrupt masks.
* @param[in] x
* The storage variable name to use.*/
#define CORE_DECLARE_NVIC_MASK(x) CORE_nvicMask_t x
/** Allocate storage for and zero initialize NVIC interrupt mask.
* @param[in] x
* The storage variable name to use.*/
#define CORE_DECLARE_NVIC_ZEROMASK(x) CORE_nvicMask_t x = { { 0 } }
/** NVIC mask style interrupt disable.
* @param[in] mask
* Mask specifying which NVIC interrupts to disable. */
#define CORE_NVIC_DISABLE(mask) CORE_NvicDisableMask(mask)
/** NVIC mask style interrupt enable.
* @param[in] mask
* Mask specifying which NVIC interrupts to enable. */
#define CORE_NVIC_ENABLE(mask) CORE_NvicEnableMask(mask)
/** Convenience macro for implementing a NVIC mask section.
* @param[in] mask
* Mask specifying which NVIC interrupts to disable within the section.
* @param[in] yourcode
* The code for the section. */
#define CORE_NVIC_SECTION(mask, yourcode) \
{ \
CORE_DECLARE_NVIC_STATE; \
CORE_ENTER_NVIC(mask); \
{ \
yourcode \
} \
CORE_EXIT_NVIC(); \
}
/** Enter NVIC mask section. Assumes that a @ref CORE_DECLARE_NVIC_STATE exist
* in scope.
* @param[in] disable
* Mask specifying which NVIC interrupts to disable within the section. */
#define CORE_ENTER_NVIC(disable) CORE_EnterNvicMask(&nvicState, disable)
/** Exit NVIC mask section. Assumes that a @ref CORE_DECLARE_NVIC_STATE exist
* in scope. */
#define CORE_EXIT_NVIC() CORE_NvicEnableMask(&nvicState)
/** NVIC maks style yield.
* @param[in] enable
* Mask specifying which NVIC interrupts to briefly enable. */
#define CORE_YIELD_NVIC(enable) CORE_YieldNvicMask(enable)
/*******************************************************************************
************************* TYPEDEFS ****************************************
******************************************************************************/
/** Storage for NVIC interrupt masks. */
typedef struct {
uint32_t a[CORE_NVIC_REG_WORDS]; /*!< Array of NVIC mask words. */
} CORE_nvicMask_t;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
bool CORE_IrqIsBlocked(IRQn_Type irqN) SL_DEPRECATED_API_SDK_2024_6;
void CORE_GetNvicEnabledMask(CORE_nvicMask_t *mask) SL_DEPRECATED_API_SDK_2024_6;
bool CORE_GetNvicMaskDisableState(const CORE_nvicMask_t *mask) SL_DEPRECATED_API_SDK_2024_6;
void CORE_EnterNvicMask(CORE_nvicMask_t *nvicState,
const CORE_nvicMask_t *disable) SL_DEPRECATED_API_SDK_2024_6;
void CORE_NvicDisableMask(const CORE_nvicMask_t *disable) SL_DEPRECATED_API_SDK_2024_6;
void CORE_NvicEnableMask(const CORE_nvicMask_t *enable) SL_DEPRECATED_API_SDK_2024_6;
void CORE_YieldNvicMask(const CORE_nvicMask_t *enable) SL_DEPRECATED_API_SDK_2024_6;
void CORE_NvicMaskSetIRQ(IRQn_Type irqN, CORE_nvicMask_t *mask) SL_DEPRECATED_API_SDK_2024_6;
void CORE_NvicMaskClearIRQ(IRQn_Type irqN, CORE_nvicMask_t *mask) SL_DEPRECATED_API_SDK_2024_6;
bool CORE_NvicIRQDisabled(IRQn_Type irqN) SL_DEPRECATED_API_SDK_2024_6;
void *CORE_GetNvicRamTableHandler(IRQn_Type irqN) SL_DEPRECATED_API_SDK_2024_6;
void CORE_SetNvicRamTableHandler(IRQn_Type irqN, void *handler) SL_DEPRECATED_API_SDK_2024_6;
void CORE_InitNvicVectorTable(uint32_t *sourceTable,
uint32_t sourceSize,
uint32_t *targetTable,
uint32_t targetSize,
void *defaultHandler,
bool overwriteActive);
#ifdef __cplusplus
}
#endif
/** @} (end addtogroup core) */
#endif /* EM_CORE_H */

View File

@@ -0,0 +1,36 @@
/***************************************************************************//**
* @file
* @brief Core interrupt handling API (Generic)
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_CORE_GENERIC_H
#define EM_CORE_GENERIC_H
#include "sl_core.h"
#endif /* EM_CORE_GENERIC_H */

View File

@@ -0,0 +1,130 @@
/***************************************************************************//**
* @file
* @brief Debug (DBG) API
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_DBG_H
#define EM_DBG_H
#include <stdbool.h>
#include "em_device.h"
#if defined(CoreDebug_DHCSR_C_DEBUGEN_Msk)
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup dbg
* @{
******************************************************************************/
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/** Lock modes */
typedef enum {
dbgLockModeAllowErase = 1UL, /**< Lock debug access. */
#if !defined(_SILICON_LABS_32B_SERIES_0)
dbgLockModePermanent = 2UL /**< Lock debug access permanently. */
#endif
} DBG_LockMode_TypeDef;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
#if defined(GPIO_ROUTE_SWCLKPEN) \
|| defined(GPIO_ROUTEPEN_SWCLKTCKPEN) \
|| defined(GPIO_DBGROUTEPEN_SWCLKTCKPEN)
/***************************************************************************//**
* @brief
* Check if a debugger is connected (and debug session activated).
*
* @details
* Used to make run-time decisions depending on whether or not a debug session
* has been active since last reset, i.e., using a debug probe or similar. In
* some cases, special handling is required in that scenario.
*
* @return
* True if a debug session is active since last reset, otherwise false.
******************************************************************************/
__STATIC_INLINE bool DBG_Connected(void)
{
return (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) ? true : false;
}
#endif
#if defined(GPIO_ROUTE_SWOPEN) \
|| defined(GPIO_ROUTEPEN_SWVPEN) \
|| defined(GPIO_TRACEROUTEPEN_SWVPEN)
void DBG_SWOEnable(unsigned int location);
#endif
#if defined (EMU_CTRL_EM2DBGEN)
/***************************************************************************//**
* @brief
* Enable or disable debug support while in EM2 mode.
*
* @warning
* Disabling debug support in EM2 will reduce current consumption with 1-2 uA,
* but some debuggers will have problems regaining control over a device which
* is in EM2 and has debug support disabled.
*
* To remedy this, set the WSTK switch next to the battery holder to USB
* (powers down the EFR). Execute Simplicity Commander with command line
* parameters:
* "./commander.exe device recover"
* and then immediately move the switch to the AEM position. An additional
* "./commander.exe device masserase"
* command completes the recovery procedure.
*
* @param[in] enable
* Boolean true enables EM2 debug support, false disables.
******************************************************************************/
__STATIC_INLINE void DBG_EM2DebugEnable(bool enable)
{
if (enable) {
EMU->CTRL_SET = EMU_CTRL_EM2DBGEN;
} else {
EMU->CTRL_CLR = EMU_CTRL_EM2DBGEN;
}
}
#endif
/** @} (end addtogroup dbg) */
#ifdef __cplusplus
}
#endif
#endif /* defined( CoreDebug_DHCSR_C_DEBUGEN_Msk ) */
#endif /* EM_DBG_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,218 @@
/***************************************************************************//**
* @file
* @brief EUSART Compatibility Header
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_EUSART_COMPAT_H
#define EM_EUSART_COMPAT_H
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
#define EUSART_IF_TXCIF EUSART_IF_TXC
#define _EUSART_IF_TXCIF_SHIFT _EUSART_IF_TXC_SHIFT
#define _EUSART_IF_TXCIF_MASK _EUSART_IF_TXC_MASK
#define _EUSART_IF_TXCIF_DEFAULT _EUSART_IF_TXC_DEFAULT
#define EUSART_IF_TXCIF_DEFAULT EUSART_IF_TXC_DEFAULT
#define EUSART_IF_TXFLIF EUSART_IF_TXFL
#define _EUSART_IF_TXFLIF_SHIFT _EUSART_IF_TXFL_SHIFT
#define _EUSART_IF_TXFLIF_MASK _EUSART_IF_TXFL_MASK
#define _EUSART_IF_TXFLIF_DEFAULT _EUSART_IF_TXFL_DEFAULT
#define EUSART_IF_TXFLIF_DEFAULT EUSART_IF_TXFL_DEFAULT
#define EUSART_IF_RXFLIF EUSART_IF_RXFL
#define _EUSART_IF_RXFLIF_SHIFT _EUSART_IF_RXFL_SHIFT
#define _EUSART_IF_RXFLIF_MASK _EUSART_IF_RXFL_MASK
#define _EUSART_IF_RXFLIF_DEFAULT _EUSART_IF_RXFL_DEFAULT
#define EUSART_IF_RXFLIF_DEFAULT EUSART_IF_RXFL_DEFAULT
#define EUSART_IF_RXFULLIF EUSART_IF_RXFULL
#define _EUSART_IF_RXFULLIF_SHIFT _EUSART_IF_RXFULL_SHIFT
#define _EUSART_IF_RXFULLIF_MASK _EUSART_IF_RXFULL_MASK
#define _EUSART_IF_RXFULLIF_DEFAULT _EUSART_IF_RXFULL_DEFAULT
#define EUSART_IF_RXFULLIF_DEFAULT EUSART_IF_RXFULL_DEFAULT
#define EUSART_IF_RXOFIF EUSART_IF_RXOF
#define _EUSART_IF_RXOFIF_SHIFT _EUSART_IF_RXOF_SHIFT
#define _EUSART_IF_RXOFIF_MASK _EUSART_IF_RXOF_MASK
#define _EUSART_IF_RXOFIF_DEFAULT _EUSART_IF_RXOF_DEFAULT
#define EUSART_IF_RXOFIF_DEFAULT EUSART_IF_RXOF_DEFAULT
#define EUSART_IF_RXUFIF EUSART_IF_RXUF
#define _EUSART_IF_RXUFIF_SHIFT _EUSART_IF_RXUF_SHIFT
#define _EUSART_IF_RXUFIF_MASK _EUSART_IF_RXUF_MASK
#define _EUSART_IF_RXUFIF_DEFAULT _EUSART_IF_RXUF_DEFAULT
#define EUSART_IF_RXUFIF_DEFAULT EUSART_IF_RXUF_DEFAULT
#define EUSART_IF_TXOFIF EUSART_IF_TXOF
#define _EUSART_IF_TXOFIF_SHIFT _EUSART_IF_TXOF_SHIFT
#define _EUSART_IF_TXOFIF_MASK _EUSART_IF_TXOF_MASK
#define _EUSART_IF_TXOFIF_DEFAULT _EUSART_IF_TXOF_DEFAULT
#define EUSART_IF_TXOFIF_DEFAULT EUSART_IF_TXOF_DEFAULT
#define EUSART_IF_PERRIF EUSART_IF_PERR
#define _EUSART_IF_PERRIF_SHIFT _EUSART_IF_PERR_SHIFT
#define _EUSART_IF_PERRIF_MASK _EUSART_IF_PERR_MASK
#define _EUSART_IF_PERRIF_DEFAULT _EUSART_IF_PERR_DEFAULT
#define EUSART_IF_PERRIF_DEFAULT EUSART_IF_PERR_DEFAULT
#define EUSART_IF_FERRIF EUSART_IF_FERR
#define _EUSART_IF_FERRIF_SHIFT _EUSART_IF_FERR_SHIFT
#define _EUSART_IF_FERRIF_MASK _EUSART_IF_FERR_MASK
#define _EUSART_IF_FERRIF_DEFAULT _EUSART_IF_FERR_DEFAULT
#define EUSART_IF_FERRIF_DEFAULT EUSART_IF_FERR_DEFAULT
#define EUSART_IF_MPAFIF EUSART_IF_MPAF
#define _EUSART_IF_MPAFIF_SHIFT _EUSART_IF_MPAF_SHIFT
#define _EUSART_IF_MPAFIF_MASK _EUSART_IF_MPAF_MASK
#define _EUSART_IF_MPAFIF_DEFAULT _EUSART_IF_MPAF_DEFAULT
#define EUSART_IF_MPAFIF_DEFAULT EUSART_IF_MPAF_DEFAULT
#define EUSART_IF_CCFIF EUSART_IF_CCF
#define _EUSART_IF_CCFIF_SHIFT _EUSART_IF_CCF_SHIFT
#define _EUSART_IF_CCFIF_MASK _EUSART_IF_CCF_MASK
#define _EUSART_IF_CCFIF_DEFAULT _EUSART_IF_CCF_DEFAULT
#define EUSART_IF_CCFIF_DEFAULT EUSART_IF_CCF_DEFAULT
#define EUSART_IF_TXIDLEIF EUSART_IF_TXIDLE
#define _EUSART_IF_TXIDLEIF_SHIFT _EUSART_IF_TXIDLE_SHIFT
#define _EUSART_IF_TXIDLEIF_MASK _EUSART_IF_TXIDLE_MASK
#define _EUSART_IF_TXIDLEIF_DEFAULT _EUSART_IF_TXIDLE_DEFAULT
#define EUSART_IF_TXIDLEIF_DEFAULT EUSART_IF_TXIDLE_DEFAULT
#define EUSART_IF_STARTFIF EUSART_IF_STARTF
#define _EUSART_IF_STARTFIF_SHIFT _EUSART_IF_STARTF_SHIFT
#define _EUSART_IF_STARTFIF_MASK _EUSART_IF_STARTF_MASK
#define _EUSART_IF_STARTFIF_DEFAULT _EUSART_IF_STARTF_DEFAULT
#define EUSART_IF_STARTFIF_DEFAULT EUSART_IF_STARTF_DEFAULT
#define EUSART_IF_SIGFIF EUSART_IF_SIGF
#define _EUSART_IF_SIGFIF_SHIFT _EUSART_IF_SIGF_SHIFT
#define _EUSART_IF_SIGFIF_MASK _EUSART_IF_SIGF_MASK
#define _EUSART_IF_SIGFIF_DEFAULT _EUSART_IF_SIGF_DEFAULT
#define EUSART_IF_SIGFIF_DEFAULT EUSART_IF_SIGF_DEFAULT
#define EUSART_IF_AUTOBAUDDONEIF EUSART_IF_AUTOBAUDDONE
#define _EUSART_IF_AUTOBAUDDONEIF_SHIFT _EUSART_IF_AUTOBAUDDONE_SHIFT
#define _EUSART_IF_AUTOBAUDDONEIF_MASK _EUSART_IF_AUTOBAUDDONE_MASK
#define _EUSART_IF_AUTOBAUDDONEIF_DEFAULT _EUSART_IF_AUTOBAUDDONE_DEFAULT
#define EUSART_IF_AUTOBAUDDONEIF_DEFAULT EUSART_IF_AUTOBAUDDONE_DEFAULT
#define EUSART_IEN_TXCIEN EUSART_IEN_TXC
#define _EUSART_IEN_TXCIEN_SHIFT _EUSART_IEN_TXC_SHIFT
#define _EUSART_IEN_TXCIEN_MASK _EUSART_IEN_TXC_MASK
#define _EUSART_IEN_TXCIEN_DEFAULT _EUSART_IEN_TXC_DEFAULT
#define EUSART_IEN_TXCIEN_DEFAULT EUSART_IEN_TXC_DEFAULT
#define EUSART_IEN_TXFLIEN EUSART_IEN_TXFL
#define _EUSART_IEN_TXFLIEN_SHIFT _EUSART_IEN_TXFL_SHIFT
#define _EUSART_IEN_TXFLIEN_MASK _EUSART_IEN_TXFL_MASK
#define _EUSART_IEN_TXFLIEN_DEFAULT _EUSART_IEN_TXFL_DEFAULT
#define EUSART_IEN_TXFLIEN_DEFAULT EUSART_IEN_TXFL_DEFAULT
#define EUSART_IEN_RXFLIEN EUSART_IEN_RXFL
#define _EUSART_IEN_RXFLIEN_SHIFT _EUSART_IEN_RXFL_SHIFT
#define _EUSART_IEN_RXFLIEN_MASK _EUSART_IEN_RXFL_MASK
#define _EUSART_IEN_RXFLIEN_DEFAULT _EUSART_IEN_RXFL_DEFAULT
#define EUSART_IEN_RXFLIEN_DEFAULT EUSART_IEN_RXFL_DEFAULT
#define EUSART_IEN_RXFULLIEN EUSART_IEN_RXFULL
#define _EUSART_IEN_RXFULLIEN_SHIFT _EUSART_IEN_RXFULL_SHIFT
#define _EUSART_IEN_RXFULLIEN_MASK _EUSART_IEN_RXFULL_MASK
#define _EUSART_IEN_RXFULLIEN_DEFAULT _EUSART_IEN_RXFULL_DEFAULT
#define EUSART_IEN_RXFULLIEN_DEFAULT EUSART_IEN_RXFULL_DEFAULT
#define EUSART_IEN_RXOFIEN EUSART_IEN_RXOF
#define _EUSART_IEN_RXOFIEN_SHIFT _EUSART_IEN_RXOF_SHIFT
#define _EUSART_IEN_RXOFIEN_MASK _EUSART_IEN_RXOF_MASK
#define _EUSART_IEN_RXOFIEN_DEFAULT _EUSART_IEN_RXOF_DEFAULT
#define EUSART_IEN_RXOFIEN_DEFAULT EUSART_IEN_RXOF_DEFAULT
#define EUSART_IEN_RXUFIEN EUSART_IEN_RXUF
#define _EUSART_IEN_RXUFIEN_SHIFT _EUSART_IEN_RXUF_SHIFT
#define _EUSART_IEN_RXUFIEN_MASK _EUSART_IEN_RXUF_MASK
#define _EUSART_IEN_RXUFIEN_DEFAULT _EUSART_IEN_RXUF_DEFAULT
#define EUSART_IEN_RXUFIEN_DEFAULT EUSART_IEN_RXUF_DEFAULT
#define EUSART_IEN_TXOFIEN EUSART_IEN_TXOF
#define _EUSART_IEN_TXOFIEN_SHIFT _EUSART_IEN_TXOF_SHIFT
#define _EUSART_IEN_TXOFIEN_MASK _EUSART_IEN_TXOF_MASK
#define _EUSART_IEN_TXOFIEN_DEFAULT _EUSART_IEN_TXOF_DEFAULT
#define EUSART_IEN_TXOFIEN_DEFAULT EUSART_IEN_TXOF_DEFAULT
#define EUSART_IEN_PERRIEN EUSART_IEN_PERR
#define _EUSART_IEN_PERRIEN_SHIFT _EUSART_IEN_PERR_SHIFT
#define _EUSART_IEN_PERRIEN_MASK _EUSART_IEN_PERR_MASK
#define _EUSART_IEN_PERRIEN_DEFAULT _EUSART_IEN_PERR_DEFAULT
#define EUSART_IEN_PERRIEN_DEFAULT EUSART_IEN_PERR_DEFAULT
#define EUSART_IEN_FERRIEN EUSART_IEN_FERR
#define _EUSART_IEN_FERRIEN_SHIFT _EUSART_IEN_FERR_SHIFT
#define _EUSART_IEN_FERRIEN_MASK _EUSART_IEN_FERR_MASK
#define _EUSART_IEN_FERRIEN_DEFAULT _EUSART_IEN_FERR_DEFAULT
#define EUSART_IEN_FERRIEN_DEFAULT EUSART_IEN_FERR_DEFAULT
#define EUSART_IEN_MPAFIEN EUSART_IEN_MPAF
#define _EUSART_IEN_MPAFIEN_SHIFT _EUSART_IEN_MPAF_SHIFT
#define _EUSART_IEN_MPAFIEN_MASK _EUSART_IEN_MPAF_MASK
#define _EUSART_IEN_MPAFIEN_DEFAULT _EUSART_IEN_MPAF_DEFAULT
#define EUSART_IEN_MPAFIEN_DEFAULT EUSART_IEN_MPAF_DEFAULT
#define EUSART_IEN_CCFIEN EUSART_IEN_CCF
#define _EUSART_IEN_CCFIEN_SHIFT _EUSART_IEN_CCF_SHIFT
#define _EUSART_IEN_CCFIEN_MASK _EUSART_IEN_CCF_MASK
#define _EUSART_IEN_CCFIEN_DEFAULT _EUSART_IEN_CCF_DEFAULT
#define EUSART_IEN_CCFIEN_DEFAULT EUSART_IEN_CCF_DEFAULT
#define EUSART_IEN_TXIDLEIEN EUSART_IEN_TXIDLE
#define _EUSART_IEN_TXIDLEIEN_SHIFT _EUSART_IEN_TXIDLE_SHIFT
#define _EUSART_IEN_TXIDLEIEN_MASK _EUSART_IEN_TXIDLE_MASK
#define _EUSART_IEN_TXIDLEIEN_DEFAULT _EUSART_IEN_TXIDLE_DEFAULT
#define EUSART_IEN_TXIDLEIEN_DEFAULT EUSART_IEN_TXIDLE_DEFAULT
#define EUSART_IEN_STARTFIEN EUSART_IEN_STARTF
#define _EUSART_IEN_STARTFIEN_SHIFT _EUSART_IEN_STARTF_SHIFT
#define _EUSART_IEN_STARTFIEN_MASK _EUSART_IEN_STARTF_MASK
#define _EUSART_IEN_STARTFIEN_DEFAULT _EUSART_IEN_STARTF_DEFAULT
#define EUSART_IEN_STARTFIEN_DEFAULT EUSART_IEN_STARTF_DEFAULT
#define EUSART_IEN_SIGFIEN EUSART_IEN_SIGF
#define _EUSART_IEN_SIGFIEN_SHIFT _EUSART_IEN_SIGF_SHIFT
#define _EUSART_IEN_SIGFIEN_MASK _EUSART_IEN_SIGF_MASK
#define _EUSART_IEN_SIGFIEN_DEFAULT _EUSART_IEN_SIGF_DEFAULT
#define EUSART_IEN_SIGFIEN_DEFAULT EUSART_IEN_SIGF_DEFAULT
#define EUSART_IEN_AUTOBAUDDONEIEN EUSART_IEN_AUTOBAUDDONE
#define _EUSART_IEN_AUTOBAUDDONEIEN_SHIFT _EUSART_IEN_AUTOBAUDDONE_SHIFT
#define _EUSART_IEN_AUTOBAUDDONEIEN_MASK _EUSART_IEN_AUTOBAUDDONE_MASK
#define _EUSART_IEN_AUTOBAUDDONEIEN_DEFAULT _EUSART_IEN_AUTOBAUDDONE_DEFAULT
#define EUSART_IEN_AUTOBAUDDONEIEN_DEFAULT EUSART_IEN_AUTOBAUDDONE_DEFAULT
#endif // _SILICON_LABS_32B_SERIES_2_CONFIG_2
#endif

View File

@@ -0,0 +1,346 @@
/***************************************************************************//**
* @file
* @brief General Purpose Cyclic Redundancy Check (GPCRC) API.
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_GPCRC_H
#define EM_GPCRC_H
#include "em_bus.h"
#include "em_device.h"
#if defined(GPCRC_PRESENT) && (GPCRC_COUNT > 0)
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup gpcrc GPCRC - General Purpose CRC
* @brief General Purpose Cyclic Redundancy Check (GPCRC) API
*
* @details
* The GPCRC API functions provide full support for the GPCRC peripheral.
*
* The GPCRC module is a peripheral that implements a Cyclic Redundancy Check
* (CRC) function. It supports a fixed 32-bit polynomial and a user
* configurable 16-bit polynomial. The fixed 32-bit polynomial is the commonly
* used IEEE 802.3 polynomial 0x04C11DB7.
*
* When using a 16-bit polynomial it is up to the user to choose a polynomial
* that fits the application. Commonly used 16-bit polynomials are 0x1021
* (CCITT-16), 0x3D65 (IEC16-MBus), and 0x8005 (ZigBee, 802.15.4, and USB).
* See this link for other polynomials:
* https://en.wikipedia.org/wiki/Cyclic_redundancy_check
*
* Before a CRC calculation can begin, call the
* @ref GPCRC_Start function. This function will reset CRC calculation
* by copying the configured initialization value over to the CRC data register.
*
* There are two ways of sending input data to the GPCRC. Either write
* the input data into the input data register using input functions
* @ref GPCRC_InputU32, @ref GPCRC_InputU16 and @ref GPCRC_InputU8, or the
* user can configure @ref ldma to transfer data directly to one of the GPCRC
* input data registers.
*
* <b> Examples of GPCRC usage: </b>
*
* A CRC-32 Calculation:
*
* @include em_gpcrc_crc32.c
*
* A CRC-16 Calculation:
*
* @include em_gpcrc_crc16.c
*
* A CRC-CCITT calculation:
*
* @include em_gpcrc_ccit.c
*
* @{
******************************************************************************/
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/** CRC initialization structure. */
typedef struct {
/**
* CRC polynomial value. GPCRC supports either a fixed 32-bit polynomial
* or a user-configurable 16 bit polynomial. The fixed 32-bit polynomial
* is the one used in IEEE 802.3, which has the value 0x04C11DB7. To use the
* 32-bit fixed polynomial, assign 0x04C11DB7 to the crcPoly field.
* To use a 16-bit polynomial, assign a value to crcPoly where the upper 16
* bits are zero.
*
* The polynomial should be written in normal bit order. For instance,
* to use the CRC-16 polynomial X^16 + X^15 + X^2 + 1, first convert
* it to hex representation and remove the highest order term
* of the polynomial. This will give 0x8005 as the value to write into
* crcPoly.
*/
uint32_t crcPoly;
/**
* CRC initialization value. This value is assigned to the GPCRC_INIT register.
* The initValue is loaded into the data register when calling the
* @ref GPCRC_Start function or when one of the data registers are read
* while @ref autoInit is enabled.
*/
uint32_t initValue;
/**
* Reverse byte order. This has an effect when sending a 32-bit word or
* 16-bit half word input to the CRC calculation. When set to true, the input
* bytes are reversed before entering the CRC calculation. When set to
* false, the input bytes stay in the same order.
*/
bool reverseByteOrder;
/**
* Reverse bits within each input byte. This setting enables or disables byte
* level bit reversal. When byte-level bit reversal is enabled, then each byte
* of input data will be reversed before entering CRC calculation.
*/
bool reverseBits;
/**
* Enable/disable byte mode. When byte mode is enabled, then all input
* is treated as single byte input even though the input is a 32-bit word
* or a 16-bit half word. Only the least significant byte of the data-word
* will be used for CRC calculation for all writes.
*/
bool enableByteMode;
/**
* Enable automatic initialization by re-seeding the CRC result based on
* the init value after reading one of the CRC data registers.
*/
bool autoInit;
/** Enable/disable GPCRC when initialization is completed. */
bool enable;
} GPCRC_Init_TypeDef;
/** Default configuration for GPCRC_Init_TypeDef structure. */
#define GPCRC_INIT_DEFAULT \
{ \
0x04C11DB7UL, /* CRC32 Polynomial value. */ \
0x00000000UL, /* Initialization value. */ \
false, /* Byte order is normal. */ \
false, /* Bit order is not reversed on output. */ \
false, /* Disable byte mode. */ \
false, /* Disable automatic initialization on data read. */ \
true, /* Enable GPCRC. */ \
}
/*******************************************************************************
****************************** PROTOTYPES *********************************
******************************************************************************/
void GPCRC_Init(GPCRC_TypeDef * gpcrc, const GPCRC_Init_TypeDef * init);
void GPCRC_Reset(GPCRC_TypeDef * gpcrc);
/***************************************************************************//**
* @brief
* Enable/disable GPCRC.
*
* @param[in] gpcrc
* Pointer to GPCRC peripheral register block.
*
* @param[in] enable
* True to enable GPCRC, false to disable.
******************************************************************************/
__STATIC_INLINE void GPCRC_Enable(GPCRC_TypeDef * gpcrc, bool enable)
{
#if defined(GPCRC_EN_EN)
BUS_RegBitWrite(&gpcrc->EN, _GPCRC_EN_EN_SHIFT, enable);
#else
BUS_RegBitWrite(&gpcrc->CTRL, _GPCRC_CTRL_EN_SHIFT, enable);
#endif
}
/***************************************************************************//**
* @brief
* Issue a command to initialize the CRC calculation.
*
* @details
* Issues the command INIT in GPCRC_CMD that initializes the
* CRC calculation by writing the initial values to the DATA register.
*
* @param[in] gpcrc
* Pointer to GPCRC peripheral register block.
******************************************************************************/
__STATIC_INLINE void GPCRC_Start(GPCRC_TypeDef * gpcrc)
{
gpcrc->CMD = GPCRC_CMD_INIT;
}
/***************************************************************************//**
* @brief
* Set the initialization value of the CRC.
*
* @param [in] initValue
* Value to use to initialize a CRC calculation. This value is moved into
* the data register when calling @ref GPCRC_Start
*
* @param[in] gpcrc
* Pointer to GPCRC peripheral register block.
******************************************************************************/
__STATIC_INLINE void GPCRC_InitValueSet(GPCRC_TypeDef * gpcrc, uint32_t initValue)
{
gpcrc->INIT = initValue;
}
/***************************************************************************//**
* @brief
* Write a 32-bit value to the input data register of the CRC.
*
* @details
* Use this function to write a 32-bit input data to the CRC. CRC
* calculation is based on the provided input data using the configured
* CRC polynomial.
*
* @param[in] gpcrc
* Pointer to GPCRC peripheral register block.
*
* @param[in] data
* Data to be written to the input data register.
******************************************************************************/
__STATIC_INLINE void GPCRC_InputU32(GPCRC_TypeDef * gpcrc, uint32_t data)
{
gpcrc->INPUTDATA = data;
}
/***************************************************************************//**
* @brief
* Write a 16-bit value to the input data register of the CRC.
*
* @details
* Use this function to write a 16 bit input data to the CRC. CRC
* calculation is based on the provided input data using the configured
* CRC polynomial.
*
* @param[in] gpcrc
* Pointer to GPCRC peripheral register block.
*
* @param[in] data
* Data to be written to the input data register.
******************************************************************************/
__STATIC_INLINE void GPCRC_InputU16(GPCRC_TypeDef * gpcrc, uint16_t data)
{
gpcrc->INPUTDATAHWORD = data;
}
/***************************************************************************//**
* @brief
* Write an 8-bit value to the CRC input data register.
*
* @details
* Use this function to write an 8-bit input data to the CRC. CRC
* calculation is based on the provided input data using the configured
* CRC polynomial.
*
* @param[in] gpcrc
* Pointer to GPCRC peripheral register block.
*
* @param[in] data
* Data to be written to the input data register.
******************************************************************************/
__STATIC_INLINE void GPCRC_InputU8(GPCRC_TypeDef * gpcrc, uint8_t data)
{
gpcrc->INPUTDATABYTE = data;
}
/***************************************************************************//**
* @brief
* Read the CRC data register.
*
* @details
* Use this function to read the calculated CRC value.
*
* @param[in] gpcrc
* Pointer to GPCRC peripheral register block.
*
* @return
* Content of the CRC data register.
******************************************************************************/
__STATIC_INLINE uint32_t GPCRC_DataRead(GPCRC_TypeDef * gpcrc)
{
return gpcrc->DATA;
}
/***************************************************************************//**
* @brief
* Read the data register of the CRC bit reversed.
*
* @details
* Use this function to read the calculated CRC value bit reversed. When
* using a 32-bit polynomial, bits [31:0] are reversed, when using a
* 16-bit polynomial, bits [15:0] are reversed.
*
* @param[in] gpcrc
* Pointer to GPCRC peripheral register block.
*
* @return
* Content of the CRC data register bit reversed.
******************************************************************************/
__STATIC_INLINE uint32_t GPCRC_DataReadBitReversed(GPCRC_TypeDef * gpcrc)
{
return gpcrc->DATAREV;
}
/***************************************************************************//**
* @brief
* Read the data register of the CRC byte reversed.
*
* @details
* Use this function to read the calculated CRC value byte reversed.
*
* @param[in] gpcrc
* Pointer to GPCRC peripheral register block.
*
* @return
* Content of the CRC data register byte reversed.
******************************************************************************/
__STATIC_INLINE uint32_t GPCRC_DataReadByteReversed(GPCRC_TypeDef * gpcrc)
{
return gpcrc->DATABYTEREV;
}
/** @} (end addtogroup gpcrc) */
#ifdef __cplusplus
}
#endif
#endif /* defined(GPCRC_COUNT) && (GPCRC_COUNT > 0) */
#endif /* EM_GPCRC_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,525 @@
/***************************************************************************//**
* @file
* @brief Inter-integrated circuit (I2C) peripheral API
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_I2C_H
#define EM_I2C_H
#include "em_device.h"
#if defined(I2C_COUNT) && (I2C_COUNT > 0)
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup i2c
* @{
******************************************************************************/
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
/**
* @brief
* Standard mode max frequency assuming using 4:4 ratio for Nlow:Nhigh.
* @details
* From I2C specification: Min Tlow = 4.7us, min Thigh = 4.0us,
* max Trise=1.0us, max Tfall=0.3us. Since ratio is 4:4, have to use
* worst case value of Tlow or Thigh as base.
*
* 1/(Tlow + Thigh + 1us + 0.3us) = 1/(4.7 + 4.7 + 1.3)us = 93458Hz
* @note
* Due to chip characteristics, max value is somewhat reduced.
*/
#if defined(_SILICON_LABS_32B_SERIES_0) \
&& (defined(_EFM32_GECKO_FAMILY) \
|| defined(_EFM32_TINY_FAMILY) \
|| defined(_EFM32_ZERO_FAMILY) \
|| defined(_EFM32_HAPPY_FAMILY))
#define I2C_FREQ_STANDARD_MAX 93000
#elif defined(_SILICON_LABS_32B_SERIES_0) \
&& (defined(_EFM32_GIANT_FAMILY) \
|| defined(_EFM32_WONDER_FAMILY))
#define I2C_FREQ_STANDARD_MAX 92000
#elif defined(_SILICON_LABS_32B_SERIES_1)
// None of the chips on this platform has been characterized on this parameter.
// Use same value as on Wonder until further notice.
#define I2C_FREQ_STANDARD_MAX 92000
#elif defined(_SILICON_LABS_32B_SERIES_2)
#define I2C_FREQ_STANDARD_MAX 100000
#else
#error "Unknown device family."
#endif
/**
* @brief
* Fast mode max frequency assuming using 6:3 ratio for Nlow:Nhigh.
* @details
* From I2C specification: Min Tlow = 1.3us, min Thigh = 0.6us,
* max Trise=0.3us, max Tfall=0.3us. Since ratio is 6:3, have to use
* worst case value of Tlow or 2xThigh as base.
*
* 1/(Tlow + Thigh + 0.3us + 0.3us) = 1/(1.3 + 0.65 + 0.6)us = 392157Hz
*/
#define I2C_FREQ_FAST_MAX 392157
/**
* @brief
* Fast mode+ max frequency assuming using 11:6 ratio for Nlow:Nhigh.
* @details
* From I2C specification: Min Tlow = 0.5us, min Thigh = 0.26us,
* max Trise=0.12us, max Tfall=0.12us. Since ratio is 11:6, have to use
* worst case value of Tlow or (11/6)xThigh as base.
*
* 1/(Tlow + Thigh + 0.12us + 0.12us) = 1/(0.5 + 0.273 + 0.24)us = 987167Hz
*/
#define I2C_FREQ_FASTPLUS_MAX 987167
/**
* @brief
* Indicate plain write sequence: S+ADDR(W)+DATA0+P.
* @details
* @li S - Start
* @li ADDR(W) - address with W/R bit cleared
* @li DATA0 - Data taken from buffer with index 0
* @li P - Stop
*/
#define I2C_FLAG_WRITE 0x0001
/**
* @brief
* Indicate plain read sequence: S+ADDR(R)+DATA0+P.
* @details
* @li S - Start
* @li ADDR(R) - Address with W/R bit set
* @li DATA0 - Data read into buffer with index 0
* @li P - Stop
*/
#define I2C_FLAG_READ 0x0002
/**
* @brief
* Indicate combined write/read sequence: S+ADDR(W)+DATA0+Sr+ADDR(R)+DATA1+P.
* @details
* @li S - Start
* @li Sr - Repeated start
* @li ADDR(W) - Address with W/R bit cleared
* @li ADDR(R) - Address with W/R bit set
* @li DATAn - Data written from/read into buffer with index n
* @li P - Stop
*/
#define I2C_FLAG_WRITE_READ 0x0004
/**
* @brief
* Indicate write sequence using two buffers: S+ADDR(W)+DATA0+DATA1+P.
* @details
* @li S - Start
* @li ADDR(W) - Address with W/R bit cleared
* @li DATAn - Data written from buffer with index n
* @li P - Stop
*/
#define I2C_FLAG_WRITE_WRITE 0x0008
/** Use 10 bit address. */
#define I2C_FLAG_10BIT_ADDR 0x0010
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/** Clock low to high ratio settings. */
typedef enum {
i2cClockHLRStandard = _I2C_CTRL_CLHR_STANDARD, /**< Ratio is 4:4 */
i2cClockHLRAsymetric = _I2C_CTRL_CLHR_ASYMMETRIC, /**< Ratio is 6:3 */
i2cClockHLRFast = _I2C_CTRL_CLHR_FAST /**< Ratio is 11:3 */
} I2C_ClockHLR_TypeDef;
/** Return codes for single Controller mode transfer function. */
typedef enum {
/* In progress code (>0) */
i2cTransferInProgress = 1, /**< Transfer in progress. */
/* Complete code (=0) */
i2cTransferDone = 0, /**< Transfer completed successfully. */
/* Transfer error codes (<0). */
i2cTransferNack = -1, /**< NACK received during transfer. */
i2cTransferBusErr = -2, /**< Bus error during transfer (misplaced START/STOP). */
i2cTransferArbLost = -3, /**< Arbitration lost during transfer. */
i2cTransferUsageFault = -4, /**< Usage fault. */
i2cTransferSwFault = -5 /**< SW fault. */
} I2C_TransferReturn_TypeDef;
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/** I2C initialization structure. */
typedef struct {
/** Enable I2C peripheral when initialization completed. */
bool enable;
/** Set to Controller (true) or Target (false) mode */
bool master;
/**
* I2C reference clock assumed when configuring bus frequency setup.
* Set it to 0 if currently configured reference clock will be used
* This parameter is only applicable if operating in Controller mode.
*/
uint32_t refFreq;
/**
* (Max) I2C bus frequency to use. This parameter is only applicable
* if operating in Controller mode.
*/
uint32_t freq;
/** Clock low/high ratio control. */
I2C_ClockHLR_TypeDef clhr;
} I2C_Init_TypeDef;
/** Suggested default configuration for I2C initialization structure. */
#define I2C_INIT_DEFAULT \
{ \
true, /* Enable when initialization done. */ \
true, /* Set to Controller mode. */ \
0, /* Use currently configured reference clock. */ \
I2C_FREQ_STANDARD_MAX, /* Set to standard rate assuring being */ \
/* within I2C specification. */ \
i2cClockHLRStandard /* Set to use 4:4 low/high duty cycle. */ \
}
/**
* @brief
* Master mode transfer message structure used to define a complete
* I2C transfer sequence (from start to stop).
* @details
* The structure allows for defining the following types of sequences
* (refer to defines for sequence details):
* @li #I2C_FLAG_READ - Data read into buf[0].data
* @li #I2C_FLAG_WRITE - Data written from buf[0].data
* @li #I2C_FLAG_WRITE_READ - Data written from buf[0].data and read
* into buf[1].data
* @li #I2C_FLAG_WRITE_WRITE - Data written from buf[0].data and
* buf[1].data
*/
typedef struct {
/**
* @brief
* Address to use after (repeated) start.
* @details
* Layout details, A = Address bit, X = don't care bit (set to 0):
* @li 7 bit address - Use format AAAA AAAX
* @li 10 bit address - Use format XXXX XAAX AAAA AAAA
*/
uint16_t addr;
/** Flags defining sequence type and details, see I2C_FLAG_ defines. */
uint16_t flags;
/**
* Buffers used to hold data to send from or receive into, depending
* on sequence type.
*/
struct {
/** Buffer used for data to transmit/receive, must be @p len long. */
uint8_t *data;
/**
* Number of bytes in @p data to send or receive. Notice that when
* receiving data to this buffer, at least 1 byte must be received.
* Setting @p len to 0 in the receive case is considered a usage fault.
* Transmitting 0 bytes is legal, in which case only the address
* is transmitted after the start condition.
*/
uint16_t len;
} buf[2];
} I2C_TransferSeq_TypeDef;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
uint32_t I2C_BusFreqGet(I2C_TypeDef *i2c);
void I2C_BusFreqSet(I2C_TypeDef *i2c,
uint32_t freqRef,
uint32_t freqScl,
I2C_ClockHLR_TypeDef i2cMode);
void I2C_Enable(I2C_TypeDef *i2c, bool enable);
void I2C_Init(I2C_TypeDef *i2c, const I2C_Init_TypeDef *init);
/***************************************************************************//**
* @brief
* Clear one or more pending I2C interrupts.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] flags
* Pending I2C interrupt source to clear. Use a bitwise logic OR combination of
* valid interrupt flags for the I2C module (I2C_IF_nnn).
******************************************************************************/
__STATIC_INLINE void I2C_IntClear(I2C_TypeDef *i2c, uint32_t flags)
{
#if defined (I2C_HAS_SET_CLEAR)
i2c->IF_CLR = flags;
#else
i2c->IFC = flags;
#endif
}
/***************************************************************************//**
* @brief
* Disable one or more I2C interrupts.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] flags
* I2C interrupt sources to disable. Use a bitwise logic OR combination of
* valid interrupt flags for the I2C module (I2C_IF_nnn).
******************************************************************************/
__STATIC_INLINE void I2C_IntDisable(I2C_TypeDef *i2c, uint32_t flags)
{
#if defined (I2C_HAS_SET_CLEAR)
i2c->IEN_CLR = flags;
#else
i2c->IEN &= ~(flags);
#endif
}
/***************************************************************************//**
* @brief
* Enable one or more I2C interrupts.
*
* @note
* Depending on the use, a pending interrupt may already be set prior to
* enabling the interrupt. To ignore a pending interrupt, consider using
* I2C_IntClear() prior to enabling the interrupt.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] flags
* I2C interrupt sources to enable. Use a bitwise logic OR combination of
* valid interrupt flags for the I2C module (I2C_IF_nnn).
******************************************************************************/
__STATIC_INLINE void I2C_IntEnable(I2C_TypeDef *i2c, uint32_t flags)
{
#if defined (I2C_HAS_SET_CLEAR)
i2c->IEN_SET = flags;
#else
i2c->IEN |= flags;
#endif
}
/***************************************************************************//**
* @brief
* Get pending I2C interrupt flags.
*
* @note
* Event bits are not cleared by the use of this function.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @return
* I2C interrupt sources pending. A bitwise logic OR combination of valid
* interrupt flags for the I2C module (I2C_IF_nnn).
******************************************************************************/
__STATIC_INLINE uint32_t I2C_IntGet(I2C_TypeDef *i2c)
{
return i2c->IF;
}
/***************************************************************************//**
* @brief
* Get enabled and pending I2C interrupt flags.
* Useful for handling more interrupt sources in the same interrupt handler.
*
* @note
* Interrupt flags are not cleared by the use of this function.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @return
* Pending and enabled I2C interrupt sources
* Return value is the bitwise AND of
* - the enabled interrupt sources in I2Cn_IEN and
* - the pending interrupt flags I2Cn_IF
******************************************************************************/
__STATIC_INLINE uint32_t I2C_IntGetEnabled(I2C_TypeDef *i2c)
{
uint32_t ien;
ien = i2c->IEN;
return i2c->IF & ien;
}
/***************************************************************************//**
* @brief
* Set one or more pending I2C interrupts from SW.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] flags
* I2C interrupt sources to set to pending. Use a bitwise logic OR combination
* of valid interrupt flags for the I2C module (I2C_IF_nnn).
******************************************************************************/
__STATIC_INLINE void I2C_IntSet(I2C_TypeDef *i2c, uint32_t flags)
{
#if defined (I2C_HAS_SET_CLEAR)
i2c->IF_SET = flags;
#else
i2c->IFS = flags;
#endif
}
void I2C_Reset(I2C_TypeDef *i2c);
/***************************************************************************//**
* @brief
* Get Target address used for I2C peripheral (when operating in Target mode).
*
* @details
* For 10-bit addressing mode, the address is split in two bytes, and only
* the first byte setting is fetched, effectively only controlling the 2 most
* significant bits of the 10-bit address. Full handling of 10-bit addressing
* in Target mode requires additional SW handling.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @return
* I2C Target address in use. The 7 most significant bits define the actual
* address, the least significant bit is reserved and always returned as 0.
******************************************************************************/
__STATIC_INLINE uint8_t I2C_SlaveAddressGet(I2C_TypeDef *i2c)
{
return ((uint8_t)(i2c->SADDR));
}
/***************************************************************************//**
* @brief
* Set Target address to use for I2C peripheral (when operating in Target mode).
*
* @details
* For 10- bit addressing mode, the address is split in two bytes, and only
* the first byte is set, effectively only controlling the 2 most significant
* bits of the 10-bit address. Full handling of 10-bit addressing in Target
* mode requires additional SW handling.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] addr
* I2C Target address to use. The 7 most significant bits define the actual
* address, the least significant bit is reserved and always set to 0.
******************************************************************************/
__STATIC_INLINE void I2C_SlaveAddressSet(I2C_TypeDef *i2c, uint8_t addr)
{
i2c->SADDR = (uint32_t)addr & 0xfe;
}
/***************************************************************************//**
* @brief
* Get Target address mask used for I2C peripheral (when operating in Target
* mode).
*
* @details
* The address mask defines how the comparator works. A bit position with
* value 0 means that the corresponding Target address bit is ignored during
* comparison (don't care). A bit position with value 1 means that the
* corresponding Target address bit must match.
*
* For 10-bit addressing mode, the address is split in two bytes, and only
* the mask for the first address byte is fetched, effectively only
* controlling the 2 most significant bits of the 10-bit address.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @return
* I2C Target address mask in use. The 7 most significant bits define the
* actual address mask, the least significant bit is reserved and always
* returned as 0.
******************************************************************************/
__STATIC_INLINE uint8_t I2C_SlaveAddressMaskGet(I2C_TypeDef *i2c)
{
return ((uint8_t)(i2c->SADDRMASK));
}
/***************************************************************************//**
* @brief
* Set Target address mask used for I2C peripheral (when operating in Target
* mode).
*
* @details
* The address mask defines how the comparator works. A bit position with
* value 0 means that the corresponding Target address bit is ignored during
* comparison (don't care). A bit position with value 1 means that the
* corresponding Target address bit must match.
*
* For 10-bit addressing mode, the address is split in two bytes, and only
* the mask for the first address byte is set, effectively only controlling
* the 2 most significant bits of the 10-bit address.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] mask
* I2C Target address mask to use. The 7 most significant bits define the
* actual address mask, the least significant bit is reserved and should
* be 0.
******************************************************************************/
__STATIC_INLINE void I2C_SlaveAddressMaskSet(I2C_TypeDef *i2c, uint8_t mask)
{
i2c->SADDRMASK = (uint32_t)mask & 0xfe;
}
I2C_TransferReturn_TypeDef I2C_Transfer(I2C_TypeDef *i2c);
I2C_TransferReturn_TypeDef I2C_TransferInit(I2C_TypeDef *i2c,
I2C_TransferSeq_TypeDef *seq);
/** @} (end addtogroup i2c) */
#ifdef __cplusplus
}
#endif
#endif /* defined(I2C_COUNT) && (I2C_COUNT > 0) */
#endif /* EM_I2C_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,334 @@
/***************************************************************************//**
* @file
* @brief Low Energy Timer (LETIMER) peripheral API
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_LETIMER_H
#define EM_LETIMER_H
#include <stdbool.h>
#include "em_device.h"
#if defined(LETIMER_COUNT) && (LETIMER_COUNT > 0)
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup letimer
* @{
******************************************************************************/
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/** Repeat mode. */
typedef enum {
/** Count until stopped by SW. */
letimerRepeatFree = _LETIMER_CTRL_REPMODE_FREE,
/** Count REP0 times. */
letimerRepeatOneshot = _LETIMER_CTRL_REPMODE_ONESHOT,
/**
* Count REP0 times, if REP1 has been written to, it is loaded into
* REP0 when REP0 is about to be decremented to 0.
*/
letimerRepeatBuffered = _LETIMER_CTRL_REPMODE_BUFFERED,
/**
* Run as long as both REP0 and REP1 are not 0. Both REP0 and REP1
* are decremented when counter underflows.
*/
letimerRepeatDouble = _LETIMER_CTRL_REPMODE_DOUBLE
} LETIMER_RepeatMode_TypeDef;
/** Underflow action on output. */
typedef enum {
/** No output action. */
letimerUFOANone = _LETIMER_CTRL_UFOA0_NONE,
/** Toggle output when counter underflows. */
letimerUFOAToggle = _LETIMER_CTRL_UFOA0_TOGGLE,
/** Hold output one LETIMER clock cycle when counter underflows. */
letimerUFOAPulse = _LETIMER_CTRL_UFOA0_PULSE,
/** Set output idle when counter underflows, and active when matching COMP1. */
letimerUFOAPwm = _LETIMER_CTRL_UFOA0_PWM
} LETIMER_UFOA_TypeDef;
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/** LETIMER initialization structure. */
typedef struct {
bool enable; /**< Start counting when initialization completes. */
bool debugRun; /**< Counter shall keep running during debug halt. */
#if defined(LETIMER_CTRL_RTCC0TEN)
bool rtcComp0Enable; /**< Start counting on RTC COMP0 match. */
bool rtcComp1Enable; /**< Start counting on RTC COMP1 match. */
#endif
bool comp0Top; /**< Load COMP0 register into CNT when counter underflows. */
bool bufTop; /**< Load COMP1 into COMP0 when REP0 reaches 0. */
uint8_t out0Pol; /**< Idle value for output 0. */
uint8_t out1Pol; /**< Idle value for output 1. */
LETIMER_UFOA_TypeDef ufoa0; /**< Underflow output 0 action. */
LETIMER_UFOA_TypeDef ufoa1; /**< Underflow output 1 action. */
LETIMER_RepeatMode_TypeDef repMode; /**< Repeat mode. */
uint32_t topValue; /**< Top value. Counter wraps when top value matches counter value is reached. */
} LETIMER_Init_TypeDef;
/** Default configuration for LETIMER initialization structure. */
#if defined(LETIMER_CTRL_RTCC0TEN)
#define LETIMER_INIT_DEFAULT \
{ \
true, /* Enable timer when initialization completes. */ \
false, /* Stop counter during debug halt. */ \
false, /* Do not start counting on RTC COMP0 match. */ \
false, /* Do not start counting on RTC COMP1 match. */ \
false, /* Do not load COMP0 into CNT on underflow. */ \
false, /* Do not load COMP1 into COMP0 when REP0 reaches 0. */ \
0, /* Idle value 0 for output 0. */ \
0, /* Idle value 0 for output 1. */ \
letimerUFOANone, /* No action on underflow on output 0. */ \
letimerUFOANone, /* No action on underflow on output 1. */ \
letimerRepeatFree, /* Count until stopped by SW. */ \
0 /* Use default top Value. */ \
}
#else
#define LETIMER_INIT_DEFAULT \
{ \
true, /* Enable timer when initialization completes. */ \
false, /* Stop counter during debug halt. */ \
false, /* Do not load COMP0 into CNT on underflow. */ \
false, /* Do not load COMP1 into COMP0 when REP0 reaches 0. */ \
0, /* Idle value 0 for output 0. */ \
0, /* Idle value 0 for output 1. */ \
letimerUFOANone, /* No action on underflow on output 0. */ \
letimerUFOANone, /* No action on underflow on output 1. */ \
letimerRepeatFree, /* Count until stopped by SW. */ \
0 /* Use default top Value. */ \
}
#endif
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
uint32_t LETIMER_CompareGet(LETIMER_TypeDef *letimer, unsigned int comp);
void LETIMER_CompareSet(LETIMER_TypeDef *letimer,
unsigned int comp,
uint32_t value);
uint32_t LETIMER_CounterGet(LETIMER_TypeDef *letimer);
#if !defined(_EFM32_GECKO_FAMILY)
void LETIMER_CounterSet(LETIMER_TypeDef *letimer, uint32_t value);
#endif
void LETIMER_Enable(LETIMER_TypeDef *letimer, bool enable);
#if defined(_LETIMER_FREEZE_MASK)
void LETIMER_FreezeEnable(LETIMER_TypeDef *letimer, bool enable);
#endif
void LETIMER_Init(LETIMER_TypeDef *letimer, const LETIMER_Init_TypeDef *init);
/***************************************************************************//**
* @brief
* Clear one or more pending LETIMER interrupts.
*
* @param[in] letimer
* Pointer to LETIMER peripheral register block.
*
* @param[in] flags
* Pending LETIMER interrupt source to clear. Use a bitwise logic OR
* combination of valid interrupt flags for the LETIMER module
* (LETIMER_IF_nnn).
******************************************************************************/
__STATIC_INLINE void LETIMER_IntClear(LETIMER_TypeDef *letimer, uint32_t flags)
{
#if defined (LETIMER_HAS_SET_CLEAR)
letimer->IF_CLR = flags;
#else
letimer->IFC = flags;
#endif
}
/***************************************************************************//**
* @brief
* Disable one or more LETIMER interrupts.
*
* @param[in] letimer
* Pointer to LETIMER peripheral register block.
*
* @param[in] flags
* LETIMER interrupt sources to disable. Use a bitwise logic OR combination of
* valid interrupt flags for the LETIMER module (LETIMER_IF_nnn).
******************************************************************************/
__STATIC_INLINE void LETIMER_IntDisable(LETIMER_TypeDef *letimer, uint32_t flags)
{
letimer->IEN &= ~flags;
}
/***************************************************************************//**
* @brief
* Enable one or more LETIMER interrupts.
*
* @note
* Depending on the use, a pending interrupt may already be set prior to
* enabling the interrupt. To ignore a pending interrupt, consider using
* LETIMER_IntClear() prior to enabling the interrupt.
*
* @param[in] letimer
* Pointer to the LETIMER peripheral register block.
*
* @param[in] flags
* LETIMER interrupt sources to enable. Use a bitwise logic OR combination of
* valid interrupt flags for the LETIMER module (LETIMER_IF_nnn).
******************************************************************************/
__STATIC_INLINE void LETIMER_IntEnable(LETIMER_TypeDef *letimer, uint32_t flags)
{
letimer->IEN |= flags;
}
/***************************************************************************//**
* @brief
* Get pending LETIMER interrupt flags.
*
* @note
* Event bits are not cleared by the use of this function.
*
* @param[in] letimer
* Pointer to LETIMER peripheral register block.
*
* @return
* LETIMER interrupt sources pending. A bitwise logic OR combination of
* valid interrupt flags for the LETIMER module (LETIMER_IF_nnn).
******************************************************************************/
__STATIC_INLINE uint32_t LETIMER_IntGet(LETIMER_TypeDef *letimer)
{
return letimer->IF;
}
/***************************************************************************//**
* @brief
* Get enabled and pending LETIMER interrupt flags.
*
* @details
* Useful for handling more interrupt sources in the same interrupt handler.
*
* @note
* Event bits are not cleared by the use of this function.
*
* @param[in] letimer
* Pointer to LETIMER peripheral register block.
*
* @return
* Pending and enabled LETIMER interrupt sources.
* Return value is the bitwise AND combination of
* - the OR combination of enabled interrupt sources in LETIMER_IEN_nnn
* register (LETIMER_IEN_nnn) and
* - the OR combination of valid interrupt flags of the LETIMER module
* (LETIMER_IF_nnn).
******************************************************************************/
__STATIC_INLINE uint32_t LETIMER_IntGetEnabled(LETIMER_TypeDef *letimer)
{
uint32_t ien;
/* Store flags in temporary variable in order to define explicit order
* of volatile accesses. */
ien = letimer->IEN;
/* Bitwise AND of pending and enabled interrupts */
return letimer->IF & ien;
}
/***************************************************************************//**
* @brief
* Set one or more pending LETIMER interrupts from SW.
*
* @param[in] letimer
* Pointer to LETIMER peripheral register block.
*
* @param[in] flags
* LETIMER interrupt sources to set to pending. Use a bitwise logic OR
* combination of valid interrupt flags for the LETIMER module (LETIMER_IF_nnn).
******************************************************************************/
__STATIC_INLINE void LETIMER_IntSet(LETIMER_TypeDef *letimer, uint32_t flags)
{
#if defined (LETIMER_HAS_SET_CLEAR)
letimer->IF_SET = flags;
#else
letimer->IFS = flags;
#endif
}
#if defined(_LETIMER_LOCK_MASK)
/***************************************************************************//**
* @brief
* Lock LETIMER registers.
*
* @param[in] letimer
* Pointer to LETIMER peripheral register block.
*
* @note When LETIMER registers are locked LETIMER_EN, LETIMER_SWRST,
* LETIMER_CTRL, LETIMER_CMD, LETIMER_CNT, LETIMER_COMPx,
* LETIMER_TOP, LETIMER_TOPBUFF, LETIMER_REPx, and PRSMODE registers
* cannot be written to.
******************************************************************************/
__STATIC_INLINE void LETIMER_Lock(LETIMER_TypeDef *letimer)
{
letimer->LOCK = ~LETIMER_LOCK_LETIMERLOCKKEY_UNLOCK;
}
#endif
#if defined(_LETIMER_LOCK_MASK)
/***************************************************************************//**
* @brief
* Unlock LETIMER registers.
*
* @param[in] letimer
* Pointer to LETIMER peripheral register block.
******************************************************************************/
__STATIC_INLINE void LETIMER_Unlock(LETIMER_TypeDef *letimer)
{
letimer->LOCK = LETIMER_LOCK_LETIMERLOCKKEY_UNLOCK;
}
#endif
uint32_t LETIMER_RepeatGet(LETIMER_TypeDef *letimer, unsigned int rep);
void LETIMER_RepeatSet(LETIMER_TypeDef *letimer,
unsigned int rep,
uint32_t value);
void LETIMER_Reset(LETIMER_TypeDef *letimer);
void LETIMER_SyncWait(LETIMER_TypeDef *letimer);
void LETIMER_TopSet(LETIMER_TypeDef *letimer, uint32_t value);
uint32_t LETIMER_TopGet(LETIMER_TypeDef *letimer);
/** @} (end addtogroup letimer) */
#ifdef __cplusplus
}
#endif
#endif /* defined(LETIMER_COUNT) && (LETIMER_COUNT > 0) */
#endif /* EM_LETIMER_H */

View File

@@ -0,0 +1,889 @@
/***************************************************************************//**
* @file
* @brief Flash Controller (MSC) Peripheral API
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_MSC_H
#define EM_MSC_H
#include "em_device.h"
#if defined(MSC_COUNT) && (MSC_COUNT > 0)
#include <stdint.h>
#include <stdbool.h>
#include "em_bus.h"
#include "em_msc_compat.h"
#include "em_ramfunc.h"
#include "sl_assert.h"
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
#include "sli_tz_ns_interface.h"
#include "sli_tz_service_msc.h"
#include "sli_tz_s_interface.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup msc MSC - Memory System Controller
* @brief Memory System Controller API
* @details
* Contains functions to control the MSC, primarily the Flash.
* Users can perform Flash memory write and erase operations, as well as
* optimization of the CPU instruction fetch interface for the application.
* Available instruction fetch features depends on the MCU or SoC family, but
* features such as instruction pre-fetch, cache, and configurable branch prediction
* are typically available.
*
* @note Flash wait-state configuration is handled by @ref cmu.
* When core clock configuration is changed by a call to functions such as
* CMU_ClockSelectSet() or CMU_HFRCOBandSet(), then Flash wait-state
* configuration is also updated.
*
* MSC resets into a safe state. To initialize the instruction interface
* to recommended settings:
* @include em_msc_init_exec.c
*
* @note The optimal configuration is highly application dependent. Performance
* benchmarking is supported by most families. See MSC_StartCacheMeasurement()
* and MSC_GetCacheMeasurement() for more details.
*
* @note
* The flash write and erase runs from RAM on the EFM32G devices. On all other
* devices the flash write and erase functions run from flash.
*
* @note
* Flash erase may add ms of delay to interrupt latency if executing from Flash.
*
* Flash write and erase operations are supported by @ref MSC_WriteWord(),
* @ref MSC_ErasePage(), and MSC_MassErase().
* Mass erase is supported for MCU and SoC families with larger Flash sizes.
*
* @note
* @ref MSC_Init() must be called prior to any Flash write or erase operation.
*
* The following steps are necessary to perform a page erase and write:
* @include em_msc_erase_write.c
*
* @deprecated
* The configuration called EM_MSC_RUN_FROM_FLASH is deprecated. This was
* previously used for allocating the flash write functions in either flash
* or RAM.
*
* @note
* The configuration EM_MSC_RUN_FROM_RAM is used to allocate the flash
* write functions in RAM. By default, flash write
* functions are placed in RAM on EFM32G and Series 2 devices
* unless SL_RAMFUNC_DISABLE is defined. For other devices,
* flash write functions are placed in FLASH by default unless
* EM_MSC_RUN_FROM_RAM is defined and SL_RAMFUNC_DISABLE is not defined.
*
* @deprecated
* The function called MSC_WriteWordFast() is deprecated.
*
* @{
******************************************************************************/
/*******************************************************************************
************************* DEFINES *****************************************
******************************************************************************/
/**
* @brief
* Timeout used while waiting for Flash to become ready after a write.
* This number indicates the number of iterations to perform before
* issuing a timeout.
*
* @note
* Timeout is set very large (in the order of 100x longer than
* necessary). This is to avoid any corner case.
*/
#define MSC_PROGRAM_TIMEOUT 10000000UL
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
#if (defined(_EFM32_GECKO_FAMILY) \
|| defined(_SILICON_LABS_32B_SERIES_2) \
|| defined(EM_MSC_RUN_FROM_RAM)) \
&& !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
#define MSC_RAMFUNC_DECLARATOR SL_RAMFUNC_DECLARATOR
#define MSC_RAMFUNC_DEFINITION_BEGIN SL_RAMFUNC_DEFINITION_BEGIN
#define MSC_RAMFUNC_DEFINITION_END SL_RAMFUNC_DEFINITION_END
#else
#define MSC_RAMFUNC_DECLARATOR
#define MSC_RAMFUNC_DEFINITION_BEGIN
#define MSC_RAMFUNC_DEFINITION_END
#endif
/** @endcond */
/*******************************************************************************
************************* TYPEDEFS ****************************************
******************************************************************************/
/** Return codes for writing/erasing Flash. */
typedef enum {
mscReturnOk = 0, /**< Flash write/erase successful. */
mscReturnInvalidAddr = -1, /**< Invalid address. Write to an address that is not Flash. */
mscReturnLocked = -2, /**< Flash address is locked. */
mscReturnTimeOut = -3, /**< Timeout while writing to Flash. */
mscReturnUnaligned = -4 /**< Unaligned access to Flash. */
} MSC_Status_TypeDef;
#if defined(_MSC_READCTRL_BUSSTRATEGY_MASK)
/** Strategy for prioritized bus access. */
typedef enum {
mscBusStrategyCPU = MSC_READCTRL_BUSSTRATEGY_CPU, /**< Prioritize CPU bus accesses. */
mscBusStrategyDMA = MSC_READCTRL_BUSSTRATEGY_DMA, /**< Prioritize DMA bus accesses. */
mscBusStrategyDMAEM1 = MSC_READCTRL_BUSSTRATEGY_DMAEM1, /**< Prioritize DMAEM1 for bus accesses. */
mscBusStrategyNone = MSC_READCTRL_BUSSTRATEGY_NONE /**< No unit has bus priority. */
} MSC_BusStrategy_Typedef;
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_MASK)
/** AHBHOST masters that can use alternate MPAHBRAM ports. */
typedef enum {
mscDmemMasterLDMA = _SYSCFG_DMEM0PORTMAPSEL_LDMAPORTSEL_SHIFT,
mscDmemMasterSRWAES = _SYSCFG_DMEM0PORTMAPSEL_SRWAESPORTSEL_SHIFT,
mscDmemMasterAHBSRW = _SYSCFG_DMEM0PORTMAPSEL_AHBSRWPORTSEL_SHIFT,
#if defined(_SYSCFG_DMEM0PORTMAPSEL_IFADCDEBUGPORTSEL_MASK)
mscDmemMasterIFADCDEBUG = _SYSCFG_DMEM0PORTMAPSEL_IFADCDEBUGPORTSEL_SHIFT,
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_SRWECA0PORTSEL_MASK)
mscDmemMasterSRWECA0 = _SYSCFG_DMEM0PORTMAPSEL_SRWECA0PORTSEL_SHIFT,
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_SRWECA1PORTSEL_MASK)
mscDmemMasterSRWECA1 = _SYSCFG_DMEM0PORTMAPSEL_SRWECA1PORTSEL_SHIFT,
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA0PORTSEL_MASK)
mscDmemMasterMVPAHBDATA0 = _SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA0PORTSEL_SHIFT,
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA1PORTSEL_MASK)
mscDmemMasterMVPAHBDATA1 = _SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA1PORTSEL_SHIFT,
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA2PORTSEL_MASK)
mscDmemMasterMVPAHBDATA2 = _SYSCFG_DMEM0PORTMAPSEL_MVPAHBDATA2PORTSEL_SHIFT,
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_LDMA1PORTSEL_MASK)
mscDmemMasterLDMA1 = _SYSCFG_DMEM0PORTMAPSEL_LDMA1PORTSEL_SHIFT,
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_SRWLDMAPORTSEL_MASK)
mscDmemMasterSRWLDMA = _SYSCFG_DMEM0PORTMAPSEL_SRWLDMAPORTSEL_SHIFT,
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_USBPORTSEL_MASK)
mscDmemMasterUSB = _SYSCFG_DMEM0PORTMAPSEL_USBPORTSEL_SHIFT,
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_BUFCPORTSEL_MASK)
mscDmemMasterBUFC = _SYSCFG_DMEM0PORTMAPSEL_BUFCPORTSEL_SHIFT
#endif
} MSC_DmemMaster_TypeDef;
#endif
#if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_MASK)
/** AHB port given priority. */
typedef enum {
mscPortPriorityNone = _MPAHBRAM_CTRL_AHBPORTPRIORITY_NONE,
mscPortPriorityPort0 = _MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT0,
mscPortPriorityPort1 = _MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT1,
#if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT2)
mscPortPriorityPort2 = _MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT2,
#endif
#if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT3)
mscPortPriorityPort3 = _MPAHBRAM_CTRL_AHBPORTPRIORITY_PORT3,
#endif
} MSC_PortPriority_TypeDef;
#endif
#if defined(MSC_READCTRL_DOUTBUFEN) || defined(MSC_RDATACTRL_DOUTBUFEN)
/** Code execution configuration */
typedef struct {
bool doutBufEn; /**< Flash dout pipeline buffer enable */
} MSC_ExecConfig_TypeDef;
/** Default MSC ExecConfig initialization */
#define MSC_EXECCONFIG_DEFAULT \
{ \
false, \
}
#else
/** Code execution configuration. */
typedef struct {
bool scbtEn; /**< Enable Suppressed Conditional Branch Target Prefetch. */
bool prefetchEn; /**< Enable MSC prefetching. */
bool ifcDis; /**< Disable instruction cache. */
bool aiDis; /**< Disable automatic cache invalidation on write or erase. */
bool iccDis; /**< Disable automatic caching of fetches in interrupt context. */
bool useHprot; /**< Use ahb_hprot to determine if the instruction is cacheable or not. */
} MSC_ExecConfig_TypeDef;
/** Default MSC ExecConfig initialization. */
#define MSC_EXECCONFIG_DEFAULT \
{ \
false, \
true, \
false, \
false, \
false, \
false, \
}
#endif
#if defined(_MSC_ECCCTRL_MASK) \
|| defined(_SYSCFG_DMEM0ECCCTRL_MASK) \
|| defined(_MPAHBRAM_CTRL_MASK)
#if defined(_SILICON_LABS_32B_SERIES_1_CONFIG_1)
/** EFM32GG11B incorporates 2 memory banks including ECC support. */
#define MSC_ECC_BANKS (2)
/** Default MSC EccConfig initialization. */
#define MSC_ECCCONFIG_DEFAULT \
{ \
{ false, false }, \
{ 0, 1 }, \
}
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_106)
/** EFM32GG12B incorporates 3 memory banks including ECC support. */
#define MSC_ECC_BANKS (3)
/** Default MSC EccConfig initialization. */
#define MSC_ECCCONFIG_DEFAULT \
{ \
{ false, false, false }, \
{ 0, 1 }, \
}
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
/** xG26 chips incorporate 2 memory banks including ECC support. */
#define MSC_ECC_BANKS (2)
/** Default MSC EccConfig initialization */
#define MSC_ECCCONFIG_DEFAULT \
{ \
{ false, false }, \
{ 0, 1 }, \
}
#elif defined(_SILICON_LABS_32B_SERIES_2)
/** Series 2 chips incorporate 1 memory bank including ECC support. */
#define MSC_ECC_BANKS (1)
/** Default MSC EccConfig initialization */
#define MSC_ECCCONFIG_DEFAULT \
{ \
{ false }, \
{ 0, 1 }, \
}
#else
#error Device not supported.
#endif
/** ECC configuration. */
typedef struct {
bool enableEccBank[MSC_ECC_BANKS]; /**< Array of bools to enable/disable
Error Correcting Code (ECC) for
each RAM bank that supports ECC on
the device. */
uint32_t dmaChannels[2]; /**< Array of 2 DMA channel numbers to
use for ECC initialization. */
} MSC_EccConfig_TypeDef;
#endif /* #if defined(_MSC_ECCCTRL_MASK) */
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/* Deprecated type names. */
#define mscBusStrategy_Typedef MSC_BusStrategy_Typedef
#define msc_Return_TypeDef MSC_Status_TypeDef
/** @endcond */
/*******************************************************************************
************************* Inline Functions ********************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Get the status of the MSC register lock.
*
* @return
* Boolean true if register lock is applied, false otherwise.
******************************************************************************/
__STATIC_INLINE bool MSC_LockGetLocked(void)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
return (bool)sli_tz_ns_interface_dispatch_simple_noarg(
(sli_tz_veneer_simple_noarg_fn)sli_tz_s_interface_dispatch_simple_no_args,
SLI_TZ_MSC_GET_LOCKED_SID);
#elif defined(_MSC_STATUS_REGLOCK_MASK)
return (MSC->STATUS & _MSC_STATUS_REGLOCK_MASK) != MSC_STATUS_REGLOCK_UNLOCKED;
#else
return (MSC->LOCK & _MSC_LOCK_MASK) != MSC_LOCK_LOCKKEY_UNLOCKED;
#endif
}
/***************************************************************************//**
* @brief
* Set the MSC register lock to a locked state.
******************************************************************************/
__STATIC_INLINE void MSC_LockSetLocked(void)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
(void)sli_tz_ns_interface_dispatch_simple_noarg(
(sli_tz_veneer_simple_noarg_fn)sli_tz_s_interface_dispatch_simple_no_args,
SLI_TZ_MSC_SET_LOCKED_SID);
#else
MSC->LOCK = MSC_LOCK_LOCKKEY_LOCK;
#endif
}
/***************************************************************************//**
* @brief
* Set the MSC register lock to an unlocked state.
******************************************************************************/
__STATIC_INLINE void MSC_LockSetUnlocked(void)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
(void)sli_tz_ns_interface_dispatch_simple_noarg(
(sli_tz_veneer_simple_noarg_fn)sli_tz_s_interface_dispatch_simple_no_args,
SLI_TZ_MSC_SET_UNLOCKED_SID);
#else
MSC->LOCK = MSC_LOCK_LOCKKEY_UNLOCK;
#endif
}
/***************************************************************************//**
* @brief
* Get the current value of the read control register (MSC_READCTRL).
*
* @return
* The 32-bit value read from the MSC_READCTRL register.
******************************************************************************/
__STATIC_INLINE uint32_t MSC_ReadCTRLGet(void)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
return sli_tz_ns_interface_dispatch_simple_noarg(
(sli_tz_veneer_simple_noarg_fn)sli_tz_s_interface_dispatch_simple_no_args,
SLI_TZ_MSC_GET_READCTRL_SID);
#else
return MSC->READCTRL;
#endif
}
/***************************************************************************//**
* @brief
* Write a value to the read control register (MSC_READCTRL).
*
* @param[in] value
* The 32-bit value to write to the MSC_READCTRL register.
******************************************************************************/
__STATIC_INLINE void MSC_ReadCTRLSet(uint32_t value)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
(void)sli_tz_ns_interface_dispatch_simple(
(sli_tz_veneer_simple_fn)sli_tz_s_interface_dispatch_simple,
SLI_TZ_MSC_SET_READCTRL_SID,
value);
#else
MSC->READCTRL = value;
#endif
}
#if defined(_MSC_PAGELOCK0_MASK) || defined(_MSC_INST_PAGELOCKWORD0_MASK)
/***************************************************************************//**
* @brief
* Set the lockbit for a flash page in order to prevent page writes/erases to
* the corresponding page.
*
* @param[in] page_number
* The index of the page to apply the pagelock to. Must be in the range
* [0, (flash_size / page_size) - 1].
******************************************************************************/
__STATIC_INLINE void MSC_PageLockSetLocked(uint32_t page_number)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
(void)sli_tz_ns_interface_dispatch_simple(
(sli_tz_veneer_simple_fn)sli_tz_s_interface_dispatch_simple,
SLI_TZ_MSC_SET_PAGELOCK_SID,
page_number);
#else
EFM_ASSERT(page_number < (FLASH_SIZE / FLASH_PAGE_SIZE));
#if defined(_MSC_PAGELOCK0_MASK)
uint32_t *pagelock_registers = (uint32_t *)&MSC->PAGELOCK0;
#elif defined(_MSC_INST_PAGELOCKWORD0_MASK)
uint32_t *pagelock_registers = (uint32_t *)&MSC->INST_PAGELOCKWORD0;
#endif
pagelock_registers[page_number / 32] |= (1 << (page_number % 32));
#endif
}
/***************************************************************************//**
* @brief
* Get the value of the lockbit for a flash page.
*
* @param[in] page_number
* The index of the page to get the lockbit value from. Must be in the range
* [0, (flash_size / page_size) - 1].
*
* @return
* Boolean true if the page is locked, false otherwise.
******************************************************************************/
__STATIC_INLINE bool MSC_PageLockGetLocked(uint32_t page_number)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
return (bool)sli_tz_ns_interface_dispatch_simple(
(sli_tz_veneer_simple_fn)sli_tz_s_interface_dispatch_simple,
SLI_TZ_MSC_GET_PAGELOCK_SID,
page_number);
#else
EFM_ASSERT(page_number < (FLASH_SIZE / FLASH_PAGE_SIZE));
#if defined(_MSC_PAGELOCK0_MASK)
uint32_t *pagelock_registers = (uint32_t *)&MSC->PAGELOCK0;
#elif defined(_MSC_INST_PAGELOCKWORD0_MASK)
uint32_t *pagelock_registers = (uint32_t *)&MSC->INST_PAGELOCKWORD0;
#endif
return pagelock_registers[page_number / 32] & (1 << (page_number % 32));
#endif
}
#endif // _MSC_PAGELOCK0_MASK || _MSC_INST_PAGELOCKWORD0_MASK
#if defined(_MSC_USERDATASIZE_MASK)
/***************************************************************************//**
* @brief
* Get the size of the user data region in flash.
*
* @return
* The size of the user data region divided by 256.
******************************************************************************/
__STATIC_INLINE uint32_t MSC_UserDataGetSize(void)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
return sli_tz_ns_interface_dispatch_simple_noarg(
(sli_tz_veneer_simple_noarg_fn)sli_tz_s_interface_dispatch_simple_no_args,
SLI_TZ_MSC_GET_USERDATA_SIZE_SID);
#else
return MSC->USERDATASIZE;
#endif
}
#endif // _MSC_USERDATASIZE_MASK
#if defined(_MSC_MISCLOCKWORD_MASK)
/***************************************************************************//**
* @brief
* Get the current value of the mass erase and user data page lock word
* (MSC_MISCLOCKWORD).
*
* @return
* The 32-bit value read from the MSC_MISCLOCKWORD register.
******************************************************************************/
__STATIC_INLINE uint32_t MSC_MiscLockWordGet(void)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
return sli_tz_ns_interface_dispatch_simple_noarg(
(sli_tz_veneer_simple_noarg_fn)sli_tz_s_interface_dispatch_simple_no_args,
SLI_TZ_MSC_GET_MISCLOCKWORD_SID);
#else
return MSC->MISCLOCKWORD;
#endif
}
/***************************************************************************//**
* @brief
* Write a value to the mass erase and user data page lock word
* (MSC_MISCLOCKWORD).
*
* @param[in] value
* The 32-bit value to write to the MSC_MISCLOCKWORD register.
******************************************************************************/
__STATIC_INLINE void MSC_MiscLockWordSet(uint32_t value)
{
#if defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
(void)sli_tz_ns_interface_dispatch_simple(
(sli_tz_veneer_simple_fn)sli_tz_s_interface_dispatch_simple,
SLI_TZ_MSC_SET_MISCLOCKWORD_SID,
value);
#else
MSC->MISCLOCKWORD = value;
#endif
}
#endif // _MSC_USERDATASIZE_MASK
#if !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
/***************************************************************************//**
* @brief
* Clear one or more pending MSC interrupts.
*
* @param[in] flags
* Pending MSC interrupt source to clear. Use a bitwise logic OR combination
* of valid interrupt flags for the MSC module (MSC_IF_nnn).
******************************************************************************/
__STATIC_INLINE void MSC_IntClear(uint32_t flags)
{
#if defined(MSC_HAS_SET_CLEAR)
MSC->IF_CLR = flags;
#else
MSC->IFC = flags;
#endif
}
/***************************************************************************//**
* @brief
* Disable one or more MSC interrupts.
*
* @param[in] flags
* MSC interrupt sources to disable. Use a bitwise logic OR combination of
* valid interrupt flags for the MSC module (MSC_IF_nnn).
******************************************************************************/
__STATIC_INLINE void MSC_IntDisable(uint32_t flags)
{
#if defined(MSC_HAS_SET_CLEAR)
MSC->IEN_CLR = flags;
#else
MSC->IEN &= ~(flags);
#endif
}
/***************************************************************************//**
* @brief
* Enable one or more MSC interrupts.
*
* @note
* Depending on the use, a pending interrupt may already be set prior to
* enabling the interrupt. To ignore a pending interrupt, consider using
* MSC_IntClear() prior to enabling the interrupt.
*
* @param[in] flags
* MSC interrupt sources to enable. Use a bitwise logic OR combination of
* valid interrupt flags for the MSC module (MSC_IF_nnn).
******************************************************************************/
__STATIC_INLINE void MSC_IntEnable(uint32_t flags)
{
#if defined(MSC_HAS_SET_CLEAR)
MSC->IEN_SET = flags;
#else
MSC->IEN |= flags;
#endif
}
/***************************************************************************//**
* @brief
* Get pending MSC interrupt flags.
*
* @note
* The event bits are not cleared by the use of this function.
*
* @return
* MSC interrupt sources pending. A bitwise logic OR combination of valid
* interrupt flags for the MSC module (MSC_IF_nnn).
******************************************************************************/
__STATIC_INLINE uint32_t MSC_IntGet(void)
{
return MSC->IF;
}
/***************************************************************************//**
* @brief
* Get enabled and pending MSC interrupt flags.
* Useful for handling more interrupt sources in the same interrupt handler.
*
* @note
* Interrupt flags are not cleared by the use of this function.
*
* @return
* Pending and enabled MSC interrupt sources.
* The return value is the bitwise AND of
* - the enabled interrupt sources in MSC_IEN and
* - the pending interrupt flags MSC_IF
******************************************************************************/
__STATIC_INLINE uint32_t MSC_IntGetEnabled(void)
{
uint32_t ien;
ien = MSC->IEN;
return MSC->IF & ien;
}
/***************************************************************************//**
* @brief
* Set one or more pending MSC interrupts from SW.
*
* @param[in] flags
* MSC interrupt sources to set to pending. Use a bitwise logic OR combination of
* valid interrupt flags for the MSC module (MSC_IF_nnn).
******************************************************************************/
__STATIC_INLINE void MSC_IntSet(uint32_t flags)
{
#if defined(MSC_HAS_SET_CLEAR)
MSC->IF_SET = flags;
#else
MSC->IFS = flags;
#endif
}
#if defined(MSC_IF_CHOF) && defined(MSC_IF_CMOF)
/***************************************************************************//**
* @brief
* Start measuring the cache hit ratio.
* @details
* Starts performance counters. It is defined inline to
* minimize the impact of this code on the measurement itself.
******************************************************************************/
__STATIC_INLINE void MSC_StartCacheMeasurement(void)
{
/* Clear CMOF and CHOF to catch these later. */
MSC->IFC = MSC_IF_CHOF | MSC_IF_CMOF;
/* Start performance counters. */
#if defined(_MSC_CACHECMD_MASK)
MSC->CACHECMD = MSC_CACHECMD_STARTPC;
#else
MSC->CMD = MSC_CMD_STARTPC;
#endif
}
/***************************************************************************//**
* @brief
* Stop measuring the hit rate.
* @note
* Defined inline to minimize the impact of this
* code on the measurement itself.
* Only works for relatively short sections of code.
* To measure longer sections of code, implement an IRQ Handler for
* the CHOF and CMOF overflow interrupts. These overflows need to be
* counted and included in the total.
* Functions can then be implemented as follows:
* @verbatim
* volatile uint32_t hitOverflows
* volatile uint32_t missOverflows
*
* void MSC_IRQHandler(void)
* {
* uint32_t flags;
* flags = MSC->IF;
* if (flags & MSC_IF_CHOF) {
* MSC->IFC = MSC_IF_CHOF;
* hitOverflows++;
* }
* if (flags & MSC_IF_CMOF) {
* MSC->IFC = MSC_IF_CMOF;
* missOverflows++;
* }
* }
*
* void startPerformanceCounters(void)
* {
* hitOverflows = 0;
* missOverflows = 0;
*
* MSC_IntEnable(MSC_IF_CHOF | MSC_IF_CMOF);
* NVIC_EnableIRQ(MSC_IRQn);
*
* MSC_StartCacheMeasurement();
* }
* @endverbatim
* @return
* Returns -1 if there has been no cache accesses.
* Returns -2 if there has been an overflow in the performance counters.
* If not, it will return the percentage of hits versus misses.
******************************************************************************/
__STATIC_INLINE int32_t MSC_GetCacheMeasurement(void)
{
int32_t total;
int32_t hits;
/* Stop counter before computing hit-rate. */
#if defined(_MSC_CACHECMD_MASK)
MSC->CACHECMD = MSC_CACHECMD_STOPPC;
#else
MSC->CMD = MSC_CMD_STOPPC;
#endif
/* Check for overflows in performance counters. */
if (MSC->IF & (MSC_IF_CHOF | MSC_IF_CMOF)) {
return -2;
}
hits = (int32_t)MSC->CACHEHITS;
total = (int32_t)MSC->CACHEMISSES + hits;
/* To avoid a division by zero. */
if (total == 0) {
return -1;
}
return (hits * 100) / total;
}
/***************************************************************************//**
* @brief
* Flush contents of instruction cache.
******************************************************************************/
__STATIC_INLINE void MSC_FlushCache(void)
{
#if defined(_MSC_CACHECMD_MASK)
MSC->CACHECMD = MSC_CACHECMD_INVCACHE;
#else
MSC->CMD = MSC_CMD_INVCACHE;
#endif
}
/***************************************************************************//**
* @brief
* Enable or disable instruction cache functionality.
* @param[in] enable
* Enable instruction cache. Default is on.
******************************************************************************/
__STATIC_INLINE void MSC_EnableCache(bool enable)
{
BUS_RegBitWrite(&(MSC->READCTRL), _MSC_READCTRL_IFCDIS_SHIFT, !enable);
}
#if defined(MSC_READCTRL_ICCDIS)
/***************************************************************************//**
* @brief
* Enable or disable instruction cache functionality in IRQs.
* @param[in] enable
* Enable instruction cache. Default is on.
******************************************************************************/
__STATIC_INLINE void MSC_EnableCacheIRQs(bool enable)
{
BUS_RegBitWrite(&(MSC->READCTRL), _MSC_READCTRL_ICCDIS_SHIFT, !enable);
}
#endif
/***************************************************************************//**
* @brief
* Enable or disable instruction cache flushing when writing to flash.
* @param[in] enable
* Enable automatic cache flushing. Default is on.
******************************************************************************/
__STATIC_INLINE void MSC_EnableAutoCacheFlush(bool enable)
{
BUS_RegBitWrite(&(MSC->READCTRL), _MSC_READCTRL_AIDIS_SHIFT, !enable);
}
#endif /* defined( MSC_IF_CHOF ) && defined( MSC_IF_CMOF ) */
#if defined(_MSC_READCTRL_BUSSTRATEGY_MASK)
/***************************************************************************//**
* @brief
* Configure which unit should get priority on system bus.
* @param[in] mode
* Unit to prioritize bus accesses for.
******************************************************************************/
__STATIC_INLINE void MSC_BusStrategy(mscBusStrategy_Typedef mode)
{
MSC->READCTRL = (MSC->READCTRL & ~(_MSC_READCTRL_BUSSTRATEGY_MASK)) | mode;
}
#endif
/*******************************************************************************
************************* PROTOTYPES **************************************
******************************************************************************/
void MSC_ExecConfigSet(MSC_ExecConfig_TypeDef *execConfig);
#if defined(_MSC_ECCCTRL_MASK) \
|| defined(_SYSCFG_DMEM0ECCCTRL_MASK) \
|| defined(_MPAHBRAM_CTRL_MASK)
void MSC_EccConfigSet(MSC_EccConfig_TypeDef *eccConfig);
#endif
#if defined(_SYSCFG_DMEM0PORTMAPSEL_MASK)
void MSC_DmemPortMapSet(MSC_DmemMaster_TypeDef master, uint8_t port);
#endif
#if defined(_MPAHBRAM_CTRL_AHBPORTPRIORITY_MASK)
void MSC_PortSetPriority(MSC_PortPriority_TypeDef portPriority);
MSC_PortPriority_TypeDef MSC_PortGetCurrentPriority(void);
#endif
#if !defined(_SILICON_LABS_32B_SERIES_2)
/* Note that this function is deprecated because we no longer support
* placing msc code in ram. */
MSC_RAMFUNC_DECLARATOR
MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address,
void const *data,
uint32_t numBytes);
#endif
#if defined(MSC_WRITECMD_ERASEMAIN0)
/***************************************************************************//**
* @brief
* Erase the entire Flash in one operation.
*
* @note
* This command will erase the entire contents of the device.
* Use with care, both a debug session and all contents of the flash will be
* lost. The lock bit, MLW will prevent this operation from executing and
* might prevent a successful mass erase.
*
* @return
* Returns the status of the operation.
******************************************************************************/
SL_RAMFUNC_DECLARATOR
MSC_Status_TypeDef MSC_MassErase(void);
#endif
#endif /* !SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT */
MSC_RAMFUNC_DECLARATOR
MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress);
MSC_RAMFUNC_DECLARATOR
MSC_Status_TypeDef MSC_WriteWord(uint32_t *address,
void const *data,
uint32_t numBytes);
#if (_SILICON_LABS_32B_SERIES > 0)
MSC_Status_TypeDef MSC_WriteWordDma(int ch,
uint32_t *address,
const void *data,
uint32_t numBytes);
#endif
void MSC_Init(void);
void MSC_Deinit(void);
/** @} (end addtogroup msc) */
#ifdef __cplusplus
}
#endif
#endif /* defined(MSC_COUNT) && (MSC_COUNT > 0) */
#endif /* EM_MSC_H */

View File

@@ -0,0 +1,81 @@
/***************************************************************************//**
* @file
* @brief Flash Controller (MSC) Compatibility Header
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_MSC_COMPAT_H
#define EM_MSC_COMPAT_H
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
#define MSC_IF_PWROFFIF MSC_IF_PWROFF
#define _MSC_IF_PWROFFIF_SHIFT _MSC_IF_PWROFF_SHIFT
#define _MSC_IF_PWROFFIF_MASK _MSC_IF_PWROFF_MASK
#define _MSC_IF_PWROFFIF_DEFAULT _MSC_IF_PWROFF_DEFAULT
#define MSC_IF_PWROFFIF_DEFAULT MSC_IF_PWROFF_DEFAULT
#define MSC_IEN_PWROFFIEN MSC_IEN_PWROFF
#define _MSC_IEN_PWROFFIEN_SHIFT _MSC_IEN_PWROFF_SHIFT
#define _MSC_IEN_PWROFFIEN_MASK _MSC_IEN_PWROFF_MASK
#define _MSC_IEN_PWROFFIEN_DEFAULT _MSC_IEN_PWROFF_DEFAULT
#define MSC_IEN_PWROFFIEN_DEFAULT MSC_IEN_PWROFF_DEFAULT
#define ICACHE_IEN_RAMERRORIEN ICACHE_IEN_RAMERROR
#define _ICACHE_IEN_RAMERRORIEN_SHIFT _ICACHE_IEN_RAMERROR_SHIFT
#define _ICACHE_IEN_RAMERRORIEN_MASK _ICACHE_IEN_RAMERROR_MASK
#define _ICACHE_IEN_RAMERRORIEN_DEFAULT _ICACHE_IEN_RAMERROR_DEFAULT
#define ICACHE_IEN_RAMERRORIEN_DEFAULT ICACHE_IEN_RAMERROR_DEFAULT
#define SYSCFG_IF_FRCRAMERR1BIF SYSCFG_IF_FRCRAMERR1B
#define _SYSCFG_IF_FRCRAMERR1BIF_SHIFT _SYSCFG_IF_FRCRAMERR1B_SHIFT
#define _SYSCFG_IF_FRCRAMERR1BIF_MASK _SYSCFG_IF_FRCRAMERR1B_MASK
#define _SYSCFG_IF_FRCRAMERR1BIF_DEFAULT _SYSCFG_IF_FRCRAMERR1B_DEFAULT
#define SYSCFG_IF_FRCRAMERR1BIF_DEFAULT SYSCFG_IF_FRCRAMERR1B_DEFAULT
#define SYSCFG_IF_FRCRAMERR2BIF SYSCFG_IF_FRCRAMERR2B
#define _SYSCFG_IF_FRCRAMERR2BIF_SHIFT _SYSCFG_IF_FRCRAMERR2B_SHIFT
#define _SYSCFG_IF_FRCRAMERR2BIF_MASK _SYSCFG_IF_FRCRAMERR2B_MASK
#define _SYSCFG_IF_FRCRAMERR2BIF_DEFAULT _SYSCFG_IF_FRCRAMERR2B_DEFAULT
#define SYSCFG_IF_FRCRAMERR2BIF_DEFAULT SYSCFG_IF_FRCRAMERR2B_DEFAULT
#define SYSCFG_IEN_FRCRAMERR1BIEN SYSCFG_IEN_FRCRAMERR1B
#define _SYSCFG_IEN_FRCRAMERR1BIEN_SHIFT _SYSCFG_IEN_FRCRAMERR1B_SHIFT
#define _SYSCFG_IEN_FRCRAMERR1BIEN_MASK _SYSCFG_IEN_FRCRAMERR1B_MASK
#define _SYSCFG_IEN_FRCRAMERR1BIEN_DEFAULT _SYSCFG_IEN_FRCRAMERR1B_DEFAULT
#define SYSCFG_IEN_FRCRAMERR1BIEN_DEFAULT SYSCFG_IEN_FRCRAMERR1B_DEFAULT
#define SYSCFG_IEN_FRCRAMERR2BIEN SYSCFG_IEN_FRCRAMERR2B
#define _SYSCFG_IEN_FRCRAMERR2BIEN_SHIFT _SYSCFG_IEN_FRCRAMERR2B_SHIFT
#define _SYSCFG_IEN_FRCRAMERR2BIEN_MASK _SYSCFG_IEN_FRCRAMERR2B_MASK
#define _SYSCFG_IEN_FRCRAMERR2BIEN_DEFAULT _SYSCFG_IEN_FRCRAMERR2B_DEFAULT
#define SYSCFG_IEN_FRCRAMERR2BIEN_DEFAULT SYSCFG_IEN_FRCRAMERR2B_DEFAULT
#endif /* _SILICON_LABS_32B_SERIES_2_CONFIG_2 */
#endif /* EM_MSC_COMPAT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,905 @@
/***************************************************************************//**
* @file
* @brief Pulse Counter (PCNT) peripheral API
*******************************************************************************
* # License
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef EM_PCNT_H
#define EM_PCNT_H
#include "em_device.h"
#if defined(PCNT_COUNT) && (PCNT_COUNT > 0)
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup pcnt
* @{
******************************************************************************/
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
/** PCNT0 Counter register size. */
#if defined(_EFM32_GECKO_FAMILY)
#define PCNT0_CNT_SIZE (8) /**< PCNT0 counter is 8 bits. */
#else
#define PCNT0_CNT_SIZE (16) /**< PCNT0 counter is 16 bits. */
#endif
#ifdef PCNT1
/** PCNT1 Counter register size. */
#if defined(_SILICON_LABS_32B_SERIES_0)
#define PCNT1_CNT_SIZE (8) /**< PCNT1 counter is 8 bits. */
#else
#define PCNT1_CNT_SIZE (16) /**< PCNT1 counter is 16 bits. */
#endif
#endif
#ifdef PCNT2
/** PCNT2 Counter register size. */
#if defined(_SILICON_LABS_32B_SERIES_0)
#define PCNT2_CNT_SIZE (8) /**< PCNT2 counter is 8 bits. */
#else
#define PCNT2_CNT_SIZE (16) /**< PCNT2 counter is 16 bits. */
#endif
#endif
/* Define values that can be used in case some state/mode are not defined for some devices.*/
/** PCNT mode disable. */
#define PCNT_MODE_DISABLE 0xFF
/** PCNT count event is none. */
#define PCNT_CNT_EVENT_NONE 0xFF
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/** Mode selection. */
#if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
typedef enum {
/** Disable pulse counter. */
pcntModeDisable = _PCNT_CTRL_MODE_DISABLE,
/** Single input LFACLK oversampling mode (available in EM0-EM2). */
pcntModeOvsSingle = _PCNT_CTRL_MODE_OVSSINGLE,
/** Externally clocked single input counter mode (available in EM0-EM3). */
pcntModeExtSingle = _PCNT_CTRL_MODE_EXTCLKSINGLE,
/** Externally clocked quadrature decoder mode (available in EM0-EM3). */
pcntModeExtQuad = _PCNT_CTRL_MODE_EXTCLKQUAD,
#if defined(_PCNT_CTRL_MODE_OVSQUAD1X)
/** LFACLK oversampling quadrature decoder 1X mode (available in EM0-EM2). */
pcntModeOvsQuad1 = _PCNT_CTRL_MODE_OVSQUAD1X,
/** LFACLK oversampling quadrature decoder 2X mode (available in EM0-EM2). */
pcntModeOvsQuad2 = _PCNT_CTRL_MODE_OVSQUAD2X,
/** LFACLK oversampling quadrature decoder 4X mode (available in EM0-EM2). */
pcntModeOvsQuad4 = _PCNT_CTRL_MODE_OVSQUAD4X,
#endif
} PCNT_Mode_TypeDef;
#else
typedef enum {
/** Disable pulse counter. */
pcntModeDisable = PCNT_MODE_DISABLE,
/** Single input LFACLK oversampling mode (available in EM0-EM2). */
pcntModeOvsSingle = _PCNT_CFG_MODE_OVSSINGLE,
/** Externally clocked single input counter mode (available in EM0-EM3). */
pcntModeExtSingle = _PCNT_CFG_MODE_EXTCLKSINGLE,
/** Externally clocked quadrature decoder mode (available in EM0-EM3). */
pcntModeExtQuad = _PCNT_CFG_MODE_EXTCLKQUAD,
/** LFACLK oversampling quadrature decoder 1X mode (available in EM0-EM2). */
pcntModeOvsQuad1 = _PCNT_CFG_MODE_OVSQUAD1X,
/** LFACLK oversampling quadrature decoder 2X mode (available in EM0-EM2). */
pcntModeOvsQuad2 = _PCNT_CFG_MODE_OVSQUAD2X,
/** LFACLK oversampling quadrature decoder 4X mode (available in EM0-EM2). */
pcntModeOvsQuad4 = _PCNT_CFG_MODE_OVSQUAD4X,
} PCNT_Mode_TypeDef;
#endif
#if defined(_PCNT_CTRL_CNTEV_MASK)
/** Counter event selection.
* Note: unshifted values are being used for enumeration because multiple
* configuration structure members use this type definition. */
typedef enum {
/** Counts up on up-count and down on down-count events. */
pcntCntEventBoth = _PCNT_CTRL_CNTEV_BOTH,
/** Only counts up on up-count events. */
pcntCntEventUp = _PCNT_CTRL_CNTEV_UP,
/** Only counts down on down-count events. */
pcntCntEventDown = _PCNT_CTRL_CNTEV_DOWN,
/** Never counts. */
#if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
pcntCntEventNone = _PCNT_CTRL_CNTEV_NONE
#else
pcntCntEventNone = PCNT_CNT_EVENT_NONE
#endif
} PCNT_CntEvent_TypeDef;
#endif
/** PRS sources for @p s0PRS and @p s1PRS. */
#if defined(_PCNT_INPUT_MASK)
typedef enum {
pcntPRSCh0 = 0, /**< PRS channel 0. */
pcntPRSCh1 = 1, /**< PRS channel 1. */
pcntPRSCh2 = 2, /**< PRS channel 2. */
pcntPRSCh3 = 3, /**< PRS channel 3. */
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH4)
pcntPRSCh4 = 4, /**< PRS channel 4. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH5)
pcntPRSCh5 = 5, /**< PRS channel 5. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH6)
pcntPRSCh6 = 6, /**< PRS channel 6. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH7)
pcntPRSCh7 = 7, /**< PRS channel 7. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH8)
pcntPRSCh8 = 8, /**< PRS channel 8. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH9)
pcntPRSCh9 = 9, /**< PRS channel 9. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH10)
pcntPRSCh10 = 10, /**< PRS channel 10. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH11)
pcntPRSCh11 = 11, /**< PRS channel 11. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH12)
pcntPRSCh12 = 12, /**< PRS channel 12. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH13)
pcntPRSCh13 = 13, /**< PRS channel 13. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH14)
pcntPRSCh14 = 14, /**< PRS channel 14. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH15)
pcntPRSCh15 = 15, /**< PRS channel 15. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH16)
pcntPRSCh16 = 16, /**< PRS channel 16. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH17)
pcntPRSCh17 = 17, /**< PRS channel 17. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH18)
pcntPRSCh18 = 18, /**< PRS channel 18. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH19)
pcntPRSCh19 = 19, /**< PRS channel 19. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH20)
pcntPRSCh20 = 20, /**< PRS channel 20. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH21)
pcntPRSCh21 = 21, /**< PRS channel 21. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH22)
pcntPRSCh22 = 22, /**< PRS channel 22. */
#endif
#if defined(PCNT_INPUT_S0PRSSEL_PRSCH23)
pcntPRSCh23 = 23, /**< PRS channel 23. */
#endif
} PCNT_PRSSel_TypeDef;
#elif defined(_SILICON_LABS_32B_SERIES_2)
typedef unsigned int PCNT_PRSSel_TypeDef;
#endif
#if defined(_PCNT_INPUT_MASK) || defined(_SILICON_LABS_32B_SERIES_2)
/** PRS inputs of PCNT. */
typedef enum {
pcntPRSInputS0 = 0, /** PRS input 0. */
pcntPRSInputS1 = 1 /** PRS input 1. */
} PCNT_PRSInput_TypeDef;
#endif
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/** Initialization structure. */
typedef struct {
/** Mode to operate in. */
PCNT_Mode_TypeDef mode;
/** Initial counter value (refer to reference manual for max value allowed).
* Only used for #pcntModeOvsSingle (and possibly #pcntModeDisable) modes.
* If using #pcntModeExtSingle or #pcntModeExtQuad modes, counter
* value is reset to HW reset value. */
uint32_t counter;
/** Initial top value (refer to reference manual for max value allowed).
* Only used for #pcntModeOvsSingle (and possibly #pcntModeDisable) modes.
* If using #pcntModeExtSingle or #pcntModeExtQuad modes, top
* value is reset to HW reset value. */
uint32_t top;
/** Polarity of incoming edge.
* @li #pcntModeExtSingle mode - if false, positive edges are counted,
* otherwise negative edges.
* @li #pcntModeExtQuad mode - if true, counting direction is inverted. */
bool negEdge;
/** Counting direction, only applicable for #pcntModeOvsSingle and
* #pcntModeExtSingle modes. */
bool countDown;
/** Enable filter, only available in #pcntModeOvsSingle* mode. */
bool filter;
#if defined(_SILICON_LABS_32B_SERIES_2)
/** Enable/disable PCNT counting during debug halt. Only in OVSSINGLE and OVSQUAD modes. */
bool debugHalt;
#endif
#if defined(PCNT_CTRL_HYST) || defined(_SILICON_LABS_32B_SERIES_2)
/** Set to true to enable hysteresis. When enabled, PCNT will always
* overflow and underflow to TOP/2. */
bool hyst;
#endif
#if defined(PCNT_CTRL_S1CDIR)
/** Set to true to enable S1 to determine the direction of counting in
* OVSSINGLE or EXTCLKSINGLE modes. @n
* When S1 is high, the count direction is given by CNTDIR, and when S1 is
* low, the count direction is the opposite. */
bool s1CntDir;
#endif
#if defined(_PCNT_CTRL_CNTEV_SHIFT)
/** Selects whether the regular counter responds to up-count events,
* down-count events, both, or none. */
PCNT_CntEvent_TypeDef cntEvent;
#endif
#if defined(_PCNT_CTRL_AUXCNTEV_SHIFT)
/** Selects whether the auxiliary counter responds to up-count events,
* down-count events, both, or none. */
PCNT_CntEvent_TypeDef auxCntEvent;
#endif
#if defined(_PCNT_INPUT_MASK) || defined(_SILICON_LABS_32B_SERIES_2)
/** Select PRS channel as input to S0IN in PCNTx_INPUT register. */
PCNT_PRSSel_TypeDef s0PRS;
/** Select PRS channel as input to S1IN in PCNTx_INPUT register. */
PCNT_PRSSel_TypeDef s1PRS;
#endif
} PCNT_Init_TypeDef;
/** Default Debug. */
#if defined(_SILICON_LABS_32B_SERIES_2)
#define DEFAULT_DEBUG_HALT true,
#else
#define DEFAULT_DEBUG_HALT
#endif
/** Default Mode. */
#define DEFAULT_MODE pcntModeDisable, /**< Disabled by default. */
/** Default Hysteresis. */
#if defined(PCNT_CTRL_HYST) || defined(_SILICON_LABS_32B_SERIES_2)
#define DEFAULT_HYST false, /**< Hysteresis disabled. */
#else
#define DEFAULT_HYST
#endif
/** Default counter direction*/
#if defined(PCNT_CTRL_S1CDIR)
#define DEFAULT_CDIR true, /**< Counter direction is given by CNTDIR. */
#else
#define DEFAULT_CDIR
#endif
/** Default count event*/
#if defined(_PCNT_CTRL_CNTEV_SHIFT)
#define DEFAULT_CNTEV pcntCntEventUp, /**< Regular counter counts up on upcount events. */
#else
#define DEFAULT_CNTEV
#endif
/** Default auxiliary count event. */
#if defined(_PCNT_CTRL_AUXCNTEV_SHIFT)
#define DEFAULT_AUXCNTEV pcntCntEventNone, /**< Auxiliary counter doesn't respond to events. */
#else
#define DEFAULT_AUXCNTEV
#endif
/** Default selected PRS channel as S0IN and S1IN. */
#if defined(_PCNT_INPUT_MASK)
#define DEFAULT_PRS_CH pcntPRSCh0, /**< PRS channel 0 selected as S0IN and as S1IN. */
#elif defined(_SILICON_LABS_32B_SERIES_2)
#define DEFAULT_PRS_CH 0u,
#else
#define DEFAULT_PRS_CH
#endif
/** Default configuration for PCNT initialization structure. */
#define PCNT_INIT_DEFAULT \
{ \
DEFAULT_MODE /* Default mode. */ \
_PCNT_CNT_RESETVALUE, /* Default counter HW reset value. */ \
_PCNT_TOP_RESETVALUE, /* Default counter HW reset value. */ \
false, /* Use positive edge. */ \
false, /* Up-counting. */ \
false, /* Filter disabled. */ \
DEFAULT_DEBUG_HALT /* Debug Halt enabled. */ \
DEFAULT_HYST /* Default Hysteresis. */ \
DEFAULT_CDIR /* Default CNTDIR. */ \
DEFAULT_CNTEV /* Faults CNTEV. */ \
DEFAULT_AUXCNTEV /* Default AUXCNTEV. */ \
DEFAULT_PRS_CH /* PRS channel 0 selected as S0IN. */ \
DEFAULT_PRS_CH /* PRS channel 0 selected as S1IN. */ \
}
#if defined(PCNT_OVSCFG_FILTLEN_DEFAULT) || defined(_SILICON_LABS_32B_SERIES_2)
/** Filter initialization structure */
typedef struct {
/** Used only in OVSINGLE and OVSQUAD1X-4X modes. To use this, enable filter by
* setting filter to true during PCNT_Init(). Filter length = (filtLen + 5) LFACLK cycles. */
uint8_t filtLen;
/** When set, removes flutter from Quaddecoder inputs S0IN and S1IN.
* Available only in OVSQUAD1X-4X modes. */
bool flutterrm;
} PCNT_Filter_TypeDef;
#endif
/** Default configuration for PCNT initialization structure. */
#if defined(PCNT_OVSCFG_FILTLEN_DEFAULT) || defined(_SILICON_LABS_32B_SERIES_2)
#define PCNT_FILTER_DEFAULT \
{ \
0, /* Default length is 5 LFACLK cycles. */ \
false /* No flutter removal. */ \
}
#endif
#if defined(PCNT_CTRL_TCCMODE_DEFAULT)
/** Modes for Triggered Compare and Clear module. */
typedef enum {
/** Triggered compare and clear not enabled. */
tccModeDisabled = _PCNT_CTRL_TCCMODE_DISABLED,
/** Compare and clear performed on each (optionally prescaled) LFA clock cycle. */
tccModeLFA = _PCNT_CTRL_TCCMODE_LFA,
/** Compare and clear performed on PRS edges. Polarity defined by prsPolarity. */
tccModePRS = _PCNT_CTRL_TCCMODE_PRS
} PCNT_TCCMode_TypeDef;
/** Prescaler values for LFA compare and clear events. Only has effect when TCC mode is LFA. */
typedef enum {
/** Compare and clear event each LFA cycle. */
tccPrescDiv1 = _PCNT_CTRL_TCCPRESC_DIV1,
/** Compare and clear event every other LFA cycle. */
tccPrescDiv2 = _PCNT_CTRL_TCCPRESC_DIV2,
/** Compare and clear event every 4th LFA cycle. */
tccPrescDiv4 = _PCNT_CTRL_TCCPRESC_DIV4,
/** Compare and clear event every 8th LFA cycle. */
tccPrescDiv8 = _PCNT_CTRL_TCCPRESC_DIV8
} PCNT_TCCPresc_Typedef;
/** Compare modes for TCC module. */
typedef enum {
/** Compare match if PCNT_CNT is less than, or equal to PCNT_TOP. */
tccCompLTOE = _PCNT_CTRL_TCCCOMP_LTOE,
/** Compare match if PCNT_CNT is greater than or equal to PCNT_TOP. */
tccCompGTOE = _PCNT_CTRL_TCCCOMP_GTOE,
/** Compare match if PCNT_CNT is less than, or equal to PCNT_TOP[15:8]], and greater
* than, or equal to PCNT_TOP[7:0]. */
tccCompRange = _PCNT_CTRL_TCCCOMP_RANGE
} PCNT_TCCComp_Typedef;
/** TCC initialization structure. */
typedef struct {
/** Mode to operate in. */
PCNT_TCCMode_TypeDef mode;
/** Prescaler value for LFACLK in LFA mode. */
PCNT_TCCPresc_Typedef prescaler;
/** Choose the event that will trigger a clear. */
PCNT_TCCComp_Typedef compare;
/** PRS input to TCC module, either for gating the PCNT clock, triggering the TCC comparison, or both. */
PCNT_PRSSel_TypeDef tccPRS;
/** TCC PRS input polarity. @n
* False = Rising edge for comparison trigger, and PCNT clock gated when PRS signal is high. @n
* True = Falling edge for comparison trigger, and PCNT clock gated when PRS signal is low. */
bool prsPolarity;
/** Enable gating PCNT input clock through TCC PRS signal.
* Polarity selection is done through prsPolarity. */
bool prsGateEnable;
} PCNT_TCC_TypeDef;
/** TCC Default. */
#define PCNT_TCC_DEFAULT \
{ \
tccModeDisabled, /* Disabled by default. */ \
tccPrescDiv1, /* Do not prescale LFA clock in LFA mode. */ \
tccCompLTOE, /* Clear when CNT <= TOP. */ \
pcntPRSCh0, /* Select PRS channel 0 as input to TCC. */ \
false, /* PRS polarity is rising edge, and gate when 1. */ \
false /* Do not gate PCNT counter input. */ \
}
#endif
/* defined(PCNT_CTRL_TCCMODE_DEFAULT) */
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Get the pulse counter value.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @return
* Current pulse counter value.
******************************************************************************/
__STATIC_INLINE uint32_t PCNT_CounterGet(PCNT_TypeDef *pcnt)
{
return pcnt->CNT;
}
#if defined(_PCNT_AUXCNT_MASK)
/***************************************************************************//**
* @brief
* Get the auxiliary counter value.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @return
* Current auxiliary counter value.
******************************************************************************/
__STATIC_INLINE uint32_t PCNT_AuxCounterGet(PCNT_TypeDef *pcnt)
{
return pcnt->AUXCNT;
}
#endif
void PCNT_CounterReset(PCNT_TypeDef *pcnt);
void PCNT_CounterTopSet(PCNT_TypeDef *pcnt, uint32_t count, uint32_t top);
/***************************************************************************//**
* @brief
* Set a counter value.
*
* @details
* Pulse counter is disabled while changing counter value and re-enabled
* (if originally enabled) when counter value has been set.
*
* @note
* This function will stall until synchronization to low-frequency domain is
* completed. For that reason, it should normally not be used when using
* an external clock to clock the PCNT module since stall time may be
* undefined in that case. The counter should normally only be set when
* operating in (or about to enable) #pcntModeOvsSingle mode.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @param[in] count
* Value to set in counter register.
******************************************************************************/
__STATIC_INLINE void PCNT_CounterSet(PCNT_TypeDef *pcnt, uint32_t count)
{
PCNT_CounterTopSet(pcnt, count, pcnt->TOP);
}
void PCNT_Enable(PCNT_TypeDef *pcnt, PCNT_Mode_TypeDef mode);
bool PCNT_IsEnabled(PCNT_TypeDef *pcnt);
#if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
void PCNT_FreezeEnable(PCNT_TypeDef *pcnt, bool enable);
#endif
void PCNT_Init(PCNT_TypeDef *pcnt, const PCNT_Init_TypeDef *init);
#if defined(PCNT_OVSCFG_FILTLEN_DEFAULT) || defined(_SILICON_LABS_32B_SERIES_2)
void PCNT_FilterConfiguration(PCNT_TypeDef *pcnt, const PCNT_Filter_TypeDef *config, bool enable);
#endif
#if defined(_PCNT_INPUT_MASK) || defined(_SILICON_LABS_32B_SERIES_2)
void PCNT_PRSInputEnable(PCNT_TypeDef *pcnt,
PCNT_PRSInput_TypeDef prsInput,
bool enable);
#endif
#if defined(PCNT_CTRL_TCCMODE_DEFAULT)
void PCNT_TCCConfiguration(PCNT_TypeDef *pcnt, const PCNT_TCC_TypeDef *config);
#endif
/***************************************************************************//**
* @brief
* Clear one or more pending PCNT interrupts.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @param[in] flags
* Pending PCNT interrupt source to clear. Use a bitwise logic OR combination
* of valid interrupt flags for the PCNT module (PCNT_IF_nnn).
******************************************************************************/
__STATIC_INLINE void PCNT_IntClear(PCNT_TypeDef *pcnt, uint32_t flags)
{
#if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
pcnt->IFC = flags;
#else
pcnt->IF_CLR = flags;
#endif
}
/***************************************************************************//**
* @brief
* Disable one or more PCNT interrupts.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @param[in] flags
* PCNT interrupt sources to disable. Use a bitwise logic OR combination of
* valid interrupt flags for PCNT module (PCNT_IF_nnn).
******************************************************************************/
__STATIC_INLINE void PCNT_IntDisable(PCNT_TypeDef *pcnt, uint32_t flags)
{
#if defined(PCNT_HAS_SET_CLEAR)
pcnt->IEN_CLR = flags;
#else
pcnt->IEN &= ~flags;
#endif
}
/***************************************************************************//**
* @brief
* Enable one or more PCNT interrupts.
*
* @note
* Depending on the use, a pending interrupt may already be set prior to
* enabling the interrupt. To ignore a pending interrupt, consider using
* PCNT_IntClear() prior to enabling the interrupt.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @param[in] flags
* PCNT interrupt sources to enable. Use a bitwise logic OR combination of
* valid interrupt flags for PCNT module (PCNT_IF_nnn).
******************************************************************************/
__STATIC_INLINE void PCNT_IntEnable(PCNT_TypeDef *pcnt, uint32_t flags)
{
#if defined(PCNT_HAS_SET_CLEAR)
pcnt->IEN_SET = flags;
#else
pcnt->IEN |= flags;
#endif
}
/***************************************************************************//**
* @brief
* Get pending PCNT interrupt flags.
*
* @note
* The event bits are not cleared by the use of this function.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @return
* PCNT interrupt sources pending. A bitwise logic OR combination of valid
* interrupt flags for PCNT module (PCNT_IF_nnn).
******************************************************************************/
__STATIC_INLINE uint32_t PCNT_IntGet(PCNT_TypeDef *pcnt)
{
return pcnt->IF;
}
/***************************************************************************//**
* @brief
* Get enabled and pending PCNT interrupt flags.
*
* @details
* Useful for handling more interrupt sources in the same interrupt handler.
*
* @note
* The event bits are not cleared by the use of this function.
*
* @param[in] pcnt
* Pointer to thePCNT peripheral register block.
*
* @return
* Pending and enabled PCNT interrupt sources.
* The return value is the bitwise AND combination of
* - the OR combination of enabled interrupt sources in PCNT_IEN_nnn
* register (PCNT_IEN_nnn) and
* - the OR combination of valid interrupt flags of the PCNT module
* (PCNT_IF_nnn).
******************************************************************************/
__STATIC_INLINE uint32_t PCNT_IntGetEnabled(PCNT_TypeDef *pcnt)
{
uint32_t ien;
/* Store pcnt->IEN in temporary variable in order to define explicit order
* of volatile accesses. */
ien = pcnt->IEN;
/* Bitwise AND of pending and enabled interrupts. */
return pcnt->IF & ien;
}
/***************************************************************************//**
* @brief
* Set one or more pending PCNT interrupts from SW.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @param[in] flags
* PCNT interrupt sources to set to pending. Use a bitwise logic OR combination
* of valid interrupt flags for PCNT module (PCNT_IF_nnn).
******************************************************************************/
__STATIC_INLINE void PCNT_IntSet(PCNT_TypeDef *pcnt, uint32_t flags)
{
#if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
pcnt->IFS = flags;
#else
pcnt->IF_SET = flags;
#endif
}
#if defined(_PCNT_LOCK_MASK)
/***************************************************************************//**
* @brief
* Lock PCNT registers.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @note When PCNT registers are locked PCNT_CFG, PCNT_EN, PCNT_SWRST, PCNT_CMD,
* PCNT_CTRL, PCNT_OVSCTRL, PCNT_CNT, PCNT_TOP, and PCNT_TOPB registers
* cannot be written to.
******************************************************************************/
__STATIC_INLINE void PCNT_Lock(PCNT_TypeDef *pcnt)
{
pcnt->LOCK = ~PCNT_LOCK_PCNTLOCKKEY_UNLOCK;
}
#endif
#if defined(_PCNT_LOCK_MASK)
/***************************************************************************//**
* @brief
* Unlock PCNT registers.
*
* @param[in] pcnt
* Pointer to thePCNT peripheral register block.
******************************************************************************/
__STATIC_INLINE void PCNT_Unlock(PCNT_TypeDef *pcnt)
{
pcnt->LOCK = PCNT_LOCK_PCNTLOCKKEY_UNLOCK;
}
#endif
void PCNT_Reset(PCNT_TypeDef *pcnt);
/***************************************************************************//**
* @brief
* Get the pulse counter top buffer value.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @return
* Current pulse counter top buffer value.
******************************************************************************/
__STATIC_INLINE uint32_t PCNT_TopBufferGet(PCNT_TypeDef *pcnt)
{
#if defined(_SILICON_LABS_32B_SERIES_2)
while (pcnt->SYNCBUSY & PCNT_SYNCBUSY_TOPB) {
}
#endif
return pcnt->TOPB;
}
void PCNT_TopBufferSet(PCNT_TypeDef *pcnt, uint32_t val);
/***************************************************************************//**
* @brief
* Get the pulse counter top value.
*
* @param[in] pcnt
* Pointer to the PCNT peripheral register block.
*
* @return
* Current pulse counter top value.
******************************************************************************/
__STATIC_INLINE uint32_t PCNT_TopGet(PCNT_TypeDef *pcnt)
{
#if defined(_SILICON_LABS_32B_SERIES_2)
while (pcnt->SYNCBUSY & PCNT_SYNCBUSY_TOP) {
}
#endif
return pcnt->TOP;
}
void PCNT_TopSet(PCNT_TypeDef *pcnt, uint32_t val);
/***************************************************************************//**
* @brief
* Wait for an ongoing sync of register(s) to low-frequency domain to complete.
*
* @param[in] pcnt
* A pointer to the PCNT peripheral register block.
*
* @param[in] mask
* A bitmask corresponding to SYNCBUSY register defined bits indicating
* registers that must complete any ongoing synchronization.
******************************************************************************/
__STATIC_INLINE void PCNT_Sync(PCNT_TypeDef *pcnt, uint32_t mask)
{
/* Avoid deadlock if modifying the same register twice when freeze mode is
* activated. */
#if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
if (pcnt->FREEZE & PCNT_FREEZE_REGFREEZE) {
return;
}
#endif
/* Wait for any pending previous write operation to have been completed in
* low-frequency domain. */
while (pcnt->SYNCBUSY & mask) {
}
}
#if defined(_SILICON_LABS_32B_SERIES_2)
/***************************************************************************//**
* @brief
* Start the main PCNT counter.
*
* @details
* This function will send a start command to the PCNT peripheral. The PCNT
* peripheral will use some LF clock ticks before the command is executed.
* The @ref PCNT_Sync() function can be used to wait for the start command
* to be executed.
*
* @param[in] pcnt
* A pointer to the PCNT peripheral register block.
*
* @note
* This function requires the PCNT to be enabled.
******************************************************************************/
__STATIC_INLINE void PCNT_StartMainCnt(PCNT_TypeDef *pcnt)
{
PCNT_Sync(pcnt, PCNT_SYNCBUSY_CMD);
pcnt->CMD_SET = PCNT_CMD_STARTCNT;
}
/***************************************************************************//**
* @brief
* Stop the main PCNT counter.
*
* @details
* This function will send a stop command to the PCNT peripheral. The PCNT
* peripheral will use some LF clock ticks before the command is executed.
* The @ref PCNT_Sync() function can be used to wait for the stop command
* to be executed.
*
* @param[in] pcnt
* A pointer to the PCNT peripheral register block.
*
* @note
* This function requires the PCNT to be enabled.
******************************************************************************/
__STATIC_INLINE void PCNT_StopMainCnt(PCNT_TypeDef *pcnt)
{
PCNT_Sync(pcnt, PCNT_SYNCBUSY_CMD);
pcnt->CMD_SET = PCNT_CMD_STOPCNT;
}
/***************************************************************************//**
* @brief
* Start the auxiliary PCNT counter.
*
* @details
* This function will send a start command to the PCNT peripheral. The PCNT
* peripheral will use some LF clock ticks before the command is executed.
* The @ref PCNT_Sync() function can be used to wait for the start command
* to be executed.
*
* @param[in] pcnt
* A pointer to the PCNT peripheral register block.
*
* @note
* This function requires the PCNT to be enabled.
******************************************************************************/
__STATIC_INLINE void PCNT_StartAuxCnt(PCNT_TypeDef *pcnt)
{
PCNT_Sync(pcnt, PCNT_SYNCBUSY_CMD);
pcnt->CMD_SET = PCNT_CMD_STARTAUXCNT;
}
/***************************************************************************//**
* @brief
* Stop the auxiliary PCNT counter.
*
* @details
* This function will send a stop command to the PCNT peripheral. The PCNT
* peripheral will use some LF clock ticks before the command is executed.
* The @ref PCNT_Sync() function can be used to wait for the stop command
* to be executed.
*
* @param[in] pcnt
* A pointer to the PCNT peripheral register block.
*
* @note
* This function requires the PCNT to be enabled.
******************************************************************************/
__STATIC_INLINE void PCNT_StopAuxCnt(PCNT_TypeDef *pcnt)
{
PCNT_Sync(pcnt, PCNT_SYNCBUSY_CMD);
pcnt->CMD_SET = PCNT_CMD_STOPAUXCNT;
}
#endif
/** @} (end addtogroup pcnt) */
#ifdef __cplusplus
}
#endif
#endif /* defined(PCNT_COUNT) && (PCNT_COUNT > 0) */
#endif /* EM_PCNT_H */

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More