mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
feat(ulp): support interrupts for C6/P4 LP core
Closes https://github.com/espressif/esp-idf/issues/13059
This commit is contained in:
8
examples/system/ulp/lp_core/interrupt/CMakeLists.txt
Normal file
8
examples/system/ulp/lp_core/interrupt/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
# For more information about build system see
|
||||
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(interrupts)
|
19
examples/system/ulp/lp_core/interrupt/README.md
Normal file
19
examples/system/ulp/lp_core/interrupt/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
| Supported Targets | ESP32-C6 | ESP32-P4 |
|
||||
| ----------------- | -------- | -------- |
|
||||
|
||||
# LP-Core example with interrupt triggered from HP-Core:
|
||||
|
||||
This example demonstrates how to program the ULP coprocessor to receive an interrupt triggered by the HP-Core
|
||||
|
||||
ULP program written in C can be found across `lp_core/main.c`. The build system compiles and links this program, converts it into binary format, and embeds it into the .rodata section of the ESP-IDF application.
|
||||
|
||||
At runtime, the application running inside the main CPU loads ULP program into the `RTC_SLOW_MEM` memory region using `ulp_lp_core_load_binary` function. The main code then configures the ULP and starts the coprocessor by using `ulp_lp_core_run`. Once the ULP program is started, it runs continuously, waiting for interrupts. The main program will periodically trigger interrupts on the LP-Core.
|
||||
|
||||
After triggering a certain amount of interrupts, the main core will read and print the number of interrupts received as reported by the LP-Core.
|
||||
|
||||
## Example output
|
||||
|
||||
```
|
||||
LP core loaded with firmware and running successfully
|
||||
Triggered 10 interrupts on the LP-Core, LP-Core received 10 interrupts
|
||||
```
|
25
examples/system/ulp/lp_core/interrupt/main/CMakeLists.txt
Normal file
25
examples/system/ulp/lp_core/interrupt/main/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
# Register the component
|
||||
idf_component_register(SRCS "lp_interrupts_main.c"
|
||||
INCLUDE_DIRS ""
|
||||
REQUIRES ulp)
|
||||
|
||||
#
|
||||
# ULP support additions to component CMakeLists.txt.
|
||||
#
|
||||
# 1. The LP Core app name must be unique (if multiple components use LP Core).
|
||||
set(ulp_app_name lp_core_${COMPONENT_NAME})
|
||||
#
|
||||
# 2. Specify all C files.
|
||||
# Files should be placed into a separate directory (in this case, lp_core/),
|
||||
# which should not be added to COMPONENT_SRCS.
|
||||
set(ulp_lp_core_sources "lp_core/main.c")
|
||||
|
||||
#
|
||||
# 3. List all the component source files which include automatically
|
||||
# generated LP Core export file, ${ulp_app_name}.h:
|
||||
set(ulp_exp_dep_srcs "lp_interrupts_main.c")
|
||||
|
||||
#
|
||||
# 4. Call function to build ULP binary and embed in project using the argument
|
||||
# values above.
|
||||
ulp_embed_binary(${ulp_app_name} "${ulp_lp_core_sources}" "${ulp_exp_dep_srcs}")
|
30
examples/system/ulp/lp_core/interrupt/main/lp_core/main.c
Normal file
30
examples/system/ulp/lp_core/interrupt/main/lp_core/main.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ulp_lp_core_utils.h"
|
||||
#include "ulp_lp_core_interrupts.h"
|
||||
|
||||
uint32_t lp_core_pmu_intr_count = 0;
|
||||
|
||||
/* Add LP_CORE_ISR_ATTR to ensure registers are saved and restored */
|
||||
void LP_CORE_ISR_ATTR ulp_lp_core_lp_pmu_intr_handler(void)
|
||||
{
|
||||
ulp_lp_core_sw_intr_clear();
|
||||
lp_core_pmu_intr_count++;
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ulp_lp_core_intr_enable();
|
||||
ulp_lp_core_sw_intr_enable(true);
|
||||
|
||||
while(1) {
|
||||
/* Wait forever, handling interrupts */
|
||||
asm volatile("wfi");
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_err.h"
|
||||
#include "lp_core_main.h"
|
||||
#include "ulp_lp_core.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_main_bin_start");
|
||||
extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_main_bin_end");
|
||||
|
||||
|
||||
static void lp_core_init(void)
|
||||
{
|
||||
/* Set LP core wakeup source as the HP CPU */
|
||||
ulp_lp_core_cfg_t cfg = {
|
||||
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU,
|
||||
};
|
||||
|
||||
/* Load LP core firmware */
|
||||
ESP_ERROR_CHECK(ulp_lp_core_load_binary(lp_core_main_bin_start, (lp_core_main_bin_end - lp_core_main_bin_start)));
|
||||
|
||||
/* Run LP core */
|
||||
ESP_ERROR_CHECK(ulp_lp_core_run(&cfg));
|
||||
|
||||
// Give the LP core time to start up
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
printf("LP core loaded with firmware and running successfully\n");
|
||||
}
|
||||
|
||||
#define INTERRUPT_COUNT 10
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* Load LP Core binary and start the coprocessor */
|
||||
lp_core_init();
|
||||
|
||||
for (int i = 0; i < INTERRUPT_COUNT; i++) {
|
||||
/* In addition to waking the LP source up, the HP-LP communication bit can also be used to trigger a PMU interrupt on the LP Core */
|
||||
ulp_lp_core_sw_intr_trigger();
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
|
||||
printf("Triggered %d interrupts on the LP-Core, LP-Core received %"PRIu32" interrupts\n", INTERRUPT_COUNT, ulp_lp_core_pmu_intr_count);
|
||||
|
||||
}
|
11
examples/system/ulp/lp_core/interrupt/pytest_lp_core_intr.py
Normal file
11
examples/system/ulp/lp_core/interrupt/pytest_lp_core_intr.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32p4
|
||||
@pytest.mark.generic
|
||||
def test_lp_core_intr(dut: Dut) -> None:
|
||||
dut.expect('Triggered 10 interrupts on the LP-Core, LP-Core received 10 interrupts')
|
4
examples/system/ulp/lp_core/interrupt/sdkconfig.defaults
Normal file
4
examples/system/ulp/lp_core/interrupt/sdkconfig.defaults
Normal file
@@ -0,0 +1,4 @@
|
||||
# Enable ULP
|
||||
CONFIG_ULP_COPROC_ENABLED=y
|
||||
CONFIG_ULP_COPROC_TYPE_LP_CORE=y
|
||||
CONFIG_ULP_COPROC_RESERVE_MEM=4096
|
Reference in New Issue
Block a user