mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
feat(hw_support): add atomic code block for peripheral bus clock and reset
This commit is contained in:
parent
7f85830a3b
commit
a9c813ca3e
@ -1,16 +1,73 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include "soc/periph_defs.h"
|
#include "soc/periph_defs.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup Reset and Clock Control APIs
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire the RCC lock for a peripheral module
|
||||||
|
*
|
||||||
|
* @note User code protected by this macro should be as short as possible, because it's a critical section
|
||||||
|
* @note This macro will increase the reference lock of that peripheral.
|
||||||
|
* You can get the value before the increment from the `rc_name` local variable
|
||||||
|
*/
|
||||||
|
#define PERIPH_RCC_ACQUIRE_ATOMIC(periph, rc_name) \
|
||||||
|
for (uint8_t rc_name, i = 1, __DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||||
|
i ? (rc_name = periph_rcc_acquire_enter(periph), 1) : 0; \
|
||||||
|
periph_rcc_acquire_exit(periph, rc_name), i--)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release the RCC lock for a peripheral module
|
||||||
|
*
|
||||||
|
* @note User code protected by this macro should be as short as possible, because it's a critical section
|
||||||
|
* @note This macro will decrease the reference lock of that peripheral.
|
||||||
|
* You can get the value before the increment from the `rc_name` local variable
|
||||||
|
*/
|
||||||
|
#define PERIPH_RCC_RELEASE_ATOMIC(periph, rc_name) \
|
||||||
|
for (uint8_t rc_name, i = 1, __DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||||
|
i ? (rc_name = periph_rcc_release_enter(periph), 1) : 0; \
|
||||||
|
periph_rcc_release_exit(periph, rc_name), i--)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A simplified version of `PERIPH_RCC_ACQUIRE/RELEASE_ATOMIC`, without a reference count
|
||||||
|
*
|
||||||
|
* @note User code protected by this macro should be as short as possible, because it's a critical section
|
||||||
|
*/
|
||||||
|
#define PERIPH_RCC_ATOMIC() \
|
||||||
|
for (int i = 1, __DECLARE_RCC_ATOMIC_ENV; \
|
||||||
|
i ? (periph_rcc_enter(), 1) : 0; \
|
||||||
|
periph_rcc_exit(), i--)
|
||||||
|
|
||||||
|
/** @cond */
|
||||||
|
// The following functions are not intended to be used directly by the developers
|
||||||
|
uint8_t periph_rcc_acquire_enter(periph_module_t periph);
|
||||||
|
void periph_rcc_acquire_exit(periph_module_t periph, uint8_t ref_count);
|
||||||
|
uint8_t periph_rcc_release_enter(periph_module_t periph);
|
||||||
|
void periph_rcc_release_exit(periph_module_t periph, uint8_t ref_count);
|
||||||
|
void periph_rcc_enter(void);
|
||||||
|
void periph_rcc_exit(void);
|
||||||
|
/** @endcond */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************************************************************************************************
|
||||||
|
* @note The following APIs are no longer supported since ESP32P4, please use the RCC lock macros instead.
|
||||||
|
*************************************************************************************************************/
|
||||||
/**
|
/**
|
||||||
* @brief Enable peripheral module by un-gating the clock and de-asserting the reset signal.
|
* @brief Enable peripheral module by un-gating the clock and de-asserting the reset signal.
|
||||||
*
|
*
|
||||||
|
@ -13,10 +13,46 @@
|
|||||||
#include "esp_private/esp_modem_clock.h"
|
#include "esp_private/esp_modem_clock.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// @brief For simplicity and backward compatible, we are using the same spin lock for both bus clock on/off and reset
|
||||||
|
/// @note We may want to split them into two spin locks in the future
|
||||||
static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
static uint8_t ref_counts[PERIPH_MODULE_MAX] = {0};
|
static uint8_t ref_counts[PERIPH_MODULE_MAX] = {0};
|
||||||
|
|
||||||
|
void periph_rcc_enter(void)
|
||||||
|
{
|
||||||
|
portENTER_CRITICAL_SAFE(&periph_spinlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void periph_rcc_exit(void)
|
||||||
|
{
|
||||||
|
portEXIT_CRITICAL_SAFE(&periph_spinlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t periph_rcc_acquire_enter(periph_module_t periph)
|
||||||
|
{
|
||||||
|
periph_rcc_enter();
|
||||||
|
return ref_counts[periph];
|
||||||
|
}
|
||||||
|
|
||||||
|
void periph_rcc_acquire_exit(periph_module_t periph, uint8_t ref_count)
|
||||||
|
{
|
||||||
|
ref_counts[periph] = ++ref_count;
|
||||||
|
periph_rcc_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t periph_rcc_release_enter(periph_module_t periph)
|
||||||
|
{
|
||||||
|
periph_rcc_enter();
|
||||||
|
return ref_counts[periph] - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void periph_rcc_release_exit(periph_module_t periph, uint8_t ref_count)
|
||||||
|
{
|
||||||
|
ref_counts[periph] = ref_count;
|
||||||
|
periph_rcc_exit();
|
||||||
|
}
|
||||||
|
|
||||||
void periph_module_enable(periph_module_t periph)
|
void periph_module_enable(periph_module_t periph)
|
||||||
{
|
{
|
||||||
assert(periph < PERIPH_MODULE_MAX);
|
assert(periph < PERIPH_MODULE_MAX);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user