Merge branch 'refactor/spi_using_rcc_automic_lock' into 'master'

refac(spi): update periph_module_xxx with rcc_atomic_lock for periph bus

Closes IDF-8159

See merge request espressif/esp-idf!26394
This commit is contained in:
Wan Lei
2023-10-18 20:36:51 +08:00
11 changed files with 594 additions and 39 deletions

View File

@@ -29,7 +29,7 @@
#include "hal/cache_ll.h" #include "hal/cache_ll.h"
#endif #endif
#if SOC_PERIPH_CLK_CTRL_SHARED #if !SOC_RCC_IS_INDEPENDENT
#define SPI_COMMON_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC() #define SPI_COMMON_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC()
#else #else
#define SPI_COMMON_RCC_CLOCK_ATOMIC() #define SPI_COMMON_RCC_CLOCK_ATOMIC()
@@ -107,15 +107,10 @@ bool spicommon_periph_claim(spi_host_device_t host, const char* source)
bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &false_var, true); bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &false_var, true);
if (ret) { if (ret) {
spi_claiming_func[host] = source; spi_claiming_func[host] = source;
#if CONFIG_IDF_TARGET_ESP32P4 //deprecate clk_gate_ll start from p4, others in TODO: IDF-8159
SPI_COMMON_RCC_CLOCK_ATOMIC() { SPI_COMMON_RCC_CLOCK_ATOMIC() {
spi_ll_enable_bus_clock(host, true); spi_ll_enable_bus_clock(host, true);
spi_ll_reset_register(host); spi_ll_reset_register(host);
spi_ll_enable_clock(host, true);
} }
#else
periph_module_enable(spi_periph_signal[host].module);
#endif
} else { } else {
ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host+1, spi_claiming_func[host]); ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host+1, spi_claiming_func[host]);
} }
@@ -133,13 +128,9 @@ bool spicommon_periph_free(spi_host_device_t host)
bool true_var = true; bool true_var = true;
bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &true_var, false); bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &true_var, false);
if (ret) { if (ret) {
#if CONFIG_IDF_TARGET_ESP32P4
SPI_COMMON_RCC_CLOCK_ATOMIC() { SPI_COMMON_RCC_CLOCK_ATOMIC() {
spi_ll_enable_bus_clock(host, false); spi_ll_enable_bus_clock(host, false);
} }
#else
periph_module_disable(spi_periph_signal[host].module);
#endif
} }
return ret; return ret;
} }
@@ -156,10 +147,11 @@ int spicommon_irqdma_source_for_host(spi_host_device_t host)
//----------------------------------------------------------alloc dma periph-------------------------------------------------------// //----------------------------------------------------------alloc dma periph-------------------------------------------------------//
#if !SOC_GDMA_SUPPORTED #if !SOC_GDMA_SUPPORTED
#if SPI_LL_DMA_SHARED
static inline periph_module_t get_dma_periph(int dma_chan) static inline periph_module_t get_dma_periph(int dma_chan)
{ {
assert(dma_chan >= 1 && dma_chan <= SOC_SPI_DMA_CHAN_NUM); assert(dma_chan >= 1 && dma_chan <= SOC_SPI_DMA_CHAN_NUM);
#if CONFIG_IDF_TARGET_ESP32S2
if (dma_chan == 1) { if (dma_chan == 1) {
return PERIPH_SPI2_DMA_MODULE; return PERIPH_SPI2_DMA_MODULE;
} else if (dma_chan == 2) { } else if (dma_chan == 2) {
@@ -167,10 +159,8 @@ static inline periph_module_t get_dma_periph(int dma_chan)
} else { } else {
abort(); abort();
} }
#elif CONFIG_IDF_TARGET_ESP32
return PERIPH_SPI_DMA_MODULE;
#endif
} }
#endif
static bool claim_dma_chan(int dma_chan, uint32_t *out_actual_dma_chan) static bool claim_dma_chan(int dma_chan, uint32_t *out_actual_dma_chan)
{ {
@@ -180,7 +170,21 @@ static bool claim_dma_chan(int dma_chan, uint32_t *out_actual_dma_chan)
bool is_used = (BIT(dma_chan) & spi_dma_chan_enabled); bool is_used = (BIT(dma_chan) & spi_dma_chan_enabled);
if (!is_used) { if (!is_used) {
spi_dma_chan_enabled |= BIT(dma_chan); spi_dma_chan_enabled |= BIT(dma_chan);
periph_module_enable(get_dma_periph(dma_chan)); #if SPI_LL_DMA_SHARED
PERIPH_RCC_ACQUIRE_ATOMIC(get_dma_periph(dma_chan), ref_count) {
//esp32s2: dma_chan index is same as spi host_id, no matter dma_chan_auto or not
if (ref_count == 0) {
spi_dma_ll_enable_bus_clock(dma_chan, true);
spi_dma_ll_reset_register(dma_chan);
}
}
#else
SPI_COMMON_RCC_CLOCK_ATOMIC() {
//esp32: have only one spi_dma
spi_dma_ll_enable_bus_clock(dma_chan, true);
spi_dma_ll_reset_register(dma_chan);
}
#endif
*out_actual_dma_chan = dma_chan; *out_actual_dma_chan = dma_chan;
ret = true; ret = true;
} }
@@ -355,7 +359,17 @@ static esp_err_t dma_chan_free(spi_host_device_t host_id)
portENTER_CRITICAL(&spi_dma_spinlock); portENTER_CRITICAL(&spi_dma_spinlock);
spi_dma_chan_enabled &= ~BIT(dma_chan); spi_dma_chan_enabled &= ~BIT(dma_chan);
periph_module_disable(get_dma_periph(dma_chan)); #if SPI_LL_DMA_SHARED
PERIPH_RCC_RELEASE_ATOMIC(get_dma_periph(dma_chan), ref_count) {
if (ref_count == 0) {
spi_dma_ll_enable_bus_clock(host_id, false);
}
}
#else
SPI_COMMON_RCC_CLOCK_ATOMIC() {
spi_dma_ll_enable_bus_clock(host_id, false);
}
#endif
portEXIT_CRITICAL(&spi_dma_spinlock); portEXIT_CRITICAL(&spi_dma_spinlock);
#else //SOC_GDMA_SUPPORTED #else //SOC_GDMA_SUPPORTED

View File

@@ -177,9 +177,9 @@ static const char *SPI_TAG = "spi_master";
#define SPI_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE_ISR(a, ret_val, SPI_TAG, str) #define SPI_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE_ISR(a, ret_val, SPI_TAG, str)
#if SOC_PERIPH_CLK_CTRL_SHARED #if SOC_PERIPH_CLK_CTRL_SHARED
#define SPI_MASTER_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC() #define SPI_MASTER_PERI_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC()
#else #else
#define SPI_MASTER_RCC_CLOCK_ATOMIC() #define SPI_MASTER_PERI_CLOCK_ATOMIC()
#endif #endif
static void spi_intr(void *arg); static void spi_intr(void *arg);
@@ -270,6 +270,9 @@ static esp_err_t spi_master_init_driver(spi_host_device_t host_id)
.rx_dma_chan = bus_attr->rx_dma_chan, .rx_dma_chan = bus_attr->rx_dma_chan,
.dmadesc_n = bus_attr->dma_desc_num, .dmadesc_n = bus_attr->dma_desc_num,
}; };
SPI_MASTER_PERI_CLOCK_ATOMIC() {
spi_ll_enable_clock(host_id, true);
}
spi_hal_init(&host->hal, host_id, &hal_config); spi_hal_init(&host->hal, host_id, &hal_config);
if (host_id != SPI1_HOST) { if (host_id != SPI1_HOST) {
@@ -556,7 +559,7 @@ static SPI_MASTER_ISR_ATTR void spi_setup_device(spi_device_t *dev)
if (spi_bus_lock_touch(dev_lock)) { if (spi_bus_lock_touch(dev_lock)) {
/* Configuration has not been applied yet. */ /* Configuration has not been applied yet. */
spi_hal_setup_device(hal, hal_dev); spi_hal_setup_device(hal, hal_dev);
SPI_MASTER_RCC_CLOCK_ATOMIC() { SPI_MASTER_PERI_CLOCK_ATOMIC() {
spi_ll_set_clk_source(hal->hw, hal_dev->timing_conf.clock_source); spi_ll_set_clk_source(hal->hw, hal_dev->timing_conf.clock_source);
} }
} }

View File

@@ -177,21 +177,21 @@ void IRAM_ATTR int_handler2(void *arg)
} }
} }
#if !SOC_RCC_IS_INDEPENDENT
#define TEST_BUS_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define TEST_BUS_RCC_CLOCK_ATOMIC()
#endif
TEST_CASE("allocate 2 handlers for a same source and remove the later one", "[intr_alloc]") TEST_CASE("allocate 2 handlers for a same source and remove the later one", "[intr_alloc]")
{ {
intr_alloc_test_ctx_t ctx = {false, false, false, false }; intr_alloc_test_ctx_t ctx = {false, false, false, false };
intr_handle_t handle1, handle2; intr_handle_t handle1, handle2;
// enable SPI2 // enable SPI2
#if CONFIG_IDF_TARGET_ESP32P4 //deprecate clk_gate_ll start from p4, others in TODO: IDF-8159 TEST_BUS_RCC_CLOCK_ATOMIC() {
PERIPH_RCC_ATOMIC() {
spi_ll_enable_bus_clock(1, true); spi_ll_enable_bus_clock(1, true);
spi_ll_reset_register(1); spi_ll_reset_register(1);
spi_ll_enable_clock(1, true);
} }
#else
periph_module_enable(spi_periph_signal[1].module);
#endif
esp_err_t r; esp_err_t r;
r = esp_intr_alloc(spi_periph_signal[1].irq, ESP_INTR_FLAG_SHARED, int_handler1, &ctx, &handle1); r = esp_intr_alloc(spi_periph_signal[1].irq, ESP_INTR_FLAG_SHARED, int_handler1, &ctx, &handle1);

View File

@@ -20,6 +20,7 @@
#include "esp32/rom/lldesc.h" #include "esp32/rom/lldesc.h"
#include "soc/spi_periph.h" #include "soc/spi_periph.h"
#include "soc/spi_struct.h" #include "soc/spi_struct.h"
#include "soc/dport_reg.h"
#include "hal/misc.h" #include "hal/misc.h"
#include "hal/spi_types.h" #include "hal/spi_types.h"
#include "hal/assert.h" #include "hal/assert.h"
@@ -56,6 +57,86 @@ typedef spi_dev_t spi_dma_dev_t;
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Enable peripheral register clock
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
if (enable) {
switch (host_id)
{
case SPI1_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
break;
case SPI2_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
break;
case SPI3_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
break;
default: HAL_ASSERT(false);
}
} else {
switch (host_id)
{
case SPI1_HOST:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
break;
case SPI2_HOST:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
break;
case SPI3_HOST:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
break;
default: HAL_ASSERT(false);
}
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__)
/**
* Reset whole peripheral register to init value defined by HW design
*
* @param host_id Peripheral index number, see `spi_host_device_t`
*/
static inline void spi_ll_reset_register(spi_host_device_t host_id) {
switch (host_id)
{
case SPI1_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
break;
case SPI2_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
break;
case SPI3_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
break;
default: HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__)
/**
* Enable functional output clock within peripheral
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable)
{
//empty, keep this for compatibility
}
/** /**
* Select SPI peripheral clock source (master). * Select SPI peripheral clock source (master).
@@ -970,6 +1051,39 @@ static inline void spi_ll_enable_int(spi_dev_t *hw)
* RX DMA (Peripherals->DMA->RAM) * RX DMA (Peripherals->DMA->RAM)
* TX DMA (RAM->DMA->Peripherals) * TX DMA (RAM->DMA->Peripherals)
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Enable peripheral register clock
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_dma_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
(void)host_id; // has only one spi_dma
if (enable) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_DMA_CLK_EN);
} else {
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_DMA_CLK_EN);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_dma_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_dma_ll_enable_bus_clock(__VA_ARGS__)
/**
* Reset whole peripheral register to init value defined by HW design
*
* @param host_id Peripheral index number, see `spi_host_device_t`
*/
static inline void spi_dma_ll_reset_register(spi_host_device_t host_id) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_dma_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_dma_ll_reset_register(__VA_ARGS__)
/** /**
* Reset RX DMA which stores the data received from a peripheral into RAM. * Reset RX DMA which stores the data received from a peripheral into RAM.
* *

View File

@@ -20,6 +20,7 @@
#include "esp_types.h" #include "esp_types.h"
#include "soc/spi_periph.h" #include "soc/spi_periph.h"
#include "soc/spi_struct.h" #include "soc/spi_struct.h"
#include "soc/system_struct.h"
#include "soc/lldesc.h" #include "soc/lldesc.h"
#include "hal/assert.h" #include "hal/assert.h"
#include "hal/misc.h" #include "hal/misc.h"
@@ -36,7 +37,7 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) #define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : NULL)
#define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits
#define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words
@@ -90,6 +91,65 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Enable peripheral register clock
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
switch (host_id)
{
case SPI1_HOST:
SYSTEM.perip_clk_en0.spi01_clk_en = enable;
break;
case SPI2_HOST:
SYSTEM.perip_clk_en0.spi2_clk_en = enable;
break;
default: HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__)
/**
* Reset whole peripheral register to init value defined by HW design
*
* @param host_id Peripheral index number, see `spi_host_device_t`
*/
static inline void spi_ll_reset_register(spi_host_device_t host_id) {
switch (host_id)
{
case SPI1_HOST:
SYSTEM.perip_rst_en0.spi01_rst = 1;
SYSTEM.perip_rst_en0.spi01_rst = 0;
break;
case SPI2_HOST:
SYSTEM.perip_rst_en0.spi2_rst = 1;
SYSTEM.perip_rst_en0.spi2_rst = 0;
break;
default: HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__)
/**
* Enable functional output clock within peripheral
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable)
{
spi_dev_t *hw = SPI_LL_GET_HW(host_id);
HAL_ASSERT(hw != NULL);
hw->clk_gate.clk_en = enable;
}
/** /**
* Select SPI peripheral clock source (master). * Select SPI peripheral clock source (master).
@@ -129,7 +189,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw)
hw->slave.val = 0; hw->slave.val = 0;
hw->user.val = 0; hw->user.val = 0;
hw->clk_gate.clk_en = 1;
hw->clk_gate.mst_clk_active = 1; hw->clk_gate.mst_clk_active = 1;
hw->clk_gate.mst_clk_sel = 1; hw->clk_gate.mst_clk_sel = 1;

View File

@@ -20,6 +20,7 @@
#include "esp_types.h" #include "esp_types.h"
#include "soc/spi_periph.h" #include "soc/spi_periph.h"
#include "soc/spi_struct.h" #include "soc/spi_struct.h"
#include "soc/system_struct.h"
#include "soc/lldesc.h" #include "soc/lldesc.h"
#include "hal/assert.h" #include "hal/assert.h"
#include "hal/misc.h" #include "hal/misc.h"
@@ -36,7 +37,7 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) #define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : NULL)
#define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits
#define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words
@@ -92,6 +93,65 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Enable peripheral register clock
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
switch (host_id)
{
case SPI1_HOST:
SYSTEM.perip_clk_en0.reg_spi01_clk_en = enable;
break;
case SPI2_HOST:
SYSTEM.perip_clk_en0.reg_spi2_clk_en = enable;
break;
default: HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__)
/**
* Reset whole peripheral register to init value defined by HW design
*
* @param host_id Peripheral index number, see `spi_host_device_t`
*/
static inline void spi_ll_reset_register(spi_host_device_t host_id) {
switch (host_id)
{
case SPI1_HOST:
SYSTEM.perip_rst_en0.reg_spi01_rst = 1;
SYSTEM.perip_rst_en0.reg_spi01_rst = 0;
break;
case SPI2_HOST:
SYSTEM.perip_rst_en0.reg_spi2_rst = 1;
SYSTEM.perip_rst_en0.reg_spi2_rst = 0;
break;
default: HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__)
/**
* Enable functional output clock within peripheral
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable)
{
spi_dev_t *hw = SPI_LL_GET_HW(host_id);
HAL_ASSERT(hw != NULL);
hw->clk_gate.clk_en = enable;
}
/** /**
* Select SPI peripheral clock source (master). * Select SPI peripheral clock source (master).
@@ -131,7 +191,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw)
hw->slave.val = 0; hw->slave.val = 0;
hw->user.val = 0; hw->user.val = 0;
hw->clk_gate.clk_en = 1;
hw->clk_gate.mst_clk_active = 1; hw->clk_gate.mst_clk_active = 1;
hw->clk_gate.mst_clk_sel = 1; hw->clk_gate.mst_clk_sel = 1;

View File

@@ -37,7 +37,7 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) #define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : NULL)
#define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits
#define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words
@@ -91,6 +91,56 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Enable peripheral register clock
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
switch (host_id)
{
case SPI1_HOST:
PCR.mspi_conf.mspi_clk_en = enable;
break;
case SPI2_HOST:
PCR.spi2_conf.spi2_clk_en = enable;
break;
default: HAL_ASSERT(false);
}
}
/**
* Reset whole peripheral register to init value defined by HW design
*
* @param host_id Peripheral index number, see `spi_host_device_t`
*/
static inline void spi_ll_reset_register(spi_host_device_t host_id) {
switch (host_id)
{
case SPI1_HOST:
PCR.mspi_conf.mspi_rst_en = 1;
PCR.mspi_conf.mspi_rst_en = 0;
break;
case SPI2_HOST:
PCR.spi2_conf.spi2_rst_en = 1;
PCR.spi2_conf.spi2_rst_en = 0;
break;
default: HAL_ASSERT(false);
}
}
/**
* Enable functional output clock within peripheral
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable)
{
(void) host_id;
PCR.spi2_clkm_conf.spi2_clkm_en = enable;
}
/** /**
* Select SPI peripheral clock source (master). * Select SPI peripheral clock source (master).
@@ -134,7 +184,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw)
hw->slave.val = 0; hw->slave.val = 0;
hw->user.val = 0; hw->user.val = 0;
PCR.spi2_clkm_conf.spi2_clkm_en = 1;
PCR.spi2_clkm_conf.spi2_clkm_sel = 1; PCR.spi2_clkm_conf.spi2_clkm_sel = 1;
hw->dma_conf.val = 0; hw->dma_conf.val = 0;

View File

@@ -37,9 +37,7 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
/// This is the expected clock frequency #define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : NULL)
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2)
#define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits
#define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words
@@ -92,7 +90,56 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Enable peripheral register clock
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
switch (host_id)
{
case SPI1_HOST:
PCR.mspi_conf.mspi_clk_en = enable;
break;
case SPI2_HOST:
PCR.spi2_conf.spi2_clk_en = enable;
break;
default: HAL_ASSERT(false);
}
}
/**
* Reset whole peripheral register to init value defined by HW design
*
* @param host_id Peripheral index number, see `spi_host_device_t`
*/
static inline void spi_ll_reset_register(spi_host_device_t host_id) {
switch (host_id)
{
case SPI1_HOST:
PCR.mspi_conf.mspi_rst_en = 1;
PCR.mspi_conf.mspi_rst_en = 0;
break;
case SPI2_HOST:
PCR.spi2_conf.spi2_rst_en = 1;
PCR.spi2_conf.spi2_rst_en = 0;
break;
default: HAL_ASSERT(false);
}
}
/**
* Enable functional output clock within peripheral
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable)
{
(void) host_id;
PCR.spi2_clkm_conf.spi2_clkm_en = enable;
}
/** /**
* Select SPI peripheral clock source (master). * Select SPI peripheral clock source (master).
@@ -136,7 +183,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw)
hw->slave.val = 0; hw->slave.val = 0;
hw->user.val = 0; hw->user.val = 0;
PCR.spi2_clkm_conf.spi2_clkm_en = 1;
PCR.spi2_clkm_conf.spi2_clkm_sel = 0; PCR.spi2_clkm_conf.spi2_clkm_sel = 0;
hw->dma_conf.val = 0; hw->dma_conf.val = 0;

View File

@@ -36,7 +36,7 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3)) #define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : (((ID)==2) ? &GPSPI3 : NULL))
#define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits
#define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words

View File

@@ -20,6 +20,7 @@
#include "esp_attr.h" #include "esp_attr.h"
#include "soc/spi_periph.h" #include "soc/spi_periph.h"
#include "soc/spi_struct.h" #include "soc/spi_struct.h"
#include "soc/dport_reg.h"
#include "soc/lldesc.h" #include "soc/lldesc.h"
#include "hal/assert.h" #include "hal/assert.h"
#include "hal/misc.h" #include "hal/misc.h"
@@ -39,11 +40,12 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_OCT | SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_OCT | SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3)) #define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : (((ID)==2) ? &GPSPI3 : NULL))
#define SPI_LL_DMA_MAX_BIT_LEN (1 << 23) //reg len: 23 bits #define SPI_LL_DMA_MAX_BIT_LEN (1 << 23) //reg len: 23 bits
#define SPI_LL_CPU_MAX_BIT_LEN (18 * 32) //Fifo len: 18 words #define SPI_LL_CPU_MAX_BIT_LEN (18 * 32) //Fifo len: 18 words
#define SPI_LL_MOSI_FREE_LEVEL 1 //Default level after bus initialized #define SPI_LL_MOSI_FREE_LEVEL 1 //Default level after bus initialized
#define SPI_LL_DMA_SHARED 1 //spi_dma shared with adc and dac on S2
/** /**
* The data structure holding calculated clock configuration. Since the * The data structure holding calculated clock configuration. Since the
@@ -100,6 +102,86 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Enable peripheral register clock
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
if (enable) {
switch (host_id)
{
case SPI1_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
break;
case SPI2_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
break;
case SPI3_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
break;
default: HAL_ASSERT(false);
}
} else {
switch (host_id)
{
case SPI1_HOST:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
break;
case SPI2_HOST:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
break;
case SPI3_HOST:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
break;
default: HAL_ASSERT(false);
}
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__)
/**
* Reset whole peripheral register to init value defined by HW design
*
* @param host_id Peripheral index number, see `spi_host_device_t`
*/
static inline void spi_ll_reset_register(spi_host_device_t host_id) {
switch (host_id)
{
case SPI1_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
break;
case SPI2_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
break;
case SPI3_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
break;
default: HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__)
/**
* Enable functional output clock within peripheral
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable)
{
//empty, keep this for compatibility
}
/** /**
* Select SPI peripheral clock source (master). * Select SPI peripheral clock source (master).
@@ -1114,6 +1196,69 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
* RX DMA (Peripherals->DMA->RAM) * RX DMA (Peripherals->DMA->RAM)
* TX DMA (RAM->DMA->Peripherals) * TX DMA (RAM->DMA->Peripherals)
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Enable peripheral register clock
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_dma_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
if (enable) {
switch (host_id)
{
case SPI2_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_DMA_CLK_EN);
break;
case SPI3_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_DMA_CLK_EN);
break;
default:
HAL_ASSERT(false);
}
} else {
switch (host_id)
{
case SPI2_HOST:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_DMA_CLK_EN);
break;
case SPI3_HOST:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_DMA_CLK_EN);
break;
default:
HAL_ASSERT(false);
}
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define spi_dma_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; spi_dma_ll_enable_bus_clock(__VA_ARGS__)
/**
* Reset whole peripheral register to init value defined by HW design
*
* @param host_id Peripheral index number, see `spi_host_device_t`
*/
static inline void spi_dma_ll_reset_register(spi_host_device_t host_id) {
switch (host_id)
{
case SPI2_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_DMA_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_DMA_RST);
break;
case SPI3_HOST:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_DMA_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_DMA_RST);
break;
default:
HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define spi_dma_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; spi_dma_ll_reset_register(__VA_ARGS__)
//---------------------------------------------------RX-------------------------------------------------// //---------------------------------------------------RX-------------------------------------------------//
/** /**
* Reset RX DMA which stores the data received from a peripheral into RAM. * Reset RX DMA which stores the data received from a peripheral into RAM.

View File

@@ -20,6 +20,7 @@
#include "esp_types.h" #include "esp_types.h"
#include "soc/spi_periph.h" #include "soc/spi_periph.h"
#include "soc/spi_struct.h" #include "soc/spi_struct.h"
#include "soc/system_struct.h"
#include "soc/lldesc.h" #include "soc/lldesc.h"
#include "hal/assert.h" #include "hal/assert.h"
#include "hal/misc.h" #include "hal/misc.h"
@@ -38,7 +39,7 @@ extern "C" {
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3)) #define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : (((ID)==2) ? &GPSPI3 : NULL))
#define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits
#define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words
@@ -92,6 +93,72 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Enable peripheral register clock
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
switch (host_id)
{
case SPI1_HOST:
SYSTEM.perip_clk_en0.spi01_clk_en = enable;
break;
case SPI2_HOST:
SYSTEM.perip_clk_en0.spi2_clk_en = enable;
break;
case SPI3_HOST:
SYSTEM.perip_clk_en0.spi3_clk_en = enable;
break;
default: HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__)
/**
* Reset whole peripheral register to init value defined by HW design
*
* @param host_id Peripheral index number, see `spi_host_device_t`
*/
static inline void spi_ll_reset_register(spi_host_device_t host_id) {
switch (host_id)
{
case SPI1_HOST:
SYSTEM.perip_rst_en0.spi01_rst = 1;
SYSTEM.perip_rst_en0.spi01_rst = 0;
break;
case SPI2_HOST:
SYSTEM.perip_rst_en0.spi2_rst = 1;
SYSTEM.perip_rst_en0.spi2_rst = 0;
break;
case SPI3_HOST:
SYSTEM.perip_rst_en0.spi3_rst = 1;
SYSTEM.perip_rst_en0.spi3_rst = 0;
break;
default: HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__)
/**
* Enable functional output clock within peripheral
*
* @param host_id Peripheral index number, see `spi_host_device_t`
* @param enable Enable/Disable
*/
static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable)
{
spi_dev_t *hw = SPI_LL_GET_HW(host_id);
HAL_ASSERT(hw != NULL);
hw->clk_gate.clk_en = enable;
}
/** /**
* Select SPI peripheral clock source (master). * Select SPI peripheral clock source (master).
@@ -131,7 +198,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw)
hw->slave.val = 0; hw->slave.val = 0;
hw->user.val = 0; hw->user.val = 0;
hw->clk_gate.clk_en = 1;
hw->clk_gate.mst_clk_active = 1; hw->clk_gate.mst_clk_active = 1;
hw->clk_gate.mst_clk_sel = 1; hw->clk_gate.mst_clk_sel = 1;