mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-28 16:46:31 +03:00
Merge branch 'feature/s31_lp_mailbox' into 'master'
feat(ulp): enable LP mailbox on S31 Closes IDF-14637 See merge request espressif/esp-idf!48218
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -22,6 +22,26 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable the mailbox peripheral clock.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void lp_mailbox_ll_enable_clock(lp_mb_dev_t *dev)
|
||||
{
|
||||
dev->reg_clk_en.reg_clk_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the mailbox peripheral registers.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void lp_mailbox_ll_reset_register(lp_mb_dev_t *dev)
|
||||
{
|
||||
(void) dev;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a message (32-bit value) from the LP mailbox.
|
||||
|
||||
213
components/hal/esp32s31/include/hal/lp_mailbox_ll.h
Normal file
213
components/hal/esp32s31/include/hal/lp_mailbox_ll.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for ESP32-S31 LP Mailbox register operations
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/lp_mailbox_struct.h"
|
||||
#include "soc/lp_mailbox_reg.h"
|
||||
#include "soc/lp_peri_clkrst_struct.h"
|
||||
#include "hal/misc.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#define LP_MAILBOX_LL_MSG_COUNT 16U
|
||||
|
||||
typedef mb_dev_t lp_mb_dev_t;
|
||||
extern lp_mb_dev_t LP_MAILBOX;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable the mailbox peripheral clock.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void lp_mailbox_ll_enable_clock(lp_mb_dev_t *dev)
|
||||
{
|
||||
LP_PERI_CLKRST.mailbox.lp_mailbox_clk_en = 1;
|
||||
dev->reg_clk_en.reg_clk_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the mailbox peripheral registers.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void lp_mailbox_ll_reset_register(lp_mb_dev_t *dev)
|
||||
{
|
||||
LP_PERI_CLKRST.mailbox.lp_mailbox_rst_en = 1;
|
||||
LP_PERI_CLKRST.mailbox.lp_mailbox_rst_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a message (32-bit value) from the LP mailbox.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
* @param index Index of the message to retrieve (must be less than LP_MAILBOX_LL_MSG_COUNT).
|
||||
*
|
||||
* @return The 32-bit message value at the specified index, or 0 if the index is out of range.
|
||||
*/
|
||||
FORCE_INLINE_ATTR uint32_t lp_mailbox_ll_get_message(lp_mb_dev_t *dev, int index)
|
||||
{
|
||||
if (index < LP_MAILBOX_LL_MSG_COUNT) {
|
||||
return (&dev->massege_0.val)[index];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a message in the LP mailbox.
|
||||
*
|
||||
* @note Writing a message in the mailbox will set the corresponding message's intr_raw bit for
|
||||
* both the LP and HP registers, regardless of the writer!
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
* @param index Index of the message to set (must be less than LP_MAILBOX_LL_MSG_COUNT).
|
||||
* @param val Message (32-bit value) to write to the specified message index.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void lp_mailbox_ll_set_message(lp_mb_dev_t *dev, int index, uint32_t val)
|
||||
{
|
||||
if (index < LP_MAILBOX_LL_MSG_COUNT) {
|
||||
(&dev->massege_0.val)[index] = val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the raw status of the LP core interrupt register.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
*
|
||||
* @return Raw interrupt status value.
|
||||
*/
|
||||
FORCE_INLINE_ATTR uint32_t lp_mailbox_ll_get_lp_intr_raw(lp_mb_dev_t *dev)
|
||||
{
|
||||
return dev->lp_int_raw.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear LP core interrupt register bits.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
* @param mask Bitmask of interrupts to clear, bit `i` represents message `i`.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void lp_mailbox_ll_lp_intr_clear(lp_mb_dev_t *dev, uint32_t mask)
|
||||
{
|
||||
dev->lp_int_clr.val = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the LP core interrupt register status.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
*
|
||||
* @return Interrupt status value.
|
||||
*/
|
||||
FORCE_INLINE_ATTR uint32_t lp_mailbox_ll_lp_intr_status(lp_mb_dev_t *dev)
|
||||
{
|
||||
return dev->lp_int_st.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable mailbox interrupts by mask for the LP core.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
* @param mask Bitmask of interrupts to enable, bit `i` represents message `i`.
|
||||
*
|
||||
* @return Updated interrupt enable register value.
|
||||
*/
|
||||
FORCE_INLINE_ATTR uint32_t lp_mailbox_ll_lp_intr_enable_mask(lp_mb_dev_t *dev, uint32_t mask)
|
||||
{
|
||||
dev->lp_int_ena.val |= mask;
|
||||
return dev->lp_int_ena.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable LP core mailbox interrupts by mask.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
* @param mask Bitmask of interrupts to disable, bit `i` represents message `i`.
|
||||
*
|
||||
* @return Updated interrupt enable register value.
|
||||
*/
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t lp_mailbox_ll_lp_intr_disable_mask(lp_mb_dev_t *dev, uint32_t mask)
|
||||
{
|
||||
dev->lp_int_ena.val &= ~mask;
|
||||
return dev->lp_int_ena.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the raw status of the HP core interrupt register.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
*
|
||||
* @return Raw interrupt status value.
|
||||
*/
|
||||
FORCE_INLINE_ATTR uint32_t lp_mailbox_ll_get_hp_intr_raw(lp_mb_dev_t *dev)
|
||||
{
|
||||
return dev->hp_int_raw.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear HP core interrupt register bits.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
* @param mask Bitmask of interrupts to clear, bit `i` represents message `i`.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void lp_mailbox_ll_hp_intr_clear(lp_mb_dev_t *dev, uint32_t mask)
|
||||
{
|
||||
dev->hp_int_clr.val = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the HP core interrupt register status.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
*
|
||||
* @return Interrupt status value.
|
||||
*/
|
||||
FORCE_INLINE_ATTR uint32_t lp_mailbox_ll_hp_intr_status(lp_mb_dev_t *dev)
|
||||
{
|
||||
return dev->hp_int_st.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable mailbox interrupts by mask for the HP core.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
* @param mask Bitmask of interrupts to enable, bit `i` represents message `i`.
|
||||
*
|
||||
* @return Updated interrupt enable register value.
|
||||
*/
|
||||
FORCE_INLINE_ATTR uint32_t lp_mailbox_ll_hp_intr_enable_mask(lp_mb_dev_t *dev, uint32_t mask)
|
||||
{
|
||||
dev->hp_int_ena.val |= mask;
|
||||
return dev->hp_int_ena.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable HP core mailbox interrupts by mask.
|
||||
*
|
||||
* @param dev Pointer to the LP mailbox device structure.
|
||||
* @param mask Bitmask of interrupts to disable, bit `i` represents message `i`.
|
||||
*
|
||||
* @return Updated interrupt enable register value.
|
||||
*/
|
||||
FORCE_INLINE_ATTR uint32_t lp_mailbox_ll_hp_intr_disable_mask(lp_mb_dev_t *dev, uint32_t mask)
|
||||
{
|
||||
dev->hp_int_ena.val &= ~mask;
|
||||
return dev->hp_int_ena.val;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1187,6 +1187,10 @@ config SOC_PM_RETENTION_MODULE_NUM
|
||||
int
|
||||
default 64
|
||||
|
||||
config SOC_LP_MAILBOX_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_CORE_SUPPORT_ETM
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -473,7 +473,7 @@
|
||||
#define SOC_PM_RETENTION_MODULE_NUM (64)
|
||||
|
||||
/*-------------------------- LP_CORE CAPS ------------------------------------*/
|
||||
// #define SOC_LP_MAILBOX_SUPPORTED (1) // TODO: [ESP32S31] IDF-14637
|
||||
#define SOC_LP_MAILBOX_SUPPORTED (1) /*!< LP Core supports LP-mailbox */
|
||||
#define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM wakeup */
|
||||
#define SOC_LP_CORE_CONFIGURABLE_BOOT_ADDR (1) /*!< LP Core has no LP ROM; HP must write the reset_vector address (LP_RAM_BASE+0x80) to LP_SYS.lp_core_boot_addr before triggering LP wake */
|
||||
//#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */ TODO IDF-14635
|
||||
|
||||
@@ -158,6 +158,7 @@ esp_err_t lp_core_mailbox_init(lp_mailbox_t *mailbox, lp_mailbox_config_t *confi
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
hal_memset(&s_mailbox, 0, sizeof(s_mailbox));
|
||||
lp_core_mailbox_impl_init();
|
||||
s_mailbox.mb_ctx = lp_core_mailbox_impl_get_context();
|
||||
if (s_mailbox.mb_ctx == NULL) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
/* Implementation agnostic interrupt handler */
|
||||
static void (*s_intr_handler)(void);
|
||||
|
||||
void lp_core_mailbox_impl_init(void)
|
||||
{
|
||||
lp_mailbox_ll_enable_clock(&LP_MAILBOX);
|
||||
lp_mailbox_ll_reset_register(&LP_MAILBOX);
|
||||
}
|
||||
|
||||
void LP_CORE_ISR_ATTR ulp_lp_core_mailbox_intr_handler(void)
|
||||
{
|
||||
if (s_intr_handler) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -30,6 +30,14 @@ lp_core_mailbox_impl_sw_t g_lp_core_mailbox_impl_sw_ctx;
|
||||
/* Implementation agnostic interrupt handler */
|
||||
static void (*s_intr_handler)(void);
|
||||
|
||||
void lp_core_mailbox_impl_init(void)
|
||||
{
|
||||
/* This structure must be initialized by the LP core */
|
||||
memset(&g_lp_core_mailbox_impl_sw_ctx, 0, sizeof(g_lp_core_mailbox_impl_sw_ctx));
|
||||
ulp_lp_core_spinlock_init(&g_lp_core_mailbox_impl_sw_ctx.lock);
|
||||
ulp_lp_core_sw_intr_from_hp_enable(false);
|
||||
}
|
||||
|
||||
void LP_CORE_ISR_ATTR ulp_lp_core_sw_intr_handler(void)
|
||||
{
|
||||
if (s_intr_handler) {
|
||||
@@ -39,10 +47,6 @@ void LP_CORE_ISR_ATTR ulp_lp_core_sw_intr_handler(void)
|
||||
|
||||
lp_core_mailbox_ctx_t lp_core_mailbox_impl_get_context(void)
|
||||
{
|
||||
/* This structure must be initialized by the LP core */
|
||||
memset(&g_lp_core_mailbox_impl_sw_ctx, 0, sizeof(g_lp_core_mailbox_impl_sw_ctx));
|
||||
ulp_lp_core_spinlock_init(&g_lp_core_mailbox_impl_sw_ctx.lock);
|
||||
ulp_lp_core_sw_intr_from_hp_enable(false);
|
||||
return (lp_core_mailbox_ctx_t) &g_lp_core_mailbox_impl_sw_ctx;
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +162,7 @@ esp_err_t lp_core_mailbox_init(lp_mailbox_t *mailbox, lp_mailbox_config_t *confi
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
lp_core_mailbox_impl_init();
|
||||
lp_core_mailbox_ctx_t context = lp_core_mailbox_impl_get_context();
|
||||
if (context == NULL) {
|
||||
/* Invalid state! LP core didn't initialize the spinlock? (SW backend) */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -11,6 +11,11 @@
|
||||
#include "ulp_lp_core_mailbox_impl_shared.h"
|
||||
#include "hal/lp_mailbox_ll.h"
|
||||
|
||||
void lp_core_mailbox_impl_init(void)
|
||||
{
|
||||
lp_mailbox_ll_enable_clock(&LP_MAILBOX);
|
||||
}
|
||||
|
||||
/* Mailbox hardware controller, used as a context */
|
||||
lp_core_mailbox_ctx_t lp_core_mailbox_impl_get_context(void)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,10 @@ typedef struct {
|
||||
/* The structure above is defined by the ULP */
|
||||
extern lp_core_mailbox_impl_sw_t ulp_g_lp_core_mailbox_impl_sw_ctx;
|
||||
|
||||
void lp_core_mailbox_impl_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
lp_core_mailbox_ctx_t lp_core_mailbox_impl_get_context(void)
|
||||
{
|
||||
/* Make sure the LP core initialized the spinlock */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -31,6 +31,11 @@ typedef intptr_t lp_message_t;
|
||||
*/
|
||||
typedef void* lp_core_mailbox_ctx_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the mailbox implementation for the current target/core.
|
||||
*/
|
||||
void lp_core_mailbox_impl_init(void);
|
||||
|
||||
/**
|
||||
* @brief Get the mailbox context for the current implementation
|
||||
*/
|
||||
|
||||
@@ -23,5 +23,6 @@ INPUT += \
|
||||
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_uart.h \
|
||||
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h \
|
||||
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_interrupts.h \
|
||||
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_mailbox.h \
|
||||
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_spi.h \
|
||||
$(PROJECT_PATH)/components/ulp/ulp_common/include/ulp_common.h \
|
||||
|
||||
@@ -72,9 +72,7 @@ examples/system/ulp/lp_core/lp_i2c:
|
||||
|
||||
examples/system/ulp/lp_core/lp_mailbox:
|
||||
enable:
|
||||
- if: SOC_LP_CORE_SUPPORTED == 1 and IDF_TARGET not in ["esp32s31"]
|
||||
temporary: true
|
||||
reason: ESP32-S31 not supported yet # TODO: [ESP32S31] IDF-14637
|
||||
- if: SOC_LP_CORE_SUPPORTED == 1
|
||||
<<: *ulp_default_depends
|
||||
|
||||
examples/system/ulp/lp_core/lp_spi:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
|
||||
| ----------------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
|
||||
| ----------------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
# LP Mailbox Example
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@ from pytest_embedded_idf.utils import soc_filtered_targets
|
||||
|
||||
@pytest.mark.generic
|
||||
@idf_parametrize('target', soc_filtered_targets('SOC_LP_CORE_SUPPORTED == 1'), indirect=['target'])
|
||||
@pytest.mark.temp_skip_ci(
|
||||
targets=['esp32s31'], reason='s31 bringup on this module is not done, TODO: [ESP32S31] IDF-14637'
|
||||
)
|
||||
def test_lp_mailbox(dut: Dut) -> None:
|
||||
# Wait for LP core to be loaded and running
|
||||
dut.expect_exact('LP Mailbox initialized successfully')
|
||||
|
||||
Reference in New Issue
Block a user