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,32 @@
/***************************************************************************//**
* @file
* @brief System Real Time Counter (SYSRTC) peripheral API
*******************************************************************************
* # 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.
*
******************************************************************************/
// Compatibility layer. peripheral_sysrtc.h has been renamed to sl_hal_sysrtc.h
#include "sl_hal_sysrtc.h"

View File

@@ -0,0 +1,33 @@
/***************************************************************************//**
* @file
* @brief SYSRTC Compatibility Layer.
*******************************************************************************
* # 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.
*
******************************************************************************/
// Compatibility layer. peripheral_sysrtc_compat.h has been renamed to
// sl_hal_sysrtc_compat.h
#include "sl_hal_sysrtc_compat.h"

View File

@@ -0,0 +1,274 @@
/***************************************************************************//**
* @file
* @brief RAM and peripheral bit-field set, clear, read and write 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_HAL_BUS_H
#define SL_HAL_BUS_H
#include "sl_assert.h"
#include "sl_core.h"
#include "em_device.h"
#include "sl_code_classification.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 field set/clear/write/read access to RAM and peripheral's registers.
* @{
******************************************************************************/
/***************************************************************************//**
* @brief
* Perform a single-bit write operation on a 32-bit word in RAM.
*
* @param[in] addr An address 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 sl_hal_bus_ram_write_bit(volatile uint32_t *addr,
uint32_t bit,
uint32_t val)
{
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);
}
/***************************************************************************//**
* @brief
* Perform a single-bit read operation on a 32-bit word in RAM.
*
* @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 sl_hal_bus_ram_read_bit(volatile const uint32_t *addr,
uint32_t bit)
{
return ((*addr) >> bit) & 1UL;
}
/***************************************************************************//**
* @brief
* Perform a single-bit atomic write operation on a peripheral register.
*
* @details
* This function uses built-in hardware 4K-aliased addressing that allows to
* perform an atomic read-modify-write operation on a single register bit.
* See the reference manual for more details about alias addressing.
*
* @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.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_COMMON, SL_CODE_CLASS_TIME_CRITICAL)
__STATIC_INLINE void sl_hal_bus_reg_write_bit(volatile uint32_t *addr,
uint32_t bit,
uint32_t 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;
#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 atomic read operation on a peripheral register.
*
* @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 sl_hal_bus_reg_read_bit(volatile const uint32_t *addr,
uint32_t bit)
{
return ((*addr) >> bit) & 1UL;
}
/***************************************************************************//**
* @brief
* Perform an atomic masked set operation on a peripheral register address.
*
* @details
* A peripheral register masked set provides a 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.
*
* @note
* This function uses built-in hardware 4K-aliased addressing that allows to
* perform an atomic read-modify-write operation.
* See the reference manual for more details about alias addressing.
*
* @param[in] addr A peripheral register address.
*
* @param[in] mask A mask to set.
******************************************************************************/
__STATIC_INLINE void sl_hal_bus_reg_set_mask(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;
#else
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
*addr |= mask;
CORE_EXIT_CRITICAL();
#endif
}
/***************************************************************************//**
* @brief
* Perform an atomic masked clear operation on the peripheral register address.
*
* @details
* A peripheral register masked clear provides a 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.
*
* @note
* This function uses built-in hardware 4K-aliased addressing that allows to
* perform an atomic read-modify-write operation.
* See the reference manual for more details about alias addressing.
*
* @param[in] addr A peripheral register address.
*
* @param[in] mask A mask to clear.
******************************************************************************/
__STATIC_INLINE void sl_hal_bus_reg_clear_mask(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;
#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.
******************************************************************************/
__STATIC_INLINE void sl_hal_bus_reg_write_mask(volatile uint32_t *addr,
uint32_t mask,
uint32_t val)
{
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
*addr = (*addr & ~mask) | (val & mask);
CORE_EXIT_CRITICAL();
}
/***************************************************************************//**
* @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 sl_hal_bus_reg_read_mask(volatile const uint32_t *addr,
uint32_t mask)
{
return *addr & mask;
}
/** @} (end addtogroup bus) */
#ifdef __cplusplus
}
#endif
#endif /* SL_HAL_BUS_H */

View File

@@ -0,0 +1,915 @@
/***************************************************************************//**
* @file
* @brief General Purpose IO (GPIO) 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 SL_HAL_GPIO_H
#define SL_HAL_GPIO_H
#include "em_device.h"
#if defined(GPIO_PRESENT)
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include "sl_assert.h"
#include "sl_device_gpio.h"
#include "sl_code_classification.h"
/* *INDENT-OFF* */
// *****************************************************************************
/// @addtogroup gpio GPIO - General Purpose Input Output
/// @brief General Purpose Input Output peripheral
///
/// @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 peripheral is used for interrupt configuration, pin configuration and direct pin manipulation
/// as well as routing for peripheral pin connections.
///
/// @{
// *****************************************************************************
/* *INDENT-ON* */
/*******************************************************************************
******************************** DEFINES **********************************
******************************************************************************/
/// Define for port specific pin mask
#if defined(GPIO_PA_MASK)
#define SL_HAL_GPIO_PORT_A_PIN_MASK (GPIO_PA_MASK)
#else
#define SL_HAL_GPIO_PORT_A_PIN_MASK 0
#endif
#if defined(GPIO_PB_MASK)
#define SL_HAL_GPIO_PORT_B_PIN_MASK (GPIO_PB_MASK)
#else
#define SL_HAL_GPIO_PORT_B_PIN_MASK 0
#endif
#if defined(GPIO_PC_MASK)
#define SL_HAL_GPIO_PORT_C_PIN_MASK (GPIO_PC_MASK)
#else
#define SL_HAL_GPIO_PORT_C_PIN_MASK 0
#endif
#if defined(GPIO_PD_MASK)
#define SL_HAL_GPIO_PORT_D_PIN_MASK (GPIO_PD_MASK)
#else
#define SL_HAL_GPIO_PORT_D_PIN_MASK 0
#endif
#if defined(GPIO_PE_MASK)
#define SL_HAL_GPIO_PORT_E_PIN_MASK (GPIO_PE_MASK)
#else
#define SL_HAL_GPIO_PORT_E_PIN_MASK 0
#endif
#if defined(GPIO_PF_MASK)
#define SL_HAL_GPIO_PORT_F_PIN_MASK (GPIO_PF_MASK)
#else
#define SL_HAL_GPIO_PORT_F_PIN_MASK 0
#endif
#if defined(GPIO_PG_MASK)
#define SL_HAL_GPIO_PORT_G_PIN_MASK (GPIO_PG_MASK)
#else
#define SL_HAL_GPIO_PORT_G_PIN_MASK 0
#endif
#if defined(GPIO_PH_MASK)
#define SL_HAL_GPIO_PORT_H_PIN_MASK (GPIO_PH_MASK)
#else
#define SL_HAL_GPIO_PORT_H_PIN_MASK 0
#endif
#if defined(GPIO_PI_MASK)
#define SL_HAL_GPIO_PORT_I_PIN_MASK (GPIO_PI_MASK)
#else
#define SL_HAL_GPIO_PORT_I_PIN_MASK 0
#endif
#if defined(GPIO_PJ_MASK)
#define SL_HAL_GPIO_PORT_J_PIN_MASK (GPIO_PJ_MASK)
#else
#define SL_HAL_GPIO_PORT_J_PIN_MASK 0
#endif
#if defined(GPIO_PK_MASK)
#define SL_HAL_GPIO_PORT_K_PIN_MASK (GPIO_PK_MASK)
#else
#define SL_HAL_GPIO_PORT_K_PIN_MASK 0
#endif
/// Define for port specific pin count
#if defined(GPIO_PA_COUNT)
#define SL_HAL_GPIO_PORT_A_PIN_COUNT (GPIO_PA_COUNT)
#else
#define SL_HAL_GPIO_PORT_A_PIN_COUNT 0
#endif
#if defined(GPIO_PB_COUNT)
#define SL_HAL_GPIO_PORT_B_PIN_COUNT (GPIO_PB_COUNT)
#else
#define SL_HAL_GPIO_PORT_B_PIN_COUNT 0
#endif
#if defined(GPIO_PC_COUNT)
#define SL_HAL_GPIO_PORT_C_PIN_COUNT (GPIO_PC_COUNT)
#else
#define SL_HAL_GPIO_PORT_C_PIN_COUNT 0
#endif
#if defined(GPIO_PD_COUNT)
#define SL_HAL_GPIO_PORT_D_PIN_COUNT (GPIO_PD_COUNT)
#else
#define SL_HAL_GPIO_PORT_D_PIN_COUNT 0
#endif
#if defined(GPIO_PE_COUNT)
#define SL_HAL_GPIO_PORT_E_PIN_COUNT (GPIO_PE_COUNT)
#else
#define SL_HAL_GPIO_PORT_E_PIN_COUNT 0
#endif
#if defined(GPIO_PF_COUNT)
#define SL_HAL_GPIO_PORT_F_PIN_COUNT (GPIO_PF_COUNT)
#else
#define SL_HAL_GPIO_PORT_F_PIN_COUNT 0
#endif
#if defined(GPIO_PG_COUNT)
#define SL_HAL_GPIO_PORT_G_PIN_COUNT (GPIO_PG_COUNT)
#else
#define SL_HAL_GPIO_PORT_G_PIN_COUNT 0
#endif
#if defined(GPIO_PH_COUNT)
#define SL_HAL_GPIO_PORT_H_PIN_COUNT (GPIO_PH_COUNT)
#else
#define SL_HAL_GPIO_PORT_H_PIN_COUNT 0
#endif
#if defined(GPIO_PI_COUNT)
#define SL_HAL_GPIO_PORT_I_PIN_COUNT (GPIO_PI_COUNT)
#else
#define SL_HAL_GPIO_PORT_I_PIN_COUNT 0
#endif
#if defined(GPIO_PJ_COUNT)
#define SL_HAL_GPIO_PORT_J_PIN_COUNT (GPIO_PJ_COUNT)
#else
#define SL_HAL_GPIO_PORT_J_PIN_COUNT 0
#endif
#if defined(GPIO_PK_COUNT)
#define SL_HAL_GPIO_PORT_K_PIN_COUNT (GPIO_PK_COUNT)
#else
#define SL_HAL_GPIO_PORT_K_PIN_COUNT 0
#endif
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
/// Highest GPIO port number.
#if (SL_HAL_GPIO_PORT_K_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 10
#elif (SL_HAL_GPIO_PORT_J_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 9
#elif (SL_HAL_GPIO_PORT_I_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 8
#elif (SL_HAL_GPIO_PORT_H_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 7
#elif (SL_HAL_GPIO_PORT_G_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 6
#elif (SL_HAL_GPIO_PORT_F_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 5
#elif (SL_HAL_GPIO_PORT_E_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 4
#elif (SL_HAL_GPIO_PORT_D_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 3
#elif (SL_HAL_GPIO_PORT_C_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 2
#elif (SL_HAL_GPIO_PORT_B_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 1
#elif (SL_HAL_GPIO_PORT_A_PIN_COUNT > 0)
#define SL_HAL_GPIO_PORT_MAX 0
#else
#error "Max GPIO port number is undefined for this part."
#endif
/// Highest GPIO pin number.
#define SL_HAL_GPIO_PIN_MAX 15
/// @endcond
#define SL_HAL_GPIO_PORT_SIZE(port) ( \
(port) == 0 ? SL_HAL_GPIO_PORT_A_PIN_COUNT \
: (port) == 1 ? SL_HAL_GPIO_PORT_B_PIN_COUNT \
: (port) == 2 ? SL_HAL_GPIO_PORT_C_PIN_COUNT \
: (port) == 3 ? SL_HAL_GPIO_PORT_D_PIN_COUNT \
: (port) == 4 ? SL_HAL_GPIO_PORT_E_PIN_COUNT \
: (port) == 5 ? SL_HAL_GPIO_PORT_F_PIN_COUNT \
: (port) == 6 ? SL_HAL_GPIO_PORT_G_PIN_COUNT \
: (port) == 7 ? SL_HAL_GPIO_PORT_H_PIN_COUNT \
: (port) == 8 ? SL_HAL_GPIO_PORT_I_PIN_COUNT \
: (port) == 9 ? SL_HAL_GPIO_PORT_J_PIN_COUNT \
: (port) == 10 ? SL_HAL_GPIO_PORT_K_PIN_COUNT \
: 0)
#define SL_HAL_GPIO_PORT_MASK(port) ( \
((int)port) == 0 ? SL_HAL_GPIO_PORT_A_PIN_MASK \
: ((int)port) == 1 ? SL_HAL_GPIO_PORT_B_PIN_MASK \
: ((int)port) == 2 ? SL_HAL_GPIO_PORT_C_PIN_MASK \
: ((int)port) == 3 ? SL_HAL_GPIO_PORT_D_PIN_MASK \
: ((int)port) == 4 ? SL_HAL_GPIO_PORT_E_PIN_MASK \
: ((int)port) == 5 ? SL_HAL_GPIO_PORT_F_PIN_MASK \
: ((int)port) == 6 ? SL_HAL_GPIO_PORT_G_PIN_MASK \
: ((int)port) == 7 ? SL_HAL_GPIO_PORT_H_PIN_MASK \
: ((int)port) == 8 ? SL_HAL_GPIO_PORT_I_PIN_MASK \
: ((int)port) == 9 ? SL_HAL_GPIO_PORT_J_PIN_MASK \
: ((int)port) == 10 ? SL_HAL_GPIO_PORT_K_PIN_MASK \
: 0UL)
/// Validation of port.
#define SL_HAL_GPIO_PORT_IS_VALID(port) (SL_HAL_GPIO_PORT_MASK(port) != 0x0UL)
/// Validation of port and pin.
#define SL_HAL_GPIO_PORT_PIN_IS_VALID(port, pin) ((((SL_HAL_GPIO_PORT_MASK(port)) >> (pin)) & 0x1UL) == 0x1UL)
/// Max interrupt lines for external and EM4 interrupts.
#define SL_HAL_GPIO_INTERRUPT_MAX 15
/// Shift value for EM4WUEN
#define SL_HAL_GPIO_EM4WUEN_SHIFT _GPIO_EM4WUEN_EM4WUEN_SHIFT
/// Masks for even and odd interrupt bits.
#define SL_HAL_GPIO_INT_IF_EVEN_MASK ((_GPIO_IF_MASK) & 0x55555555UL)
#define SL_HAL_GPIO_INT_IF_ODD_MASK ((_GPIO_IF_MASK) & 0xAAAAAAAAUL)
/// Validation of mode.
#define SL_HAL_GPIO_MODE_IS_VALID(mode) ((mode & _GPIO_P_MODEL_MODE0_MASK) == mode)
/// Validation of interrupt number and pin.
#define SL_HAL_GPIO_INTNO_PIN_VALID(int_no, pin) (((int_no) & ~_GPIO_EXTIPINSELL_EXTIPINSEL0_MASK) == ((pin) & ~_GPIO_EXTIPINSELL_EXTIPINSEL0_MASK))
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* Set the mode for a GPIO pin.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[in] mode The desired pin mode.
* @param[in] output_value A value to set for the pin in the DOUT register. The DOUT setting is important for
* some input mode configurations to determine the pull-up/down direction.
******************************************************************************/
void sl_hal_gpio_set_pin_mode(const sl_gpio_t *gpio,
sl_gpio_mode_t mode,
bool output_value);
/***************************************************************************//**
* Get the mode for a GPIO pin.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
*
* @return Return the pin mode.
******************************************************************************/
sl_gpio_mode_t sl_hal_gpio_get_pin_mode(const sl_gpio_t *gpio);
/***************************************************************************//**
* Configure the GPIO external pin interrupt by connecting external interrupt id with gpio pin.
*
* @note This function configure the pin interrupt with pin ,port and external interrupt id as input.
* If external interrupt id is provided as input it will be considered as the input or else
* available interrupt number will be generated by looping through the interrupt group and will be used.
* User can provide SL_HAL_GPIO_INTERRUPT_UNAVAILABLE if user don't want to provide interrupt id.
* @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)
* @note It is recommended to disable interrupts before configuring the GPIO pin interrupt.
* See @ref sl_hal_gpio_disable_interrupts() for more information.
* The GPIO interrupt handler must be in place before enabling the interrupt.
* Notice that any pending interrupt for the selected interrupt is cleared by this function.
* Notice that only interrupt will be configured by this function. It is not enabled.
* It is recommended to enable interrupts after configuring the GPIO pin interrupt if needed.
* See @ref sl_hal_gpio_enable_interrupts() for more information.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[in] int_no The interrupt number to trigger.
* @param[in] flags Interrupt configuration flags. @ref sl_hal_gpio_interrupt_flag_t for more information.
*
* @return Return the available interrupt number
******************************************************************************/
int32_t sl_hal_gpio_configure_external_interrupt(const sl_gpio_t *gpio,
int32_t int_no,
sl_gpio_interrupt_flag_t flags);
/**************************************************************************//**
* Enable GPIO pin wake-up from EM4. When the function exits,
* EM4 mode can be safely entered.
*
* @note It is assumed that the GPIO pin modes are set correctly.
* Valid modes are SL_GPIO_MODE_INPUT and SL_GPIO_MODE_INPUT_PULL.
*
* @param[in] pinmask A bitmask containing the bitwise logic OR of which GPIO pin(s) to enable.
* @param[in] polaritymask A bitmask containing the bitwise logic OR of GPIO pin(s) wake-up polarity.
*****************************************************************************/
void sl_hal_gpio_enable_pin_em4_wakeup(uint32_t pinmask,
uint32_t polaritymask);
/***************************************************************************//**
* Configure EM4WU pins as external level-sensitive interrupts.
*
* @note It is recommended to disable interrupts before configuring the GPIO pin interrupt.
* See @ref sl_hal_gpio_disable_interrupts() for more information.
* The provided port, pin and int_no inputs should be valid EM4 related parameters
* because there are dedicated port, pin and EM4 Wakeup interrupt combination for
* configuring the port, pin for EM4 functionality.
* User can provide SL_HAL_GPIO_INTERRUPT_UNAVAILABLE if user don't want to provide interrupt id.
* The GPIO interrupt handler must be in place before enabling the interrupt.
* Notice that any pending interrupt for the selected interrupt is cleared by this function.
* Notice that any only EM4WU interrupt is configured by this function. It is not enabled.
* It is recommended to enable interrupts after configuring the GPIO pin interrupt if needed.
* See @ref sl_hal_gpio_enable_interrupts() for more information.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
* @param[in] int_no The EM4WU interrupt number to trigger.
* @param[in] polarity true = Active high level-sensitive interrupt.
* false = Active low level-sensitive interrupt.
*
* @return Return the available EM4WU interrupt number
******************************************************************************/
int32_t sl_hal_gpio_configure_wakeup_em4_external_interrupt(const sl_gpio_t *gpio,
int32_t int_no,
bool polarity);
/***************************************************************************//**
* Lock the GPIO configuration.
*
* @note Configuration lock affects the GPIO_Px_MODEL, GPIO_Px_MODEH, GPIO_Px_CTRL,
* GPIO_Px_PINLOCKN, GPIO_EXTIPSELL, GPIO_EXTIPSELH, GPIO_EXTIPINSELL,
* GPIO_EXTIPINSELH, GPIO_INSENSE, GPIO_ROUTE, GPIO_ROUTEPEN, and
* GPIO_ROUTELOC0 registers when they are present on a specific device.
* @note Unwanted or accidental changes to GPIO configuration can be avoided by
* using the configuration lock register. Any value other than 0xA534 written to
* GPIO_LOCK enables the configuration lock. Pins are unlocked by a reset or
* by writing 0xA534 to the GPIO_LOCK register.
******************************************************************************/
__INLINE void sl_hal_gpio_lock(void)
{
GPIO->LOCK = ~GPIO_LOCK_LOCKKEY_UNLOCK;
}
/***************************************************************************//**
* Unlock the GPIO configuration.
*
* @note Configuration lock affects the GPIO_Px_MODEL, GPIO_Px_MODEH, GPIO_Px_CTRL,
* GPIO_Px_PINLOCKN, GPIO_EXTIPSELL, GPIO_EXTIPSELH, GPIO_EXTIPINSELL,
* GPIO_EXTIPINSELH, GPIO_INSENSE, GPIO_ROUTE, GPIO_ROUTEPEN, and
* GPIO_ROUTELOC0 registers when they are present on a specific device.
* @note Unwanted or accidental changes to GPIO configuration can be avoided by
* using the configuration lock register. Any value other than 0xA534 written to
* GPIO_LOCK enables the configuration lock. Pins are unlocked by a reset or
* by writing 0xA534 to the GPIO_LOCK register.
******************************************************************************/
__INLINE void sl_hal_gpio_unlock(void)
{
GPIO->LOCK = GPIO_LOCK_LOCKKEY_UNLOCK;
}
/***************************************************************************//**
* Gets the GPIO configuration state.
*
* @return Return the GPIO lock state.
******************************************************************************/
__INLINE uint32_t sl_hal_gpio_get_lock_status(void)
{
return GPIO->GPIOLOCKSTATUS;
}
/***************************************************************************//**
* Set a single pin in GPIO data out register to 1.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_GPIO, SL_CODE_CLASS_TIME_CRITICAL)
__INLINE void sl_hal_gpio_set_pin(const sl_gpio_t *gpio)
{
EFM_ASSERT(gpio != NULL);
EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
GPIO->P_SET[gpio->port].DOUT = 1UL << gpio->pin;
}
/***************************************************************************//**
* Set bits GPIO data out register to 1.
*
* @param[in] port The GPIO port to access.
* @param[in] pins Bit mask for bits to set to 1 in DOUT register.
******************************************************************************/
__INLINE void sl_hal_gpio_set_port(sl_gpio_port_t port,
uint32_t pins)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
GPIO->P_SET[port].DOUT = pins;
}
/***************************************************************************//**
* Set GPIO port data out register.
*
* @param[in] port The GPIO port to access.
* @param[in] val Value to write to port data out register.
* @param[in] mask Mask indicating which bits to modify.
******************************************************************************/
__INLINE void sl_hal_gpio_set_port_value(sl_gpio_port_t port,
uint32_t val,
uint32_t mask)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
GPIO->P[port].DOUT = (GPIO->P[port].DOUT & ~mask) | (val & mask);
}
/***************************************************************************//**
* Set slewrate for pins on a GPIO port which are configured into normal modes.
*
* @param[in] port The GPIO port to configure.
* @param[in] slewrate The slewrate to configure for pins on this GPIO port.
******************************************************************************/
__INLINE void sl_hal_gpio_set_slew_rate(sl_gpio_port_t port,
uint8_t slewrate)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
EFM_ASSERT(slewrate <= (_GPIO_P_CTRL_SLEWRATE_MASK
>> _GPIO_P_CTRL_SLEWRATE_SHIFT));
GPIO->P[port].CTRL = (GPIO->P[port].CTRL
& ~_GPIO_P_CTRL_SLEWRATE_MASK)
| (slewrate << _GPIO_P_CTRL_SLEWRATE_SHIFT);
}
/***************************************************************************//**
* Set slewrate for pins on a GPIO port which are configured into alternate modes.
*
* @param[in] port The GPIO port to configure.
* @param[in] slewrate_alt The slewrate to configure for pins using alternate modes on this GPIO port.
******************************************************************************/
__INLINE void sl_hal_gpio_set_slew_rate_alternate(sl_gpio_port_t port,
uint8_t slewrate_alt)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
EFM_ASSERT(slewrate_alt <= (_GPIO_P_CTRL_SLEWRATEALT_MASK
>> _GPIO_P_CTRL_SLEWRATEALT_SHIFT));
GPIO->P[port].CTRL = (GPIO->P[port].CTRL
& ~_GPIO_P_CTRL_SLEWRATEALT_MASK)
| (slewrate_alt << _GPIO_P_CTRL_SLEWRATEALT_SHIFT);
}
/***************************************************************************//**
* Get slewrate for pins on a GPIO port.
*
* @param[in] port The GPIO port to access to get slew rate.
*
* @return Return the slewrate setting for the selected GPIO port.
******************************************************************************/
__INLINE uint8_t sl_hal_gpio_get_slew_rate(sl_gpio_port_t port)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
return (GPIO->P[port].CTRL & _GPIO_P_CTRL_SLEWRATE_MASK) >> _GPIO_P_CTRL_SLEWRATE_SHIFT;
}
/***************************************************************************//**
* Get slewrate for pins on a GPIO port which are configured into alternate modes.
*
* @param[in] port The GPIO port to access to get slew rate.
*
* @return Return the alternate slewrate setting for selected GPIO port.
******************************************************************************/
__INLINE uint8_t sl_hal_gpio_get_slew_rate_alternate(sl_gpio_port_t port)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
return (GPIO->P[port].CTRL & _GPIO_P_CTRL_SLEWRATEALT_MASK) >> _GPIO_P_CTRL_SLEWRATEALT_SHIFT;
}
/***************************************************************************//**
* Set a single pin in GPIO data out port register to 0.
*
* @param[in] gpio Pointer to GPIO structure with port and pin
******************************************************************************/
__INLINE void sl_hal_gpio_clear_pin(const sl_gpio_t *gpio)
{
EFM_ASSERT(gpio != NULL);
EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
GPIO->P_CLR[gpio->port].DOUT = 1UL << gpio->pin;
}
/***************************************************************************//**
* Set bits in DOUT register for a port to 0.
*
* @param[in] port The GPIO port to access.
* @param[in] pins Bit mask for bits to clear in DOUT register.
******************************************************************************/
__INLINE void sl_hal_gpio_clear_port(sl_gpio_port_t port,
uint32_t pins)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
GPIO->P_CLR[port].DOUT = pins;
}
/***************************************************************************//**
* Read the pad value for a single pin in a GPIO port.
*
* @param[in] gpio Pointer to GPIO structure with port and pin.
*
* @return The pin value, 0 or 1.
******************************************************************************/
__INLINE bool sl_hal_gpio_get_pin_input(const sl_gpio_t *gpio)
{
EFM_ASSERT(gpio != NULL);
EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
bool pin_input = ((GPIO->P[gpio->port].DIN) >> gpio->pin) & 1UL;
return pin_input;
}
/***************************************************************************//**
* Get current setting for a pin in a GPIO port data out register.
*
* @param[in] gpio Pointer to GPIO structure with port and pin.
*
* @return The DOUT setting for the requested pin, 0 or 1.
******************************************************************************/
__INLINE bool sl_hal_gpio_get_pin_output(const sl_gpio_t *gpio)
{
EFM_ASSERT(gpio != NULL);
EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
bool pin_output = ((GPIO->P[gpio->port].DOUT) >> gpio->pin) & 1UL;
return pin_output;
}
/***************************************************************************//**
* Read the pad values for GPIO port.
*
* @param[in] port The GPIO port to access.
*
* @return The pad values for the GPIO port.
******************************************************************************/
__INLINE uint32_t sl_hal_gpio_get_port_input(sl_gpio_port_t port)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
return GPIO->P[port].DIN;
}
/***************************************************************************//**
* Get current setting for a GPIO port data out register.
*
* @param[in] port The GPIO port to access.
*
* @return The data out setting for the requested port.
******************************************************************************/
__INLINE uint32_t sl_hal_gpio_get_port_output(sl_gpio_port_t port)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
return GPIO->P[port].DOUT;
}
/***************************************************************************//**
* Toggle a single pin in GPIO port data out register.
*
* @param[in] gpio Pointer to GPIO structure with port and pin.
******************************************************************************/
__INLINE void sl_hal_gpio_toggle_pin(const sl_gpio_t *gpio)
{
EFM_ASSERT(gpio != NULL);
EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
GPIO->P_TGL[gpio->port].DOUT = 1UL << gpio->pin;
}
/***************************************************************************//**
* Toggle pins in GPIO port data out register.
*
* @param[in] port The GPIO port to access.
* @param[in] pins Bit mask with pins to toggle.
******************************************************************************/
__INLINE void sl_hal_gpio_toggle_port(sl_gpio_port_t port,
uint32_t pins)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
GPIO->P_TGL[port].DOUT = pins;
}
/***************************************************************************//**
* Enable one or more GPIO interrupts.
*
* @param[in] flags GPIO interrupt sources to enable.
******************************************************************************/
__INLINE void sl_hal_gpio_enable_interrupts(uint32_t flags)
{
GPIO->IEN_SET = flags;
}
/***************************************************************************//**
* Disable one or more GPIO interrupts.
*
* @param[in] flags GPIO interrupt sources to disable.
******************************************************************************/
__INLINE void sl_hal_gpio_disable_interrupts(uint32_t flags)
{
GPIO->IEN_CLR = flags;
}
/***************************************************************************//**
* Clear one or more pending GPIO interrupts.
*
* @param[in] flags Bitwise logic OR of GPIO interrupt sources to clear.
******************************************************************************/
__INLINE void sl_hal_gpio_clear_interrupts(uint32_t flags)
{
GPIO->IF_CLR = flags;
}
/**************************************************************************//**
* Set one or more pending GPIO interrupts from SW.
*
* @param[in] flags GPIO interrupt sources to set to pending.
*****************************************************************************/
__INLINE void sl_hal_gpio_set_interrupts(uint32_t flags)
{
GPIO->IF_SET = flags;
}
/***************************************************************************//**
* Get pending GPIO interrupts.
*
* @return GPIO interrupt sources pending.
******************************************************************************/
__INLINE uint32_t sl_hal_gpio_get_pending_interrupts(void)
{
return GPIO->IF;
}
/***************************************************************************//**
* Get enabled GPIO interrupts.
*
* @return Enabled GPIO interrupt sources.
******************************************************************************/
__INLINE uint32_t sl_hal_gpio_get_enabled_interrupts(void)
{
return GPIO->IEN;
}
/***************************************************************************//**
* Get enabled and pending GPIO interrupt flags.
*
* @return Enabled and pending interrupt sources.
*
* @note Useful for handling more interrupt sources in the same interrupt handler.
******************************************************************************/
__INLINE uint32_t sl_hal_gpio_get_enabled_pending_interrupts(void)
{
uint32_t tmp;
tmp = GPIO->IEN;
return GPIO->IF & tmp;
}
/***************************************************************************//**
* The available external interrupt number getter.
*
* @param[in] pin The GPIO pin to access.
* @param[in] enabled_interrupts_mask Contains enabled GPIO interrupts mask.
*
* @return The available interrupt number based on interrupt and pin grouping.
******************************************************************************/
__INLINE int32_t sl_hal_gpio_get_external_interrupt_number(uint8_t pin,
uint32_t enabled_interrupts_mask)
{
uint32_t interrupt_to_check;
uint32_t int_group_start = (pin & 0xFFC);
int32_t int_no = -1;
// loop through the interrupt group, starting
// from the pin number, and take
// the first available.
for (uint8_t i = 0; i < 4; i++) {
interrupt_to_check = int_group_start + ((pin + i) & 0x3); // modulo 4
if (((enabled_interrupts_mask >> interrupt_to_check) & 0x1) == 0) {
int_no = interrupt_to_check;
break;
}
}
return int_no;
}
/***************************************************************************//**
* The available em4 wakeup interrupt number getter.
*
* @param[in] gpio Pointer to GPIO structure with port and pin.
*
* @return The available em4 wakeup interrupt number based on associated port and pin.
******************************************************************************/
__INLINE int32_t sl_hal_gpio_get_em4_interrupt_number(const sl_gpio_t *gpio)
{
EFM_ASSERT(gpio != NULL);
int32_t em4_int_no;
if (false) {
// Check all the EM4WU Pins and check if given port, pin matches any of them.
#if defined(GPIO_EM4WU0_PORT)
} else if (GPIO_EM4WU0_PORT == gpio->port && GPIO_EM4WU0_PIN == gpio->pin) {
em4_int_no = 0;
#endif
#if defined(GPIO_EM4WU1_PORT)
} else if (GPIO_EM4WU1_PORT == gpio->port && GPIO_EM4WU1_PIN == gpio->pin) {
em4_int_no = 1;
#endif
#if defined(GPIO_EM4WU3_PORT)
} else if (GPIO_EM4WU3_PORT == gpio->port && GPIO_EM4WU3_PIN == gpio->pin) {
em4_int_no = 3;
#endif
#if defined(GPIO_EM4WU4_PORT)
} else if (GPIO_EM4WU4_PORT == gpio->port && GPIO_EM4WU4_PIN == gpio->pin) {
em4_int_no = 4;
#endif
#if defined(GPIO_EM4WU6_PORT)
} else if (GPIO_EM4WU6_PORT == gpio->port && GPIO_EM4WU6_PIN == gpio->pin) {
em4_int_no = 6;
#endif
#if defined(GPIO_EM4WU7_PORT)
} else if (GPIO_EM4WU7_PORT == gpio->port && GPIO_EM4WU7_PIN == gpio->pin) {
em4_int_no = 7;
#endif
#if defined(GPIO_EM4WU8_PORT)
} else if (GPIO_EM4WU8_PORT == gpio->port && GPIO_EM4WU8_PIN == gpio->pin) {
em4_int_no = 8;
#endif
#if defined(GPIO_EM4WU9_PORT)
} else if (GPIO_EM4WU9_PORT == gpio->port && GPIO_EM4WU9_PIN == gpio->pin) {
em4_int_no = 9;
#endif
#if defined(GPIO_EM4WU10_PORT)
} else if (GPIO_EM4WU10_PORT == gpio->port && GPIO_EM4WU10_PIN == gpio->pin) {
em4_int_no = 10;
#endif
} else {
em4_int_no = -1;
}
return em4_int_no;
}
/*************************************************************************//**
* Disable GPIO pin wake-up from EM4.
*
* @param[in] pinmask Bit mask containing the bitwise logic OR of which GPIO pin(s) to disable.
*****************************************************************************/
__INLINE void sl_hal_gpio_disable_pin_em4_wakeup(uint32_t pinmask)
{
EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0UL);
GPIO->EM4WUEN &= ~pinmask;
}
/**************************************************************************//**
* Enable GPIO pin retention of output enable, output value, pull enable, and
* pull direction in EM4.
*
* @note The behavior of this function depends on the configured GPIO retention mode.
* If the GPIO retention mode is configured to be "SWUNLATCH" then this
* function will not change anything. If the retention mode is anything else
* then this function will set the GPIO retention mode to "EM4EXIT" when the
* enable argument is true, and "Disabled" when false.
*
* @param[in] enable true - enable EM4 pin retention.
* false - disable EM4 pin retention.
*****************************************************************************/
__INLINE void sl_hal_gpio_set_pin_em4_retention(bool enable)
{
// Leave configuration alone when software unlatch is used.
uint32_t mode = EMU->EM4CTRL & _EMU_EM4CTRL_EM4IORETMODE_MASK;
if (mode == EMU_EM4CTRL_EM4IORETMODE_SWUNLATCH) {
return;
}
if (enable) {
EMU->EM4CTRL = (EMU->EM4CTRL & ~_EMU_EM4CTRL_EM4IORETMODE_MASK)
| EMU_EM4CTRL_EM4IORETMODE_EM4EXIT;
} else {
EMU->EM4CTRL = (EMU->EM4CTRL & ~_EMU_EM4CTRL_EM4IORETMODE_MASK)
| EMU_EM4CTRL_EM4IORETMODE_DISABLE;
}
}
/**************************************************************************//**
* Check which GPIO pin(s) that caused a wake-up from EM4.
*
* @return Bit mask containing the bitwise logic OR of which GPIO pin(s) caused the wake-up.
*****************************************************************************/
__INLINE uint32_t sl_hal_gpio_get_pin_em4_wakeup_cause(void)
{
return GPIO->IF & _GPIO_EM4WUEN_EM4WUEN_MASK;
}
/***************************************************************************//**
* Enable/Disable serial wire output pin.
*
* @note Enabling this pin is not sufficient to fully enable serial wire output,
* which is also dependent on issues outside the GPIO module.
* @note If debug port is locked, SWO pin is not disabled automatically. To avoid
* information leakage through SWO, disable SWO pin after locking debug port.
*
* @param[in] enable false - disable serial wire viewer pin (default after reset).
* true - enable serial wire viewer pin.
******************************************************************************/
__INLINE void sl_hal_gpio_enable_debug_swo(bool enable)
{
uint32_t bit = enable ? 0x1UL : 0x0UL;
if (bit != 0U) {
GPIO->TRACEROUTEPEN_SET = 1UL << _GPIO_TRACEROUTEPEN_SWVPEN_SHIFT;
} else {
GPIO->TRACEROUTEPEN_CLR = 1UL << _GPIO_TRACEROUTEPEN_SWVPEN_SHIFT;
}
}
/***************************************************************************//**
* Enable/disable serial wire clock pin.
*
* @note Disabling SWDClk will disable the debug interface, which may result in
* a lockout if done early in startup (before debugger is able to halt core).
*
* @param[in] enable false - disable serial wire clock.
* true - enable serial wire clock (default after reset).
******************************************************************************/
__INLINE void sl_hal_gpio_enable_debug_swd_clk(bool enable)
{
uint32_t bit = enable ? 0x1UL : 0x0UL;
if (bit != 0U) {
GPIO->DBGROUTEPEN_SET = 1UL << _GPIO_DBGROUTEPEN_SWCLKTCKPEN_SHIFT;
} else {
GPIO->DBGROUTEPEN_CLR = 1UL << _GPIO_DBGROUTEPEN_SWCLKTCKPEN_SHIFT;
}
}
/***************************************************************************//**
* Enable/disable serial wire data I/O pin.
*
* @note Disabling SWDClk will disable the debug interface, which may result in
* a lockout if done early in startup (before debugger is able to halt core).
*
* @param[in] enable false - disable serial wire data pin.
* true - enable serial wire data pin (default after reset).
******************************************************************************/
__INLINE void sl_hal_gpio_enable_debug_swd_io(bool enable)
{
uint32_t bit = enable ? 0x1UL : 0x0UL;
if (bit != 0U) {
GPIO->DBGROUTEPEN_SET = 1UL << _GPIO_DBGROUTEPEN_SWDIOTMSPEN_SHIFT;
} else {
GPIO->DBGROUTEPEN_CLR = 1UL << _GPIO_DBGROUTEPEN_SWDIOTMSPEN_SHIFT;
}
}
/** @} (end addtogroup gpio) */
#ifdef __cplusplus
}
#endif
#endif /* GPIO_PRESENT */
#endif /* SL_HAL_GPIO_H */

View File

@@ -0,0 +1,89 @@
/***************************************************************************//**
* @file
* @brief API defining access to SYSCFG registers
*******************************************************************************
* # 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_HAL_SYSCFG_H
#define SL_HAL_SYSCFG_H
#include <stdint.h>
#if defined(SL_TRUSTZONE_NONSECURE)
#include "sli_tz_service_syscfg.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup syscfg SYSTEM CONFIGURATION - System Configurations
* @brief Syscfg API
* @details
*
* @{
******************************************************************************/
/*******************************************************************************
********************************* DEFINES *********************************
******************************************************************************/
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/*******************************************************************************
******************************** TZ SERVICES **********************************
******************************************************************************/
/*******************************************************************************
* @brief
* Reads CHIPREV register.
******************************************************************************/
uint32_t sl_hal_syscfg_read_chip_rev(void);
/*******************************************************************************
* @brief
* Set SYSTICEXTCLKEN bit in CFGSYSTIC to one.
******************************************************************************/
void sl_hal_syscfg_set_systicextclken_cfgsystic(void);
/*******************************************************************************
* @brief
* Clear SYSTICEXTCLKEN bit in CFGSYSTIC to zero.
******************************************************************************/
void sl_hal_syscfg_clear_systicextclken_cfgsystic(void);
#ifdef __cplusplus
}
#endif
#endif // SL_HAL_SYSCFG_H

View File

@@ -0,0 +1,445 @@
/***************************************************************************//**
* @file
* @brief System Real Time Counter (SYSRTC) peripheral 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_HAL_SYSRTC_H
#define SL_HAL_SYSRTC_H
#include "em_device.h"
#if defined(SYSRTC_COUNT) && (SYSRTC_COUNT > 0)
#include <stdbool.h>
#include "sl_code_classification.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include "sl_hal_sysrtc_compat.h"
#include "sl_enum.h"
/***************************************************************************//**
* @addtogroup sysrtc
* @{
******************************************************************************/
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
/// Minimum compare channels for SYSRTC group.
#define SYSRTC_GROUP_MIN_CHANNEL_COMPARE 1u
/// Maximum compare channels for SYSRTC group.
#define SYSRTC_GROUP_MAX_CHANNEL_COMPARE 2u
/// Minimum capture channels for SYSRTC group.
#define SYSRTC_GROUP_MIN_CHANNEL_CAPTURE 0u
/// Maximum capture channels for SYSRTC group.
#define SYSRTC_GROUP_MAX_CHANNEL_CAPTURE 1u
/// Sysrtc group number.
#if !defined(SYSRTC_GROUP_NUMBER)
#define SYSRTC_GROUP_NUMBER 1u
#endif
/// Validation of valid SYSRTC group for assert statements.
#define SYSRTC_GROUP_VALID(group) ((unsigned)(group) < SYSRTC_GROUP_NUMBER)
/*******************************************************************************
********************************* ENUM ************************************
******************************************************************************/
/// Capture input edge select.
SL_ENUM(sl_hal_sysrtc_capture_edge_t) {
SL_HAL_SYSRTC_CAPTURE_EDGE_RISING = 0, ///< Rising edges detected.
SL_HAL_SYSRTC_CAPTURE_EDGE_FALLING, ///< Falling edges detected.
SL_HAL_SYSRTC_CAPTURE_EDGE_BOTH ///< Both edges detected.
};
/// Compare match output action mode.
SL_ENUM(sl_hal_sysrtc_compare_match_out_action_t) {
SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CLEAR = 0, ///< Clear output.
SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_SET, ///< Set output.
SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_PULSE, ///< Generate a pulse.
SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_TOGGLE, ///< Toggle output.
SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CMPIF ///< Export CMPIF.
};
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/// SYSRTC configuration structure.
typedef struct {
bool enable_debug_run; ///< Counter shall keep running during debug halt.
} sl_hal_sysrtc_config_t;
/// Suggested default values for SYSRTC configuration structure.
#define SYSRTC_CONFIG_DEFAULT \
{ \
false, /* Disable updating during debug halt. */ \
}
/// Compare channel configuration structure.
typedef struct {
sl_hal_sysrtc_compare_match_out_action_t compare_match_out_action; ///< Compare mode channel match output action.
} sl_hal_sysrtc_group_channel_compare_config_t;
/// Capture channel configuration structure.
typedef struct {
sl_hal_sysrtc_capture_edge_t capture_input_edge; ///< Capture mode channel input edge.
} sl_hal_sysrtc_group_channel_capture_config_t;
/// Group configuration structure.
typedef struct {
bool compare_channel0_enable; ///< Enable/Disable compare channel 0
bool compare_channel1_enable; ///< Enable/Disable compare channel 1
bool capture_channel0_enable; ///< Enable/Disable capture channel 0
sl_hal_sysrtc_group_channel_compare_config_t const *p_compare_channel0_config; ///< Pointer to compare channel 0 config
sl_hal_sysrtc_group_channel_compare_config_t const *p_compare_channel1_config; ///< Pointer to compare channel 1 config
sl_hal_sysrtc_group_channel_capture_config_t const *p_capture_channel0_config; ///< Pointer to capture channel 0 config
} sl_hal_sysrtc_group_config_t;
/// Suggested default values for compare channel configuration structure.
#define SYSRTC_GROUP_CHANNEL_COMPARE_CONFIG_DEFAULT \
{ \
SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_PULSE \
}
/// Compare channel configuration for starting HFXO using PRS.
#define SYSRTC_GROUP_CHANNEL_COMPARE_CONFIG_EARLY_WAKEUP \
{ \
SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CMPIF \
}
/// Suggested default values for capture channel configuration structure.
#define SYSRTC_GROUP_CHANNEL_CAPTURE_CONFIG_DEFAULT \
{ \
SL_HAL_SYSRTC_CAPTURE_EDGE_RISING \
}
/// Suggested default values for SYSRTC group configuration structure.
#define SYSRTC_GROUP_CONFIG_DEFAULT \
{ \
true, /* Enable compare channel 0. */ \
false, /* Disable compare channel 1. */ \
false, /* Disable capture channel 0. */ \
NULL, /* NULL Pointer to configuration structure for compare channel 0*/ \
NULL, /* NULL Pointer to configuration structure for compare channel 1*/ \
NULL /* NULL Pointer to configuration structure for capture channel 0*/ \
}
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* Initializes SYSRTC module.
*
* Note that the compare values must be set separately with
* (sl_hal_sysrtc_set_group_compare_channel_value()), which should probably be
* done prior to the use of this function if configuring the SYSRTC to start
* when initialization is completed.
*
* @param[in] p_config A pointer to the SYSRTC initialization structure
* variable.
******************************************************************************/
void sl_hal_sysrtc_init(const sl_hal_sysrtc_config_t *p_config);
/***************************************************************************//**
* Enables SYSRTC counting.
******************************************************************************/
void sl_hal_sysrtc_enable(void);
/***************************************************************************//**
* Disables SYSRTC counting.
******************************************************************************/
void sl_hal_sysrtc_disable(void);
/***************************************************************************//**
* Waits for the SYSRTC to complete all synchronization of register changes
* and commands.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
__INLINE void sl_hal_sysrtc_wait_sync(void)
{
while ((SYSRTC0->EN & SYSRTC_EN_EN) && (SYSRTC0->SYNCBUSY != 0U)) {
// Wait for all synchronizations to finish
}
}
/***************************************************************************//**
* Waits for the SYSRTC to complete reseting or disabling procedure.
******************************************************************************/
__INLINE void sl_hal_sysrtc_wait_ready(void)
{
while ((SYSRTC0->SWRST & _SYSRTC_SWRST_RESETTING_MASK) || (SYSRTC0->EN & _SYSRTC_EN_DISABLING_MASK) || (SYSRTC0->SYNCBUSY != 0U)) {
// Wait for all synchronizations to finish
}
}
/***************************************************************************//**
* Starts SYSRTC counter.
*
* This function will send a start command to the SYSRTC peripheral. The SYSRTC
* peripheral will use some LF clock ticks before the command is executed.
* The sl_hal_sysrtc_wait_sync() function can be used to wait for the start
* command to be executed.
*
* @note This function requires the SYSRTC to be enabled.
******************************************************************************/
__INLINE void sl_hal_sysrtc_start(void)
{
sl_hal_sysrtc_wait_sync();
SYSRTC0->CMD = SYSRTC_CMD_START;
}
/***************************************************************************//**
* Stops the SYSRTC counter.
*
* This function will send a stop command to the SYSRTC peripheral. The SYSRTC
* peripheral will use some LF clock ticks before the command is executed.
* The sl_hal_sysrtc_wait_sync() function can be used to wait for the stop
* command to be executed.
*
* @note This function requires the SYSRTC to be enabled.
******************************************************************************/
__INLINE void sl_hal_sysrtc_stop(void)
{
sl_hal_sysrtc_wait_sync();
SYSRTC0->CMD = SYSRTC_CMD_STOP;
}
/***************************************************************************//**
* Restores SYSRTC to its reset state.
******************************************************************************/
void sl_hal_sysrtc_reset(void);
/***************************************************************************//**
* Gets SYSRTC STATUS register value.
*
* @return Current STATUS register value.
******************************************************************************/
__INLINE uint32_t sl_hal_sysrtc_get_status(void)
{
return SYSRTC0->STATUS;
}
/***************************************************************************//**
* Locks SYSRTC registers.
*
* @note When SYSRTC registers are locked SYSRTC_EN, SYSRTC_CFG, SYSRTC_CMD,
* SYSRTC_SWRST, SYSRTC_CNT and SYSRTC_TOPCNT registers cannot be written
* to.
******************************************************************************/
__INLINE void sl_hal_sysrtc_lock(void)
{
SYSRTC0->LOCK = ~SYSRTC_LOCK_LOCKKEY_UNLOCK;
}
/***************************************************************************//**
* Unlocks SYSRTC registers.
*
* @note When SYSRTC registers are locked SYSRTC_EN, SYSRTC_CFG, SYSRTC_CMD,
* SYSRTC_SWRST, SYSRTC_CNT and SYSRTC_TOPCNT registers cannot be written
* to.
******************************************************************************/
__INLINE void sl_hal_sysrtc_unlock(void)
{
SYSRTC0->LOCK = SYSRTC_LOCK_LOCKKEY_UNLOCK;
}
/***************************************************************************//**
* Gets SYSRTC counter value.
*
* @return Current SYSRTC counter value.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
__INLINE uint32_t sl_hal_sysrtc_get_counter(void)
{
// Wait for Counter to synchronize before getting value
sl_hal_sysrtc_wait_sync();
return SYSRTC0->CNT;
}
/***************************************************************************//**
* Sets the SYSRTC counter value.
*
* @param[in] value The new SYSRTC counter value.
******************************************************************************/
__INLINE void sl_hal_sysrtc_set_counter(uint32_t value)
{
// Wait for Counter to synchronize before getting value
sl_hal_sysrtc_wait_sync();
SYSRTC0->CNT = value;
}
/***************************************************************************//**
* Initializes the selected SYSRTC group.
*
* @param[in] group_number SYSRTC group number to use.
*
* @param[in] p_group_config Pointer to group configuration structure
* variable.
******************************************************************************/
void sl_hal_sysrtc_init_group(uint8_t group_number,
sl_hal_sysrtc_group_config_t const *p_group_config);
/***************************************************************************//**
* Enables one or more SYSRTC interrupts for the given group.
*
* @note Depending on the use, a pending interrupt may already be set prior to
* enabling the interrupt. To ignore a pending interrupt, consider using
* sl_hal_sysrtc_clear_group_interrupts() prior to enabling the interrupt.
*
* @param[in] group_number SYSRTC group number to use.
*
* @param[in] flags SYSRTC interrupt sources to enable.
* Use a set of interrupt flags OR-ed together to set
* multiple interrupt sources for the given SYSRTC group.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
void sl_hal_sysrtc_enable_group_interrupts(uint8_t group_number,
uint32_t flags);
/***************************************************************************//**
* Disables one or more SYSRTC interrupts for the given group.
*
* @param[in] group_number SYSRTC group number to use.
*
* @param[in] flags SYSRTC interrupt sources to disable.
* Use a set of interrupt flags OR-ed together to disable
* multiple interrupt sources for the given SYSRTC group.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
void sl_hal_sysrtc_disable_group_interrupts(uint8_t group_number,
uint32_t flags);
/***************************************************************************//**
* Clears one or more pending SYSRTC interrupts for the given group.
*
* @param[in] group_number SYSRTC group number to use.
*
* @param[in] flags SYSRTC interrupt sources to clear.
* Use a set of interrupt flags OR-ed together to clear
* multiple interrupt sources for the given SYSRTC group.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
void sl_hal_sysrtc_clear_group_interrupts(uint8_t group_number,
uint32_t flags);
/***************************************************************************//**
* Gets pending SYSRTC interrupt flags for the given group.
*
* @note Event bits are not cleared by using this function.
*
* @param[in] group_number SYSRTC group number to use.
*
* @return Pending SYSRTC interrupt sources.
* Returns a set of interrupt flags OR-ed together for multiple
* interrupt sources in the SYSRTC group.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
uint32_t sl_hal_sysrtc_get_group_interrupts(uint8_t group_number);
/***************************************************************************//**
* Gets enabled and pending SYSRTC interrupt flags.
* Useful for handling more interrupt sources in the same interrupt handler.
*
* @note Interrupt flags are not cleared by using this function.
*
* @param[in] group_number SYSRTC group number to use.
*
* @return Pending and enabled SYSRTC interrupt sources.
* The return value is the bitwise AND of
* - the enabled interrupt sources in SYSRTC_GRPx_IEN and
* - the pending interrupt flags SYSRTC_GRPx_IF.
******************************************************************************/
uint32_t sl_hal_sysrtc_get_group_enabled_interrupts(uint8_t group_number);
/***************************************************************************//**
* Sets one or more pending SYSRTC interrupts for the given group from Software.
*
* @param[in] group_number SYSRTC group number to use.
*
* @param[in] flags SYSRTC interrupt sources to set to pending.
* Use a set of interrupt flags OR-ed together to set
* multiple interrupt sources for the SYSRTC group.
******************************************************************************/
void sl_hal_sysrtc_set_group_interrupts(uint8_t group_number,
uint32_t flags);
/***************************************************************************//**
* Gets SYSRTC compare register value for selected channel of given group.
*
* @param[in] group_number SYSRTC group number to use.
*
* @param[in] channel Channel selector.
*
* @return Compare register value.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
uint32_t sl_hal_sysrtc_get_group_compare_channel_value(uint8_t group_number,
uint8_t channel);
/***************************************************************************//**
* Sets SYSRTC compare register value for selected channel of given group.
*
* @param[in] group_number SYSRTC group number to use.
*
* @param[in] channel Channel selector.
*
* @param[in] value Compare register value.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
void sl_hal_sysrtc_set_group_compare_channel_value(uint8_t group_number,
uint8_t channel,
uint32_t value);
/***************************************************************************//**
* Gets SYSRTC input capture register value for capture channel of given group.
*
* @param[in] group_number SYSRTC group number to use.
*
* @return Capture register value.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
uint32_t sl_hal_sysrtc_get_group_capture_channel_value(uint8_t group_number);
/** @} (end addtogroup sysrtc) */
#ifdef __cplusplus
}
#endif
#endif /* defined(SYSRTC_COUNT) && (SYSRTC_COUNT > 0) */
#endif /* SL_HAL_SYSRTC_H */

View File

@@ -0,0 +1,89 @@
/***************************************************************************//**
* @file
* @brief SYSRTC Compatibility Layer.
*******************************************************************************
* # 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_HAL_SYSRTC_COMPAT_H
#define SL_HAL_SYSRTC_COMPAT_H
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
********************************* DEFINES *********************************
******************************************************************************/
// Enum.
#define SL_SYSRTC_CAPTURE_EDGE_RISING SL_HAL_SYSRTC_CAPTURE_EDGE_RISING
#define SL_SYSRTC_CAPTURE_EDGE_FALLING SL_HAL_SYSRTC_CAPTURE_EDGE_FALLING
#define SL_SYSRTC_CAPTURE_EDGE_BOTH SL_HAL_SYSRTC_CAPTURE_EDGE_BOTH
#define SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CLEAR SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CLEAR
#define SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_SET SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_SET
#define SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_PULSE SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_PULSE
#define SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_TOGGLE SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_TOGGLE
#define SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CMPIF SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CMPIF
#define sl_sysrtc_capture_edge_t sl_hal_sysrtc_capture_edge_t
#define sl_sysrtc_compare_match_out_action_t sl_hal_sysrtc_compare_match_out_action_t
// Structure.
#define sl_sysrtc_config_t sl_hal_sysrtc_config_t
#define sl_sysrtc_group_channel_compare_config_t sl_hal_sysrtc_group_channel_compare_config_t
#define sl_sysrtc_group_channel_capture_config_t sl_hal_sysrtc_group_channel_capture_config_t
#define sl_sysrtc_group_config_t sl_hal_sysrtc_group_config_t
// Function.
#define sl_sysrtc_init sl_hal_sysrtc_init
#define sl_sysrtc_enable sl_hal_sysrtc_enable
#define sl_sysrtc_disable sl_hal_sysrtc_disable
#define sl_sysrtc_wait_sync sl_hal_sysrtc_wait_sync
#define sl_sysrtc_wait_ready sl_hal_sysrtc_wait_ready
#define sl_sysrtc_start sl_hal_sysrtc_start
#define sl_sysrtc_stop sl_hal_sysrtc_stop
#define sl_sysrtc_reset sl_hal_sysrtc_reset
#define sl_sysrtc_get_status sl_hal_sysrtc_get_status
#define sl_sysrtc_lock sl_hal_sysrtc_lock
#define sl_sysrtc_unlock sl_hal_sysrtc_unlock
#define sl_sysrtc_get_counter sl_hal_sysrtc_get_counter
#define sl_sysrtc_set_counter sl_hal_sysrtc_set_counter
#define sl_sysrtc_init_group sl_hal_sysrtc_init_group
#define sl_sysrtc_enable_group_interrupts sl_hal_sysrtc_enable_group_interrupts
#define sl_sysrtc_disable_group_interrupts sl_hal_sysrtc_disable_group_interrupts
#define sl_sysrtc_clear_group_interrupts sl_hal_sysrtc_clear_group_interrupts
#define sl_sysrtc_get_group_interrupts sl_hal_sysrtc_get_group_interrupts
#define sl_sysrtc_get_group_enabled_interrupts sl_hal_sysrtc_get_group_enabled_interrupts
#define sl_sysrtc_set_group_interrupts sl_hal_sysrtc_set_group_interrupts
#define sl_sysrtc_get_group_compare_channel_value sl_hal_sysrtc_get_group_compare_channel_value
#define sl_sysrtc_set_group_compare_channel_value sl_hal_sysrtc_set_group_compare_channel_value
#define sl_sysrtc_get_group_capture_channel_value sl_hal_sysrtc_get_group_capture_channel_value
#ifdef __cplusplus
}
#endif
#endif // SL_HAL_SYSRTC_COMPAT_H

View File

@@ -0,0 +1,146 @@
/***************************************************************************//**
* @file
* @brief System 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_HAL_SYSTEM_H
#define _SL_HAL_SYSTEM_H
#include "em_device.h"
#include "sl_hal_system_generic.h"
#include "sl_enum.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup system SYSTEM - System Utils
* @brief System API
* @details
* This module contains functions to read information such as RAM and Flash size,
* device unique ID, chip revision, family, and part number from DEVINFO and
* SCB blocks. Functions to configure and read status from FPU are available for
* compatible devices.
* @{
******************************************************************************/
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/// Family identifiers.
SL_ENUM_GENERIC(sl_hal_system_part_family_t, uint32_t) {
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
SL_HAL_SYSTEM_PART_FAMILY_MIGHTY_21 = DEVINFO_PART_FAMILY_MG | (21 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Mighty Gecko Series 2 Config 1 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_FLEX_21 = DEVINFO_PART_FAMILY_FG | (21 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Flex Gecko Series 2 Config 1 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_BLUE_21 = DEVINFO_PART_FAMILY_BG | (21 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Blue Gecko Series 2 Config 1 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_MIGHTY_RCP_21 = DEVINFO_PART_FAMILY_MR | (21 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Mighty RCP Series 2 Config 1 Value Device Family
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
SL_HAL_SYSTEM_PART_FAMILY_MIGHTY_22 = DEVINFO_PART_FAMILY_MG | (22 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Mighty Gecko Series 2 Config 2 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_FLEX_22 = DEVINFO_PART_FAMILY_FG | (22 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Flex Gecko Series 2 Config 2 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_BLUE_22 = DEVINFO_PART_FAMILY_BG | (22 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Blue Gecko Series 2 Config 2 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_EFM32_PEARL_22 = DEVINFO_PART_FAMILY_PG | (22 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFM32 Pearl Gecko Series 2 Config 2 Value Device Family
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3)
SL_HAL_SYSTEM_PART_FAMILY_FLEX_23 = DEVINFO_PART_FAMILY_FG | (23 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Flex Gecko Series 2 Config 3 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_ZEN_23 = DEVINFO_PART_FAMILY_ZG | (23 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Zen Gecko Series 2 Config 3 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_EFM32_PEARL_23 = DEVINFO_PART_FAMILY_PG | (23 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFM32 Pearl Gecko Series 2 Config 3 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_SIDEWALK_23 = DEVINFO_PART_FAMILY_SG | (23 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Side Walk Gecko Series 2 Config 3 Value Device Family
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4)
SL_HAL_SYSTEM_PART_FAMILY_MIGHTY_24 = DEVINFO_PART_FAMILY_MG | (24 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Mighty Gecko Series 2 Config 4 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_FLEX_24 = DEVINFO_PART_FAMILY_FG | (24 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Flex Gecko Series 2 Config 4 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_BLUE_24 = DEVINFO_PART_FAMILY_BG | (24 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Blue Gecko Series 2 Config 4 Value Device Family
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5)
SL_HAL_SYSTEM_PART_FAMILY_FLEX_25 = DEVINFO_PART_FAMILY_FG | (25 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Flex Gecko Series 2 Config 5 Value Device Family
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
SL_HAL_SYSTEM_PART_FAMILY_MIGHTY_26 = DEVINFO_PART_FAMILY_MG | (26 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Mighty Gecko Series 2 Config 6 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_BLUE_26 = DEVINFO_PART_FAMILY_BG | (26 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Blue Gecko Series 2 Config 6 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_EFM32_PEARL_26 = DEVINFO_PART_FAMILY_PG | (26 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFM32 Pearl Gecko Series 2 Config 6 Value Device Family
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7)
SL_HAL_SYSTEM_PART_FAMILY_MIGHTY_27 = DEVINFO_PART_FAMILY_MG | (27 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Mighty Gecko Series 2 Config 7 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_BLUE_27 = DEVINFO_PART_FAMILY_BG | (27 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Blue Gecko Series 2 Config 7 Value Device Family
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)
SL_HAL_SYSTEM_PART_FAMILY_FLEX_28 = DEVINFO_PART_FAMILY_FG | (28 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Flex Gecko Series 2 Config 8 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_ZEN_28 = DEVINFO_PART_FAMILY_ZG | (28 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Zen Gecko Series 2 Config 8 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_SIDEWALK_28 = DEVINFO_PART_FAMILY_SG | (28 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFR32 Side Walk Gecko Series 2 Config 8 Value Device Family
SL_HAL_SYSTEM_PART_FAMILY_EFM32_PEARL_28 = DEVINFO_PART_FAMILY_PG | (28 << _DEVINFO_PART_FAMILYNUM_SHIFT), ///< EFM32 Pearl Gecko Series 2 Config 8 Value Device Family
#endif
#if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
SL_HAL_SYSTEM_PART_FAMILY_BLUETOOTH_301 = DEVINFO_PART0_PROTOCOL_BLUETOOTH \
| (0x33 << _DEVINFO_PART0_SERIES_SHIFT) \
| (0x30 << _DEVINFO_PART0_DIECODE0_SHIFT), ///< SI Series 3 Bluetooth Config 1 Value Device Family (BG)
SL_HAL_SYSTEM_PART_FAMILY_PROPRIETARY_301 = DEVINFO_PART0_PROTOCOL_PROPRIETARY \
| (0x33 << _DEVINFO_PART0_SERIES_SHIFT) \
| (0x30 << _DEVINFO_PART0_DIECODE0_SHIFT), ///< SI Series 3 Proprietary Config 1 Value Device Family (FG)
SL_HAL_SYSTEM_PART_FAMILY_FIFTEENPFOUR_301 = DEVINFO_PART0_PROTOCOL_FIFTEENPFOUR \
| (0x33 << _DEVINFO_PART0_SERIES_SHIFT) \
| (0x30 << _DEVINFO_PART0_DIECODE0_SHIFT), ///< SI Series 3 15.4 Config 1 Value Device Family (MG)
SL_HAL_SYSTEM_PART_FAMILY_PEARL_301 = DEVINFO_PART0_PROTOCOL_PEARL \
| (0x33 << _DEVINFO_PART0_SERIES_SHIFT) \
| (0x30 << _DEVINFO_PART0_DIECODE0_SHIFT), ///< SI Series 3 Pearl Config 1 Value Device Family (PG)
SL_HAL_SYSTEM_PART_FAMILY_WIFI_301 = DEVINFO_PART0_PROTOCOL_WIFI \
| (0x33 << _DEVINFO_PART0_SERIES_SHIFT) \
| (0x30 << _DEVINFO_PART0_DIECODE0_SHIFT), ///< SI Series 3 Wifi Config 1 Value Device Family (WG)
SL_HAL_SYSTEM_PART_FAMILY_ZWAVE_301 = DEVINFO_PART0_PROTOCOL_ZWAVE \
| (0x33 << _DEVINFO_PART0_SERIES_SHIFT) \
| (0x30 << _DEVINFO_PART0_DIECODE0_SHIFT), ///< SI Series 3 Zwave Config 1 Value Device Family (ZG)
#endif
SL_HAL_SYSTEM_PART_FAMILY_UNKNOWN = 0xFF ///< Unknown Device Family. Family ID is missing on unprogrammed parts.
};
/***************************************************************************//**
* @brief
* Get the MCU family identifier.
*
* @return
* Family identifier of MCU.
*
* @note
* This function retrieves family ID by reading the chip's device info
* structure in flash memory. Users can retrieve family ID directly
* by reading DEVINFO->PART item and decode with mask and shift
* \#defines defined in \<part_family\>_devinfo.h (refer to code
* below for details).
******************************************************************************/
sl_hal_system_part_family_t sl_hal_system_get_family(void);
/** @} (end addtogroup system) */
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _SL_HAL_SYSTEM_H */

View File

@@ -0,0 +1,344 @@
/***************************************************************************//**
* @file
* @brief System API (Generic)
*******************************************************************************
* # 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_HAL_SYSTEM_GENERIC_H
#define _SL_HAL_SYSTEM_GENERIC_H
#include "sl_enum.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup system SYSTEM - System Utils
* @{
******************************************************************************/
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/// Family security capability.
SL_ENUM(sl_hal_system_security_capability_t) {
/// Unknown security capability.
SL_SYSTEM_SECURITY_CAPABILITY_UNKNOWN,
/// Security capability not applicable.
SL_SYSTEM_SECURITY_CAPABILITY_NA,
/// Basic security capability.
SL_SYSTEM_SECURITY_CAPABILITY_BASIC,
/// Root of Trust security capability.
SL_SYSTEM_SECURITY_CAPABILITY_ROT,
/// Secure Element security capability.
SL_SYSTEM_SECURITY_CAPABILITY_SE,
/// Secure Vault security capability.
SL_SYSTEM_SECURITY_CAPABILITY_VAULT
};
/// Floating point co-processor access modes.
SL_ENUM_GENERIC(sl_hal_system_fpu_access_t, uint32_t) {
/// Access denied, any attempted access generates a NOCP UsageFault.
SL_SYSTEM_FPU_ACCESS_DENIED = (0x0 << 20),
/// Privileged access only, an unprivileged access generates a NOCP UsageFault.
SL_SYSTEM_FPU_ACCESS_PRIVILEGED_ONLY = (0x5 << 20),
/// Reserved.
SL_SYSTEM_FPU_ACCESS_RESERVED = (0xA << 20),
/// Full access.
SL_SYSTEM_FPU_ACCESS_FULL = (0xF << 20)
};
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/// Chip revision details.
typedef struct {
uint8_t minor; ///< Minor revision number.
uint8_t major; ///< Major revision number.
uint16_t part_number; ///< Device part number. (0xFFFF if unavailable)
uint16_t family; ///< Device family number. (0xFFFF if unavailable)
} sl_hal_system_chip_revision_t;
/// ADC Calibration DEVINFO Structures.
typedef struct sl_hal_system_devinfo_adc_cal_data_t {
uint8_t trim_vros0;
uint8_t trim_vros1;
uint8_t trim_gain_4x;
uint8_t trim_gain_0x3_int;
} sl_hal_system_devinfo_adc_cal_data_t;
typedef struct sl_hal_system_devinfo_adc_offset_t {
uint8_t trim_off_1x;
uint8_t trim_off_2x;
uint8_t trim_off_4x;
uint8_t dummy_byte;
} sl_hal_system_devinfo_adc_offset_t;
typedef struct sl_hal_system_devinfo_adc_t {
sl_hal_system_devinfo_adc_cal_data_t cal_data;
sl_hal_system_devinfo_adc_offset_t offset;
} sl_hal_system_devinfo_adc_t;
/// Temperature DEVINFO Structure.
typedef struct sl_hal_system_devinfo_temperature_t {
uint16_t emu_temp_room;
uint16_t cal_temp;
} sl_hal_system_devinfo_temperature_t;
/// Chip features Structure.
typedef struct sl_hal_system_features {
char feature1;
char feature2;
char feature3;
} sl_hal_system_features_t;
/*******************************************************************************
************************** GLOBAL CONSTANTS *******************************
******************************************************************************/
extern const sl_hal_system_devinfo_adc_t SL_HAL_SYSTEM_DEVINFO_ADC_RESET_VALUES;
extern const sl_hal_system_devinfo_temperature_t SL_HAL_SYSTEM_DEVINFO_TEMPERATURE_RESET_VALUES;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/*******************************************************************************
* @brief
* Get the chip revision.
*
* @param [out]
* rev Pointer to return the chip revision to.
*
* @warning
* The chip revision structure may be returned with either the partnumber or
* family unpopulated (0xFFFF) depending on the device.
******************************************************************************/
void sl_hal_system_get_chip_revision(sl_hal_system_chip_revision_t *rev);
/***************************************************************************//**
* @brief
* Get DEVINFO revision.
*
* @return
* Revision of the DEVINFO contents.
******************************************************************************/
uint8_t sl_hal_system_get_devinfo_rev(void);
/***************************************************************************//**
* @brief
* Get the default factory calibration value for HFRCO oscillator.
*
* @return
* HFRCOCAL default value.
******************************************************************************/
uint32_t sl_hal_system_get_hfrco_default_calibration(void);
/***************************************************************************//**
* @brief
* Get the speed factory calibration value for HFRCO oscillator.
*
* @return
* HFRCOCAL speed value.
******************************************************************************/
uint32_t sl_hal_system_get_hfrco_speed_calibration(void);
/***************************************************************************//**
* @brief Get the HFRCO calibration based on the frequency band.
*
* @param[in] frequency
* Frequency for which to retrieve calibration.
*
* @return
* HFRCOCAL value for the given band.
*
* @note
* Those calibrations are only valid for the HFRCO oscillator when used with
* the DPLL module.
******************************************************************************/
uint32_t sl_hal_system_get_hfrcodpll_band_calibration(uint32_t frequency);
/***************************************************************************//**
* @brief
* Get a factory calibration value for HFRCOEM23 oscillator.
*
* @param [in]
* HFRCOEM23 frequency for which to retrieve calibration.
*
* @return
* HFRCOEM23 calibration value.
******************************************************************************/
uint32_t sl_hal_system_get_hfrcoem23_calibration(uint32_t frequency);
/***************************************************************************//**
* @brief
* Get a factory calibration value for HFXOCAL.
*
* @return
* HFXOCAL value.
******************************************************************************/
uint32_t sl_hal_system_get_hfxocal(void);
/***************************************************************************//**
* @brief
* Get family security capability.
*
* @note
* This function retrieves the family security capability based on the
* device number.
*
* @return
* Security capability of MCU.
******************************************************************************/
sl_hal_system_security_capability_t sl_hal_system_get_security_capability(void);
/***************************************************************************//**
* @brief
* Get the unique number for this device.
*
* @return
* Unique number for this device.
******************************************************************************/
uint64_t sl_hal_system_get_unique(void);
/***************************************************************************//**
* @brief
* Get the production revision for this part.
*
* @return
* Production revision for this part.
******************************************************************************/
uint8_t sl_hal_system_get_prod_rev(void);
/***************************************************************************//**
* @brief
* Get the SRAM Base Address.
*
* @return
* Base address SRAM (32-bit unsigned integer).
******************************************************************************/
uint32_t sl_hal_system_get_sram_base_address(void);
/***************************************************************************//**
* @brief
* Get the SRAM size (in KB).
*
* @note
* This function retrieves SRAM size by reading the chip device
* info structure. If your binary is made for one specific device only,
* use SRAM_SIZE instead.
*
* @return
* Size of internal SRAM (in KB).
******************************************************************************/
uint16_t sl_hal_system_get_sram_size(void);
/***************************************************************************//**
* @brief
* Get the flash size (in KB).
*
* @note
* This function retrieves flash size by reading the chip device info structure or
* DEVINFO->EMBMSIZE (embedded flash. not the case for S3 for now) or
* user config (external flash).
*
* @return
* Size of flash (in KB).
******************************************************************************/
uint16_t sl_hal_system_get_flash_size(void);
/***************************************************************************//**
* @brief
* Get the flash page size in bytes.
*
* @note
* This function retrieves flash page size by reading the SE or
* user config (external flash)
*
* @return
* Page size of flash in bytes.
******************************************************************************/
uint32_t sl_hal_system_get_flash_page_size(void);
/***************************************************************************//**
* @brief
* Get the MCU part number.
*
* @return
* The part number of MCU.
******************************************************************************/
uint16_t sl_hal_system_get_part_number(void);
/***************************************************************************//**
* @brief
* Get the SoC or MCU features.
*
* @return
* The features of the current SoC or MCU.
*
* @note The features can be decoded by referring to the SoC or MCU datasheet.
******************************************************************************/
sl_hal_system_features_t sl_hal_system_get_part_features(void);
/***************************************************************************//**
* @brief
* Get the temperature information.
*
* @param[out] info
* Pointer to variable where to store the temperature info.
******************************************************************************/
void sl_hal_system_get_temperature_info(sl_hal_system_devinfo_temperature_t *info);
/***************************************************************************//**
* @brief
* Set floating point co-processor (FPU) access mode.
*
* @param[in] accessMode
* Floating point co-processor access mode.
******************************************************************************/
void sl_hal_system_fpu_set_access_mode(sl_hal_system_fpu_access_t access_mode);
/***************************************************************************//**
* @brief Get the ADC calibration info.
*
* @param[out] info
* Pointer to variable where to store the adc calibration info.
******************************************************************************/
void sl_hal_system_get_adc_calibration_info(sl_hal_system_devinfo_adc_t *info);
/** @} (end addtogroup system) */
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _SL_HAL_SYSTEM_GENERIC_H */

View File

@@ -0,0 +1,432 @@
/***************************************************************************//**
* @file
* @brief General Purpose IO (GPIO) peripheral 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 "sl_hal_gpio.h"
#if defined(GPIO_PRESENT)
#include "sl_hal_bus.h"
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
extern __INLINE void sl_hal_gpio_lock(void);
extern __INLINE void sl_hal_gpio_unlock(void);
extern __INLINE uint32_t sl_hal_gpio_get_lock_status(void);
extern __INLINE void sl_hal_gpio_set_pin(const sl_gpio_t *gpio);
extern __INLINE void sl_hal_gpio_set_port(sl_gpio_port_t port,
uint32_t pins);
extern __INLINE void sl_hal_gpio_set_port_value(sl_gpio_port_t port,
uint32_t val,
uint32_t mask);
extern __INLINE void sl_hal_gpio_set_slew_rate(sl_gpio_port_t port,
uint8_t slewrate);
extern __INLINE void sl_hal_gpio_set_slew_rate_alternate(sl_gpio_port_t port,
uint8_t slewrate_alt);
extern __INLINE uint8_t sl_hal_gpio_get_slew_rate(sl_gpio_port_t port);
extern __INLINE uint8_t sl_hal_gpio_get_slew_rate_alternate(sl_gpio_port_t port);
extern __INLINE void sl_hal_gpio_clear_pin(const sl_gpio_t *gpio);
extern __INLINE void sl_hal_gpio_clear_port(sl_gpio_port_t port,
uint32_t pins);
extern __INLINE bool sl_hal_gpio_get_pin_input(const sl_gpio_t *gpio);
extern __INLINE bool sl_hal_gpio_get_pin_output(const sl_gpio_t *gpio);
extern __INLINE uint32_t sl_hal_gpio_get_port_input(sl_gpio_port_t port);
extern __INLINE uint32_t sl_hal_gpio_get_port_output(sl_gpio_port_t port);
extern __INLINE void sl_hal_gpio_toggle_pin(const sl_gpio_t *gpio);
extern __INLINE void sl_hal_gpio_toggle_port(sl_gpio_port_t port,
uint32_t pins);
extern __INLINE void sl_hal_gpio_enable_interrupts(uint32_t flags);
extern __INLINE void sl_hal_gpio_disable_interrupts(uint32_t flags);
extern __INLINE void sl_hal_gpio_clear_interrupts(uint32_t flags);
extern __INLINE void sl_hal_gpio_set_interrupts(uint32_t flags);
extern __INLINE uint32_t sl_hal_gpio_get_pending_interrupts(void);
extern __INLINE uint32_t sl_hal_gpio_get_enabled_interrupts(void);
extern __INLINE uint32_t sl_hal_gpio_get_enabled_pending_interrupts(void);
extern __INLINE int32_t sl_hal_gpio_get_external_interrupt_number(uint8_t pin,
uint32_t enabled_interrupts_mask);
extern __INLINE int32_t sl_hal_gpio_get_em4_interrupt_number(const sl_gpio_t *gpio);
extern __INLINE void sl_hal_gpio_set_pin_em4_retention(bool enable);
extern __INLINE void sl_hal_gpio_disable_pin_em4_wakeup (uint32_t pinmask);
extern __INLINE uint32_t sl_hal_gpio_get_pin_em4_wakeup_cause(void);
extern __INLINE void sl_hal_gpio_enable_debug_swo(bool enable);
extern __INLINE void sl_hal_gpio_enable_debug_swd_clk(bool enable);
extern __INLINE void sl_hal_gpio_enable_debug_swd_io(bool enable);
/***************************************************************************//**
* Sets the mode for GPIO pin.
******************************************************************************/
void sl_hal_gpio_set_pin_mode(const sl_gpio_t *gpio,
sl_gpio_mode_t mode,
bool output_value)
{
sl_gpio_mode_t gpio_mode = SL_GPIO_MODE_DISABLED;
EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
EFM_ASSERT(sl_hal_gpio_get_lock_status() == 0);
switch (mode) {
#if defined(_GPIO_P_MODEL_MODE0_DISABLED)
case SL_GPIO_MODE_DISABLED:
gpio_mode = _GPIO_P_MODEL_MODE0_DISABLED;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_INPUT)
case SL_GPIO_MODE_INPUT:
gpio_mode = _GPIO_P_MODEL_MODE0_INPUT;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_INPUTPULL)
case SL_GPIO_MODE_INPUT_PULL:
gpio_mode = _GPIO_P_MODEL_MODE0_INPUTPULL;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_INPUTPULLFILTER)
case SL_GPIO_MODE_INPUT_PULL_FILTER:
gpio_mode = _GPIO_P_MODEL_MODE0_INPUTPULLFILTER;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_PUSHPULL)
case SL_GPIO_MODE_PUSH_PULL:
gpio_mode = _GPIO_P_MODEL_MODE0_PUSHPULL;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_PUSHPULLALT)
case SL_GPIO_MODE_PUSH_PULL_ALTERNATE:
gpio_mode = _GPIO_P_MODEL_MODE0_PUSHPULLALT;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDOR)
case SL_GPIO_MODE_WIRED_OR:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDOR;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDORPULLDOWN)
case SL_GPIO_MODE_WIRED_OR_PULL_DOWN:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDORPULLDOWN;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDAND)
case SL_GPIO_MODE_WIRED_AND:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDAND;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDFILTER)
case SL_GPIO_MODE_WIRED_AND_FILTER:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDFILTER;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDPULLUP)
case SL_GPIO_MODE_WIRED_AND_PULLUP:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDPULLUP;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER)
case SL_GPIO_MODE_WIRED_AND_PULLUP_FILTER:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDALT)
case SL_GPIO_MODE_WIRED_AND_ALTERNATE:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDALT;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTFILTER)
case SL_GPIO_MODE_WIRED_AND_ALTERNATE_FILTER:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDALTFILTER;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTPULLUP)
case SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDALTPULLUP;
break;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTPULLUPFILTER)
case SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP_FILTER:
gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDALTPULLUPFILTER;
break;
#endif
default:
EFM_ASSERT(false);
break;
}
EFM_ASSERT(SL_HAL_GPIO_MODE_IS_VALID(gpio_mode));
// If disabling a pin, do not modify DOUT to reduce the chance of
// a glitch/spike (may not be sufficient precaution in all use cases).
// As mode settings are dependent on DOUT values, setting output value
// prior to mode. @ref enum - sl_gpio_mode_t
if (mode != SL_GPIO_MODE_DISABLED) {
if (output_value) {
sl_hal_gpio_set_pin(gpio);
} else {
sl_hal_gpio_clear_pin(gpio);
}
}
// There are two registers controlling the pins for each port.
// The MODEL register controls pins 0-7 and MODEH controls pins 8-15.
if (gpio->pin < 8) {
sl_hal_bus_reg_write_mask(&(GPIO->P[gpio->port].MODEL), 0xFu << (gpio->pin * 4), gpio_mode << (gpio->pin * 4));
} else {
sl_hal_bus_reg_write_mask(&(GPIO->P[gpio->port].MODEH), 0xFu << ((gpio->pin - 8) * 4), gpio_mode << ((gpio->pin - 8) * 4));
}
// SL_GPIO_MODE_DISABLED based on DOUT Value (low/high) act as two different configurations.
// By setting mode to disabled first and then modifying the DOUT value, so that
// previous mode configuration on given pin not effected.
if (mode == SL_GPIO_MODE_DISABLED) {
if (output_value) {
sl_hal_gpio_set_pin(gpio);
} else {
sl_hal_gpio_clear_pin(gpio);
}
}
}
/***************************************************************************//**
* Get the mode for a GPIO pin.
******************************************************************************/
sl_gpio_mode_t sl_hal_gpio_get_pin_mode(const sl_gpio_t *gpio)
{
sl_gpio_mode_t mode = SL_GPIO_MODE_DISABLED;
EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
// Determine the current mode of the GPIO pin based on the pin number.
if (gpio->pin < 8) {
mode = (sl_gpio_mode_t) ((GPIO->P[gpio->port].MODEL >> (gpio->pin * 4)) & 0xF);
} else {
mode = (sl_gpio_mode_t) ((GPIO->P[gpio->port].MODEH >> ((gpio->pin - 8) * 4)) & 0xF);
}
// Map the hardware-specific mode to the corresponding sl_gpio_mode_t value
switch (mode) {
#if defined(_GPIO_P_MODEL_MODE0_DISABLED)
case _GPIO_P_MODEL_MODE0_DISABLED:
return SL_GPIO_MODE_DISABLED;
#endif
#if defined(_GPIO_P_MODEL_MODE0_INPUT)
case _GPIO_P_MODEL_MODE0_INPUT:
return SL_GPIO_MODE_INPUT;
#endif
#if defined(_GPIO_P_MODEL_MODE0_INPUTPULL)
case _GPIO_P_MODEL_MODE0_INPUTPULL:
return SL_GPIO_MODE_INPUT_PULL;
#endif
#if defined(_GPIO_P_MODEL_MODE0_INPUTPULLFILTER)
case _GPIO_P_MODEL_MODE0_INPUTPULLFILTER:
return SL_GPIO_MODE_INPUT_PULL_FILTER;
#endif
#if defined(_GPIO_P_MODEL_MODE0_PUSHPULL)
case _GPIO_P_MODEL_MODE0_PUSHPULL:
return SL_GPIO_MODE_PUSH_PULL;
#endif
#if defined(_GPIO_P_MODEL_MODE0_PUSHPULLALT)
case _GPIO_P_MODEL_MODE0_PUSHPULLALT:
return SL_GPIO_MODE_PUSH_PULL_ALTERNATE;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDOR)
case _GPIO_P_MODEL_MODE0_WIREDOR:
return SL_GPIO_MODE_WIRED_OR;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDORPULLDOWN)
case _GPIO_P_MODEL_MODE0_WIREDORPULLDOWN:
return SL_GPIO_MODE_WIRED_OR_PULL_DOWN;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDAND)
case _GPIO_P_MODEL_MODE0_WIREDAND:
return SL_GPIO_MODE_WIRED_AND;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDFILTER)
case _GPIO_P_MODEL_MODE0_WIREDANDFILTER:
return SL_GPIO_MODE_WIRED_AND_FILTER;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDPULLUP)
case _GPIO_P_MODEL_MODE0_WIREDANDPULLUP:
return SL_GPIO_MODE_WIRED_AND_PULLUP;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER)
case _GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER:
return SL_GPIO_MODE_WIRED_AND_PULLUP_FILTER;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDALT)
case _GPIO_P_MODEL_MODE0_WIREDANDALT:
return SL_GPIO_MODE_WIRED_AND_ALTERNATE;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTFILTER)
case _GPIO_P_MODEL_MODE0_WIREDANDALTFILTER:
return SL_GPIO_MODE_WIRED_AND_ALTERNATE_FILTER;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTPULLUP)
case _GPIO_P_MODEL_MODE0_WIREDANDALTPULLUP:
return SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP;
#endif
#if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTPULLUPFILTER)
case _GPIO_P_MODEL_MODE0_WIREDANDALTPULLUPFILTER:
return SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP_FILTER;
#endif
default:
EFM_ASSERT(false);
return mode; // returning the default state
}
}
/***************************************************************************//**
* Configure the GPIO pin interrupt.
******************************************************************************/
int32_t sl_hal_gpio_configure_external_interrupt(const sl_gpio_t *gpio,
int32_t int_no,
sl_gpio_interrupt_flag_t flags)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
EFM_ASSERT(SL_GPIO_FLAG_IS_VALID(flags));
EFM_ASSERT(sl_hal_gpio_get_lock_status() == 0);
if (int_no != SL_GPIO_INTERRUPT_UNAVAILABLE && int_no >= 0) {
#if defined(_GPIO_EXTIPINSELL_MASK)
EFM_ASSERT(SL_HAL_GPIO_INTNO_PIN_VALID(int_no, gpio->pin));
#endif
}
#if !defined(_GPIO_EXTIPINSELL_MASK)
int_no = gpio->pin;
#endif
if (int_no == SL_GPIO_INTERRUPT_UNAVAILABLE) {
uint32_t interrupts_enabled = sl_hal_gpio_get_enabled_interrupts();
int_no = sl_hal_gpio_get_external_interrupt_number(gpio->pin, interrupts_enabled);
}
if (int_no != SL_GPIO_INTERRUPT_UNAVAILABLE && int_no >= 0) {
if (int_no < 8) {
// The EXTIPSELL register controls pins 0-7 of the interrupt configuration.
#if defined(_GPIO_EXTIPSELL_EXTIPSEL0_MASK)
sl_hal_bus_reg_write_mask(&GPIO->EXTIPSELL,
_GPIO_EXTIPSELL_EXTIPSEL0_MASK
<< (_GPIO_EXTIPSELL_EXTIPSEL1_SHIFT * int_no),
(uint32_t)gpio->port << (_GPIO_EXTIPSELL_EXTIPSEL1_SHIFT * int_no));
#endif
// The EXTIPINSELL register controls interrupt 0-7 of the interrupt/pin number mapping.
#if defined(_GPIO_EXTIPINSELL_EXTIPINSEL0_MASK)
sl_hal_bus_reg_write_mask(&GPIO->EXTIPINSELL,
_GPIO_EXTIPINSELL_EXTIPINSEL0_MASK
<< (_GPIO_EXTIPINSELL_EXTIPINSEL1_SHIFT * int_no),
((gpio->pin % 4) & _GPIO_EXTIPINSELL_EXTIPINSEL0_MASK)
<< (_GPIO_EXTIPINSELL_EXTIPINSEL1_SHIFT * int_no));
#endif
} else {
// EXTIPSELH controls pins 8-15 of the interrupt configuration.
#if defined(_GPIO_EXTIPSELH_EXTIPSEL0_MASK)
uint32_t tmp = int_no - 8;
sl_hal_bus_reg_write_mask(&GPIO->EXTIPSELH,
_GPIO_EXTIPSELH_EXTIPSEL0_MASK
<< (_GPIO_EXTIPSELH_EXTIPSEL1_SHIFT * tmp),
(uint32_t)gpio->port << (_GPIO_EXTIPSELH_EXTIPSEL1_SHIFT * tmp));
#endif
// EXTIPINSELH controls interrupt 8-15 of the interrupt/pin number mapping.
#if defined(_GPIO_EXTIPINSELH_EXTIPINSEL0_MASK)
sl_hal_bus_reg_write_mask(&GPIO->EXTIPINSELH,
_GPIO_EXTIPINSELH_EXTIPINSEL0_MASK
<< (_GPIO_EXTIPINSELH_EXTIPINSEL1_SHIFT * tmp),
((gpio->pin % 4) & _GPIO_EXTIPINSELH_EXTIPINSEL0_MASK)
<< (_GPIO_EXTIPSELH_EXTIPSEL1_SHIFT * tmp));
#endif
}
// Enable/disable rising edge interrupt.
(((flags & SL_GPIO_INTERRUPT_RISING_EDGE) == SL_GPIO_INTERRUPT_RISING_EDGE)
|| ((flags & SL_GPIO_INTERRUPT_RISING_FALLING_EDGE) == SL_GPIO_INTERRUPT_RISING_FALLING_EDGE)) \
? sl_hal_bus_reg_write_bit(&(GPIO->EXTIRISE), int_no, true) \
: sl_hal_bus_reg_write_bit(&(GPIO->EXTIRISE), int_no, false);
// Enable/disable falling edge interrupt.
(((flags & SL_GPIO_INTERRUPT_FALLING_EDGE) == SL_GPIO_INTERRUPT_FALLING_EDGE)
|| (flags & SL_GPIO_INTERRUPT_RISING_FALLING_EDGE) == SL_GPIO_INTERRUPT_RISING_FALLING_EDGE) \
? sl_hal_bus_reg_write_bit(&(GPIO->EXTIFALL), int_no, true) \
: sl_hal_bus_reg_write_bit(&(GPIO->EXTIFALL), int_no, false);
// Clear any pending interrupt.
sl_hal_gpio_clear_interrupts(1 << int_no);
}
return int_no;
}
/**************************************************************************//**
* Enable GPIO pin wake-up from EM4. When the function exits,
* EM4 mode can be safely entered.
*****************************************************************************/
void sl_hal_gpio_enable_pin_em4_wakeup(uint32_t pinmask,
uint32_t polaritymask)
{
EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);
EFM_ASSERT((polaritymask & ~_GPIO_EM4WUPOL_MASK) == 0);
GPIO->EM4WUPOL &= ~pinmask; // Set the wakeup polarity.
GPIO->EM4WUPOL |= pinmask & polaritymask;
GPIO->EM4WUEN |= pinmask; // Enable wakeup.
sl_hal_gpio_set_pin_em4_retention(true); // Enable the pin retention.
sl_hal_gpio_clear_interrupts(pinmask); // clear any pending interrupt.
}
/***************************************************************************//**
* Configure EM4WU pins as external level-sensitive interrupts.
******************************************************************************/
int32_t sl_hal_gpio_configure_wakeup_em4_external_interrupt(const sl_gpio_t *gpio,
int32_t int_no,
bool polarity)
{
EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
EFM_ASSERT(sl_hal_gpio_get_lock_status() == 0);
int32_t em4_int_no = sl_hal_gpio_get_em4_interrupt_number(gpio);
if (int_no == SL_GPIO_INTERRUPT_UNAVAILABLE) {
int_no = em4_int_no;
}
if (em4_int_no == SL_GPIO_INTERRUPT_UNAVAILABLE || int_no != em4_int_no) {
return SL_GPIO_INTERRUPT_UNAVAILABLE;
}
if (int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) {
// GPIO pin mode set.
sl_hal_gpio_set_pin_mode(gpio, SL_GPIO_MODE_INPUT_PULL_FILTER, (unsigned int)!polarity);
// Enable EM4WU function and set polarity.
uint32_t polarityMask = (uint32_t)polarity << (int_no + _GPIO_EM4WUEN_EM4WUEN_SHIFT);
uint32_t pinmask = 1UL << (int_no + _GPIO_EM4WUEN_EM4WUEN_SHIFT);
sl_hal_gpio_enable_pin_em4_wakeup(pinmask, polarityMask);
}
return int_no;
}
#endif /* defined(GPIO_PRESENT)*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,662 @@
/***************************************************************************//**
* @file
* @brief Universal asynchronous receiver/transmitter (EUSART) peripheral 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.
*
******************************************************************************/
#include "sl_hal_system.h"
#include "sl_hal_syscfg.h"
#include "em_device.h"
#include <stdbool.h>
#if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
#include "sl_se_manager.h"
#include "sli_se_manager_device_data.h"
#endif
#include "sl_status.h"
#include "sl_assert.h"
/***************************************************************************//**
* @addtogroup system
* @{
******************************************************************************/
/*******************************************************************************
************************** DEFINES *******************************
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/* Bit mask used to extract the part number value without the new naming
* bitfield. */
#define SYSCFG_CHIPREV_PARTNUMBER1 0xFE0
#define SYSCFG_CHIPREV_PARTNUMBER0 0xF
/** @endcond */
#define HFRCO_DPLL_FREQUENCY_TABLE_SIZE 11
#define DEVINFO_TEMPERATURE_CALTEMP_INTEGER_SHIFT 4
/*******************************************************************************
******************************* TYPEDEF ***********************************
******************************************************************************/
#if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
typedef struct hfrco_dpll_cal_element {
uint32_t min_freq;
uint32_t max_freq;
} hfrco_dpll_cal_element_t;
#endif
/*******************************************************************************
****************************** CONSTANTS **********************************
******************************************************************************/
const sl_hal_system_devinfo_adc_t SL_HAL_SYSTEM_DEVINFO_ADC_RESET_VALUES = {
.cal_data = {
.trim_vros0 = 0,
.trim_vros1 = 0,
.trim_gain_4x = 0,
.trim_gain_0x3_int = 0
},
.offset = {
.trim_off_1x = 0,
.trim_off_2x = 0,
.trim_off_4x = 0
}
};
const sl_hal_system_devinfo_temperature_t SL_HAL_SYSTEM_DEVINFO_TEMPERATURE_RESET_VALUES = {
.emu_temp_room = 0,
.cal_temp = 0
};
#if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
static const hfrco_dpll_cal_element_t HFRCO_DPLL_FREQUENCY_TABLE[HFRCO_DPLL_FREQUENCY_TABLE_SIZE] = {
{ .min_freq = 16000000, .max_freq = 20000000 }, // 18MHz calibration central frequency
{ .min_freq = 20000000, .max_freq = 24500000 }, // 22MHz calibration central frequency
{ .min_freq = 24500000, .max_freq = 30000000 }, // 27MHz calibration central frequency
{ .min_freq = 30000000, .max_freq = 36000000 }, // 33MHz calibration central frequency
{ .min_freq = 36000000, .max_freq = 42500000 }, // 39MHz calibration central frequency
{ .min_freq = 42500000, .max_freq = 50500000 }, // 46MHz calibration central frequency
{ .min_freq = 50500000, .max_freq = 60000000 }, // 55MHz calibration central frequency
{ .min_freq = 60000000, .max_freq = 70000000 }, // 65MHz calibration central frequency
{ .min_freq = 70000000, .max_freq = 80000000 }, // 75MHz calibration central frequency
{ .min_freq = 80000000, .max_freq = 90000000 }, // 85MHz calibration central frequency
{ .min_freq = 90000000, .max_freq = 100000000 } // 95MHz calibration central frequency
};
#endif
/*******************************************************************************
****************************** UTILITY *************************************
******************************************************************************/
#if defined(_SILICON_LABS_32B_SERIES_2)
/***************************************************************************//**
* @brief Get the nth ASCII character of a specified number.
*
* @param[in] input_number
* The number where the digit will be taken.
*
* @param[in] position
* The digit position.
*
* @return
* The ASCII value of the specified digit.
******************************************************************************/
char sli_get_n_digit(uint16_t input_number, uint8_t position)
{
uint32_t exp[] = { 10, 100, 1000, 10000, 100000 };
uint32_t number = input_number;
if (position > 4) {
EFM_ASSERT(false);
return '0';
}
number = (number % exp[position]);
if (position != 0) {
number = number / (exp[position - 1]);
}
return (char)number + '0';
}
#endif
#if defined(_DEVINFO_PART0_DIECODE0_MASK) && defined(_SILICON_LABS_SECURITY_FEATURE_VAULT)
/***************************************************************************//**
* @brief Convert hexadecimal ASCII character to integer value.
*
* @param[in] character
* The character to be coverted to a number.
*
* @return
* The uint8_t value of the character given in parameter.
******************************************************************************/
uint8_t sli_hex_ascii_to_value(char character)
{
if (character >= '0' && character <= '9') {
return character - '0';
} else if (character >= 'A' && character <= 'F') {
return character - 'A';
}
return 0U;
}
#endif
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
/*******************************************************************************
* @brief Get CHIPREV register.
******************************************************************************/
void sl_hal_system_get_chip_revision(sl_hal_system_chip_revision_t *rev)
{
#if defined(CMU_CLKEN0_SYSCFG)
CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
#endif
uint32_t chip_rev = sl_hal_syscfg_read_chip_rev();
rev->minor = (chip_rev & _SYSCFG_CHIPREV_MINOR_MASK) >> _SYSCFG_CHIPREV_MINOR_SHIFT;
rev->major = (chip_rev & _SYSCFG_CHIPREV_MAJOR_MASK) >> _SYSCFG_CHIPREV_MAJOR_SHIFT;
#if defined(_SYSCFG_CHIPREV_PARTNUMBER_MASK)
rev->part_number = ((chip_rev & SYSCFG_CHIPREV_PARTNUMBER1) >> 5) | (chip_rev & SYSCFG_CHIPREV_PARTNUMBER0);
rev->family = (uint16_t)0xFFFF;
#elif defined(_SYSCFG_CHIPREV_FAMILY_MASK)
rev->part_number = (uint16_t)0xFFFF;
rev->family = (chip_rev & _SYSCFG_CHIPREV_FAMILY_MASK) >> _SYSCFG_CHIPREV_FAMILY_SHIFT;
#else
#error No Chip Revision Part Number or Family
#endif
}
/***************************************************************************//**
* @brief Get the MCU family identifier.
******************************************************************************/
sl_hal_system_part_family_t sl_hal_system_get_family(void)
{
#if defined(_DEVINFO_PART_FAMILY_MASK)
return (DEVINFO->PART & (_DEVINFO_PART_FAMILY_MASK
| _DEVINFO_PART_FAMILYNUM_MASK));
#else
return (DEVINFO->PART0 & (_DEVINFO_PART0_PROTOCOL_MASK
| _DEVINFO_PART0_SERIES_MASK
| _DEVINFO_PART0_DIECODE0_MASK));
#endif
}
/***************************************************************************//**
* @brief Get DEVINFO revision.
******************************************************************************/
uint8_t sl_hal_system_get_devinfo_rev(void)
{
#if defined(_DEVINFO_INFO_DEVINFOREV_MASK)
return (uint8_t)((DEVINFO->INFO & _DEVINFO_INFO_DEVINFOREV_MASK)
>> _DEVINFO_INFO_DEVINFOREV_SHIFT);
#elif defined(_DEVINFO_REVISION_DEVINFOREV_MASK)
return (uint8_t)((DEVINFO->REVISION & _DEVINFO_REVISION_DEVINFOREV_MASK)
>> _DEVINFO_REVISION_DEVINFOREV_SHIFT);
#else
#error (sl_hal_system.c): Location of devinfo revision is not defined.
#endif
}
/***************************************************************************//**
* @brief Get the default factory calibration value for HFRCO oscillator.
******************************************************************************/
uint32_t sl_hal_system_get_hfrco_default_calibration(void)
{
#if defined(_DEVINFO_HFRCOCALDEFAULT_MASK)
return DEVINFO->HFRCOCALDEFAULT;
#else
return 0;
#endif
}
/***************************************************************************//**
* @brief Get the speed factory calibration value for HFRCO oscillator.
******************************************************************************/
uint32_t sl_hal_system_get_hfrco_speed_calibration(void)
{
#if defined(_DEVINFO_HFRCOCALSPEED_MASK)
return DEVINFO->HFRCOCALSPEED;
#else
return 0;
#endif
}
/***************************************************************************//**
* @brief Get the HFRCO calibration based on the frequency band.
******************************************************************************/
uint32_t sl_hal_system_get_hfrcodpll_band_calibration(uint32_t frequency)
{
#if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
sl_status_t status;
uint8_t band_index = 0xFF;
sl_se_command_context_t se_command_ctx;
sli_se_device_data_t otp_section_id = (sli_se_device_data_t)(SLI_SE_DEVICE_DATA_DI0 + DEVINFO_GP_FRAGMENT_INDEX);
uint32_t offset;
uint32_t calibration_value = 0;
for (uint8_t i = 0; i < HFRCO_DPLL_FREQUENCY_TABLE_SIZE; i++) {
if ((frequency >= HFRCO_DPLL_FREQUENCY_TABLE[i].min_freq)
&& (frequency <= HFRCO_DPLL_FREQUENCY_TABLE[i].max_freq)) {
band_index = i;
break;
}
}
if (band_index >= HFRCO_DPLL_FREQUENCY_TABLE_SIZE) {
return 0;
}
// Calculate memory offset based on the band index we want.
offset = (band_index * 4) + DEVINFO_GP_HFRCODPLLBAND0_OFFSET;
// Initialize command context
status = sl_se_init_command_context(&se_command_ctx);
if (status != SL_STATUS_OK) {
return 0;
}
// Send the SE command to retrieve the HFRCODPLL calibration for a given band from the DEVINFO OTP section
status = sli_se_device_data_read_word(&se_command_ctx, otp_section_id, offset, &calibration_value);
if (status != SL_STATUS_OK) {
return 0;
}
return calibration_value;
#else
(void)frequency;
return 0;
#endif
}
/***************************************************************************//**
* Get a factory calibration value for HFRCOCEM23 oscillator.
******************************************************************************/
uint32_t sl_hal_system_get_hfrcoem23_calibration(uint32_t frequency)
{
#if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
sl_status_t status;
sl_se_command_context_t se_command_ctx;
sli_se_device_data_t otp_section_id = (sli_se_device_data_t)(SLI_SE_DEVICE_DATA_DI0 + DEVINFO_GP_FRAGMENT_INDEX);
uint32_t offset;
uint32_t calibration_value = 0;
// Determine offset based on HFRCOEM23 frequency.
if (frequency == 40000000UL) {
#if defined(DEVINFO_GP_HFRCOEM2340MHZ_OFFSET)
offset = DEVINFO_GP_HFRCOEM2340MHZ_OFFSET;
#else
// Default to 20Mhz.
offset = DEVINFO_GP_HFRCOEM23DEFAULT_OFFSET;
#endif
} else {
offset = DEVINFO_GP_HFRCOEM23DEFAULT_OFFSET;
}
// Initialize command context
status = sl_se_init_command_context(&se_command_ctx);
if (status != SL_STATUS_OK) {
return 0;
}
// Send the SE command to retrieve the HFRCOEM23 calibration from the DEVINFO OTP section
status = sli_se_device_data_read_word(&se_command_ctx, otp_section_id, offset, &calibration_value);
if (status != SL_STATUS_OK) {
return 0;
}
return calibration_value;
#else
(void)frequency;
return 0;
#endif
}
/***************************************************************************//**
* @brief Get a factory calibration value for HFXOCAL.
******************************************************************************/
uint32_t sl_hal_system_get_hfxocal(void)
{
#if defined(_DEVINFO_HFXOCAL_MASK)
return DEVINFO->HFXOCAL;
#else
return 0;
#endif
}
/***************************************************************************//**
* @brief Get family security capability.
******************************************************************************/
sl_hal_system_security_capability_t sl_hal_system_get_security_capability(void)
{
sl_hal_system_security_capability_t sc = SL_SYSTEM_SECURITY_CAPABILITY_UNKNOWN;
uint16_t mcu_feature_set_major;
uint16_t device_number;
device_number = sl_hal_system_get_part_number();
mcu_feature_set_major = 'A' + (device_number / 1000);
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
// override feature set since BRD4182A Rev A00 -> rev B02 are marked "A"
mcu_feature_set_major = 'C';
#endif
switch (mcu_feature_set_major) {
case 'A':
sc = SL_SYSTEM_SECURITY_CAPABILITY_SE;
break;
case 'B':
sc = SL_SYSTEM_SECURITY_CAPABILITY_VAULT;
break;
case 'C':
sc = SL_SYSTEM_SECURITY_CAPABILITY_ROT;
break;
default:
sc = SL_SYSTEM_SECURITY_CAPABILITY_UNKNOWN;
break;
}
return sc;
}
/***************************************************************************//**
* @brief Get the unique number for this device.
******************************************************************************/
uint64_t sl_hal_system_get_unique(void)
{
uint32_t tmp = DEVINFO->EUI64L;
return ((uint64_t)DEVINFO->EUI64H << 32) | tmp;
}
/***************************************************************************//**
* @brief Get the production revision for this part.
******************************************************************************/
uint8_t sl_hal_system_get_prod_rev(void)
{
#if defined(_DEVINFO_INFO_PRODREV_MASK)
return (uint8_t)((DEVINFO->INFO & _DEVINFO_INFO_PRODREV_MASK)
>> _DEVINFO_INFO_PRODREV_SHIFT);
#elif defined(_DEVINFO_REVISION_PRODREV_MASK)
return (uint8_t)((DEVINFO->REVISION & _DEVINFO_REVISION_PRODREV_MASK)
>> _DEVINFO_REVISION_PRODREV_SHIFT);
#else
#error (sl_hal_system.c): Location of production revision is not defined.
#endif
}
/***************************************************************************//**
* @brief Get the SRAM Base Address.
******************************************************************************/
uint32_t sl_hal_system_get_sram_base_address(void)
{
return SRAM_BASE;
}
/***************************************************************************//**
* @brief Get the SRAM size (in KB).
******************************************************************************/
uint16_t sl_hal_system_get_sram_size(void)
{
#if defined(_DEVINFO_MSIZE_SRAM_MASK)
return (uint16_t)((DEVINFO->MSIZE & _DEVINFO_MSIZE_SRAM_MASK)
>> _DEVINFO_MSIZE_SRAM_SHIFT);
#elif defined(_DEVINFO_EMBSIZE_RAM_MASK)
return (uint16_t)((DEVINFO->EMBSIZE & _DEVINFO_EMBSIZE_RAM_MASK)
>> _DEVINFO_EMBSIZE_RAM_SHIFT);
#else
#error (sl_hal_system.c): Location of SRAM Size is not defined.
#endif
}
/***************************************************************************//**
* @brief Get the flash size (in KB).
******************************************************************************/
uint16_t sl_hal_system_get_flash_size(void)
{
#if defined(_DEVINFO_MSIZE_FLASH_MASK)
return (uint16_t)((DEVINFO->MSIZE & _DEVINFO_MSIZE_FLASH_MASK)
>> _DEVINFO_MSIZE_FLASH_SHIFT);
#elif defined(_DEVINFO_STACKMSIZE_FLASH_MASK)
uint16_t stacked_flach_size = (uint16_t)((DEVINFO->STACKMSIZE & _DEVINFO_STACKMSIZE_FLASH_MASK)
>> _DEVINFO_STACKMSIZE_FLASH_SHIFT);
if (stacked_flach_size == 0) {
// Defined in linker script for external flash provided by customers.
extern uint32_t __flash_size__;
// Get flash size in kB.
stacked_flach_size = (uint16_t)(uintptr_t)&__flash_size__ / 1024;
}
return stacked_flach_size;
#endif
}
/***************************************************************************//**
* @brief Get the flash page size in bytes.
******************************************************************************/
uint32_t sl_hal_system_get_flash_page_size(void)
{
#if defined(_DEVINFO_MEMINFO_FLASHPAGESIZE_MASK)
uint32_t tmp;
tmp = (DEVINFO->MEMINFO & _DEVINFO_MEMINFO_FLASHPAGESIZE_MASK)
>> _DEVINFO_MEMINFO_FLASHPAGESIZE_SHIFT;
return 1UL << ((tmp + 10UL) & 0x1FUL);
#else
// Defined in linker script for external flash provided by customers.
extern uint32_t __flash_page_size__;
return (uintptr_t)&__flash_page_size__;
#endif
}
/***************************************************************************//**
* @brief Get the MCU part number.
******************************************************************************/
uint16_t sl_hal_system_get_part_number(void)
{
#if defined(_DEVINFO_PART_DEVICENUM_MASK)
return (uint16_t)((DEVINFO->PART & _DEVINFO_PART_DEVICENUM_MASK)
>> _DEVINFO_PART_DEVICENUM_SHIFT);
#elif defined(_DEVINFO_PART0_DIECODE0_MASK) && defined(_SILICON_LABS_SECURITY_FEATURE_VAULT)
// Encode features to the series 2 format.
// Add security level vault high for SIxG301.
uint16_t device_number = 1000;
uint32_t register_value = (DEVINFO->PART1 & _DEVINFO_PART1_FEATURE1_MASK) >> _DEVINFO_PART1_FEATURE1_SHIFT;
device_number = sli_hex_ascii_to_value((char)register_value) * 100;
register_value = (DEVINFO->PART1 & _DEVINFO_PART1_FEATURE2_MASK) >> _DEVINFO_PART1_FEATURE2_SHIFT;
device_number += sli_hex_ascii_to_value((char)register_value) * 10;
register_value = (DEVINFO->PART2 & _DEVINFO_PART2_FEATURE3_MASK) >> _DEVINFO_PART2_FEATURE3_SHIFT;
device_number += sli_hex_ascii_to_value((char)register_value);
return device_number;
#else
#error (em_system.c): Location of device part number is not defined.
#endif
}
/***************************************************************************//**
* @brief Get the SoC or MCU features.
******************************************************************************/
sl_hal_system_features_t sl_hal_system_get_part_features(void)
{
sl_hal_system_features_t part_features = { .feature1 = '0', .feature2 = '0', .feature3 = '0' };
#if defined(_SILICON_LABS_32B_SERIES_2)
uint16_t device_number = ((DEVINFO->PART & _DEVINFO_PART_DEVICENUM_MASK) >> _DEVINFO_PART_DEVICENUM_SHIFT);
part_features.feature1 = sli_get_n_digit(device_number, 2);
part_features.feature2 = sli_get_n_digit(device_number, 1);
part_features.feature3 = sli_get_n_digit(device_number, 0);
#elif defined(_SILICON_LABS_32B_SERIES_3)
part_features.feature1 = (DEVINFO->PART1 & _DEVINFO_PART1_FEATURE1_MASK) >> _DEVINFO_PART1_FEATURE1_SHIFT;
part_features.feature2 = (DEVINFO->PART1 & _DEVINFO_PART1_FEATURE2_MASK) >> _DEVINFO_PART1_FEATURE2_SHIFT;
part_features.feature3 = (DEVINFO->PART2 & _DEVINFO_PART2_FEATURE3_MASK) >> _DEVINFO_PART2_FEATURE3_SHIFT;
#else
#error Not defined for this die.
#endif
return part_features;
}
/***************************************************************************//**
* @brief Get the temperature information.
******************************************************************************/
void sl_hal_system_get_temperature_info(sl_hal_system_devinfo_temperature_t *info)
{
#if defined(_DEVINFO_CALTEMP_MASK) || defined(_DEVINFO_EMUTEMP_MASK)
#if defined(_DEVINFO_CALTEMP_TEMP_MASK)
info->cal_temp = ((DEVINFO->CALTEMP & _DEVINFO_CALTEMP_TEMP_MASK)
>> _DEVINFO_CALTEMP_TEMP_SHIFT);
#else
info->cal_temp = 0;
#endif
#if defined(_DEVINFO_EMUTEMP_EMUTEMPROOM_MASK)
info->emu_temp_room = ((DEVINFO->EMUTEMP & _DEVINFO_EMUTEMP_EMUTEMPROOM_MASK)
>> _DEVINFO_EMUTEMP_EMUTEMPROOM_SHIFT);
#else
info->emu_temp_room = 0;
#endif
#elif defined (_SILICON_LABS_32B_SERIES_3_CONFIG_301)
sl_status_t status;
sl_se_command_context_t se_command_ctx;
sli_se_device_data_t otp_section_id = (sli_se_device_data_t)(SLI_SE_DEVICE_DATA_DI0 + DEVINFO_GP_FRAGMENT_INDEX);
uint32_t offset = DEVINFO_GP_TEMPERATURE_OFFSET;
// Initialize command context
status = sl_se_init_command_context(&se_command_ctx);
if (status != SL_STATUS_OK) {
*info = SL_HAL_SYSTEM_DEVINFO_TEMPERATURE_RESET_VALUES;
return;
}
// Send the SE command to retrieve the temperature information from the DEVINFO OTP section
status = sli_se_device_data_read_word(&se_command_ctx, otp_section_id, offset, (uint32_t*)info);
if (status != SL_STATUS_OK) {
*info = SL_HAL_SYSTEM_DEVINFO_TEMPERATURE_RESET_VALUES;
return;
}
// Divide the temperature by 16 to retrieve only the integer part of the temperature value.
info->cal_temp = info->cal_temp >> DEVINFO_TEMPERATURE_CALTEMP_INTEGER_SHIFT;
#else
(void)info;
#endif
}
/*******************************************************************************
* @brief Reads CHIPREV register.
******************************************************************************/
uint32_t sl_hal_syscfg_read_chip_rev(void)
{
#if defined(SL_TRUSTZONE_NONSECURE)
return sli_tz_syscfg_read_chiprev_register();
#else
return SYSCFG->CHIPREV;
#endif
}
/*******************************************************************************
* @brief Set SYSTICEXTCLKEN bit in CFGSYSTIC to one.
******************************************************************************/
void sl_hal_syscfg_set_systicextclken_cfgsystic(void)
{
#if defined(SL_TRUSTZONE_NONSECURE)
sli_tz_syscfg_set_systicextclken_cfgsystic();
#else
SYSCFG->CFGSYSTIC = (SYSCFG->CFGSYSTIC | _SYSCFG_CFGSYSTIC_SYSTICEXTCLKEN_MASK);
#endif
}
/*******************************************************************************
* @brief Clear SYSTICEXTCLKEN bit in CFGSYSTIC to zero.
******************************************************************************/
void sl_hal_syscfg_clear_systicextclken_cfgsystic(void)
{
#if defined(SL_TRUSTZONE_NONSECURE)
sli_tz_syscfg_clear_systicextclken_cfgsystic();
#else
SYSCFG->CFGSYSTIC = (SYSCFG->CFGSYSTIC & ~_SYSCFG_CFGSYSTIC_SYSTICEXTCLKEN_MASK);
#endif
}
#if defined(__FPU_PRESENT) && (__FPU_PRESENT == 1)
/***************************************************************************//**
* @brief Set floating point co-processor (FPU) access mode.
******************************************************************************/
void sl_hal_system_fpu_set_access_mode(sl_hal_system_fpu_access_t access_mode)
{
SCB->CPACR = (SCB->CPACR & ~(0xFUL << 20)) | access_mode;
}
#endif
/***************************************************************************//**
* @brief Get the ADC calibration info.
******************************************************************************/
void sl_hal_system_get_adc_calibration_info(sl_hal_system_devinfo_adc_t *info)
{
#if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
sl_status_t status;
sl_se_command_context_t se_command_ctx;
sli_se_device_data_t otp_section_id = (sli_se_device_data_t)(SLI_SE_DEVICE_DATA_DI0 + DEVINFO_GP_FRAGMENT_INDEX);
uint32_t offset = DEVINFO_GP_ADC0CALDATA_OFFSET;
EFM_ASSERT(info != NULL);
// Initialize command context
status = sl_se_init_command_context(&se_command_ctx);
if (status != SL_STATUS_OK) {
*info = SL_HAL_SYSTEM_DEVINFO_ADC_RESET_VALUES;
return;
}
// Send the SE command to retrieve the ADC calibration from the DEVINFO OTP section
status = sli_se_device_data_read_chunk(&se_command_ctx,
otp_section_id,
offset,
sizeof(sl_hal_system_devinfo_adc_offset_t),
info);
if (status != SL_STATUS_OK) {
*info = SL_HAL_SYSTEM_DEVINFO_ADC_RESET_VALUES;
return;
}
#else
*info = SL_HAL_SYSTEM_DEVINFO_ADC_RESET_VALUES;
#endif
}
/** @} (end addtogroup system) */