Browse Source

soc: espressif: esp32c6: Add LP Core

Add ULP Coprocessor support for ESP32C6.

Signed-off-by: Lucas Tamborrino <lucas.tamborrino@espressif.com>
pull/87487/head
Lucas Tamborrino 6 months ago committed by Benjamin Cabé
parent
commit
0b9e4e013a
  1. 3
      drivers/clock_control/clock_control_esp32.c
  2. 6
      dts/riscv/espressif/esp32c6/esp32c6_common.dtsi
  3. 63
      dts/riscv/espressif/esp32c6/esp32c6_lpcore.dtsi
  4. 12
      dts/riscv/espressif/esp32c6/esp32c6_lpcore_wroom_n4.dtsi
  5. 103
      include/zephyr/dt-bindings/clock/esp32c6_clock.h
  6. 2
      soc/espressif/Kconfig
  7. 85
      soc/espressif/Kconfig.ulp
  8. 131
      soc/espressif/esp32c6/default_lpcore.ld
  9. 47
      soc/espressif/esp32c6/hpcore_init_ulp.c
  10. 35
      soc/espressif/esp32c6/memory.h
  11. 32
      soc/espressif/esp32c6/soc_lpcore.c
  12. 25
      soc/espressif/esp32c6/start_lpcore.S
  13. 22
      soc/espressif/esp32c6/vector_table_lpcore.S
  14. 142
      soc/espressif/esp32c6/vectors_lpcore.S

3
drivers/clock_control/clock_control_esp32.c

@ -105,7 +105,8 @@ static void esp32_clock_perip_init(void) @@ -105,7 +105,8 @@ static void esp32_clock_perip_init(void)
soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
if ((rst_reason != RESET_REASON_CPU0_MWDT0) && (rst_reason != RESET_REASON_CPU0_MWDT1) &&
(rst_reason != RESET_REASON_CPU0_SW) && (rst_reason != RESET_REASON_CPU0_RTC_WDT)) {
(rst_reason != RESET_REASON_CPU0_SW) && (rst_reason != RESET_REASON_CPU0_RTC_WDT) &&
(rst_reason != RESET_REASON_CPU0_JTAG)) {
periph_ll_disable_clk_set_rst(PERIPH_UART1_MODULE);
periph_ll_disable_clk_set_rst(PERIPH_I2C0_MODULE);

6
dts/riscv/espressif/esp32c6/esp32c6_common.dtsi

@ -76,9 +76,15 @@ @@ -76,9 +76,15 @@
};
sramlp: memory@50000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "zephyr,memory-region", "mmio-sram";
reg = <0x50000000 DT_SIZE_K(16)>;
zephyr,memory-region = "SRAMLP ";
shmlp: memory@0 {
reg = <0x0 0x10>;
};
};
intc: interrupt-controller@60010000 {

63
dts/riscv/espressif/esp32c6/esp32c6_lpcore.dtsi

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
/*
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <mem.h>
#include <freq.h>
#include <zephyr/dt-bindings/gpio/gpio.h>
#include <zephyr/dt-bindings/interrupt-controller/esp-esp32c6-intmux.h>
#include <zephyr/dt-bindings/clock/esp32c6_clock.h>
#include <dt-bindings/pinctrl/esp32c6-pinctrl.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu0: cpu@0 {
device_type = "cpu";
compatible = "espressif,riscv";
riscv,isa = "rv32imac_zicsr_zifencei";
reg = <0>;
clock-source = <ESP32_RTC_FAST_CLK_SRC_XTAL_D2>;
clock-frequency = <DT_FREQ_M(20)>;
xtal-freq = <DT_FREQ_M(40)>;
};
};
soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
sramlp: memory@50000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "mmio-sram";
reg = <0x50000000 DT_SIZE_K(16)>;
shmlp: memory@0 {
reg = <0x0 0x10>;
};
};
flash: flash-controller@60002000 {
compatible = "espressif,esp32-flash-controller";
reg = <0x60002000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
flash0: flash@0 {
compatible = "soc-nv-flash";
erase-block-size = <4096>;
write-block-size = <4>;
/* Flash size is specified in SOC/SIP dtsi */
};
};
};
};

12
dts/riscv/espressif/esp32c6/esp32c6_lpcore_wroom_n4.dtsi

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
/*
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp32c6_lpcore.dtsi"
/* 4MB flash */
&flash0 {
reg = <0x0 DT_SIZE_M(4)>;
};

103
include/zephyr/dt-bindings/clock/esp32c6_clock.h

@ -13,28 +13,28 @@ @@ -13,28 +13,28 @@
#define ESP32_CLK_SRC_RC_FAST 2U
/* Supported CPU frequencies */
#define ESP32_CLK_CPU_PLL_80M 80000000
#define ESP32_CLK_CPU_PLL_160M 160000000
#define ESP32_CLK_CPU_PLL_80M 80000000
#define ESP32_CLK_CPU_PLL_160M 160000000
#define ESP32_CLK_CPU_RC_FAST_FREQ 17500000
/* Supported XTAL Frequencies */
#define ESP32_CLK_XTAL_32M 32000000
#define ESP32_CLK_XTAL_40M 40000000
#define ESP32_CLK_XTAL_32M 32000000
#define ESP32_CLK_XTAL_40M 40000000
/* Supported RTC fast clock sources */
#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 0
#define ESP32_RTC_FAST_CLK_SRC_XTAL_D2 1
/* Supported RTC slow clock frequencies */
#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0
#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1
#define ESP32_RTC_SLOW_CLK_SRC_RC32K 2
#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9
#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0
#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1
#define ESP32_RTC_SLOW_CLK_SRC_RC32K 2
#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9
/* RTC slow clock frequencies */
#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 136000
#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768
#define ESP32_RTC_SLOW_CLK_SRC_RC32K_FREQ 32768
#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 136000
#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768
#define ESP32_RTC_SLOW_CLK_SRC_RC32K_FREQ 32768
/* Modules IDs
* These IDs are actually offsets in CLK and RST Control registers.
@ -44,44 +44,49 @@ @@ -44,44 +44,49 @@
* Basic Modules
* Registers: DPORT_PERIP_CLK_EN_REG, DPORT_PERIP_RST_EN_REG
*/
#define ESP32_LEDC_MODULE 0
#define ESP32_UART0_MODULE 1
#define ESP32_UART1_MODULE 2
#define ESP32_USB_MODULE 3
#define ESP32_I2C0_MODULE 4
#define ESP32_I2S1_MODULE 5
#define ESP32_TIMG0_MODULE 6
#define ESP32_TIMG1_MODULE 7
#define ESP32_UHCI0_MODULE 8
#define ESP32_RMT_MODULE 9
#define ESP32_PCNT_MODULE 10
#define ESP32_SPI_MODULE 11
#define ESP32_SPI2_MODULE 12
#define ESP32_TWAI0_MODULE 13
#define ESP32_TWAI1_MODULE 14
#define ESP32_RNG_MODULE 15
#define ESP32_RSA_MODULE 16
#define ESP32_AES_MODULE 17
#define ESP32_SHA_MODULE 18
#define ESP32_ECC_MODULE 19
#define ESP32_HMAC_MODULE 20
#define ESP32_DS_MODULE 21
#define ESP32_SDIO_SLAVE_MODULE 22
#define ESP32_GDMA_MODULE 23
#define ESP32_MCPWM0_MODULE 24
#define ESP32_ETM_MODULE 25
#define ESP32_PARLIO_MODULE 26
#define ESP32_SYSTIMER_MODULE 27
#define ESP32_SARADC_MODULE 28
#define ESP32_TEMPSENSOR_MODULE 29
#define ESP32_REGDMA_MODULE 30
#define ESP32_LP_I2C0_MODULE 31
#define ESP32_LEDC_MODULE 0
#define ESP32_UART0_MODULE 1
#define ESP32_UART1_MODULE 2
#define ESP32_USB_MODULE 3
#define ESP32_I2C0_MODULE 4
#define ESP32_I2S1_MODULE 5
#define ESP32_TIMG0_MODULE 6
#define ESP32_TIMG1_MODULE 7
#define ESP32_UHCI0_MODULE 8
#define ESP32_RMT_MODULE 9
#define ESP32_PCNT_MODULE 10
#define ESP32_SPI_MODULE 11
#define ESP32_SPI2_MODULE 12
#define ESP32_TWAI0_MODULE 13
#define ESP32_TWAI1_MODULE 14
#define ESP32_RNG_MODULE 15
#define ESP32_RSA_MODULE 16
#define ESP32_AES_MODULE 17
#define ESP32_SHA_MODULE 18
#define ESP32_ECC_MODULE 19
#define ESP32_HMAC_MODULE 20
#define ESP32_DS_MODULE 21
#define ESP32_SDIO_SLAVE_MODULE 22
#define ESP32_GDMA_MODULE 23
#define ESP32_MCPWM0_MODULE 24
#define ESP32_ETM_MODULE 25
#define ESP32_PARLIO_MODULE 26
#define ESP32_SYSTIMER_MODULE 27
#define ESP32_SARADC_MODULE 28
#define ESP32_TEMPSENSOR_MODULE 29
#define ESP32_ASSIST_DEBUG_MODULE 30
/* LP peripherals */
#define ESP32_LP_I2C0_MODULE 31
#define ESP32_LP_UART0_MODULE 32
/* Peripherals clock managed by the modem_clock driver must be listed last */
#define ESP32_WIFI_MODULE 32
#define ESP32_BT_MODULE 33
#define ESP32_IEEE802154_MODULE 34
#define ESP32_COEX_MODULE 35
#define ESP32_PHY_MODULE 36
#define ESP32_MODULE_MAX 37
#define ESP32_WIFI_MODULE 33
#define ESP32_BT_MODULE 34
#define ESP32_IEEE802154_MODULE 35
#define ESP32_COEX_MODULE 36
#define ESP32_PHY_MODULE 37
#define ESP32_ANA_I2C_MASTER_MODULE 38
#define ESP32_MODEM_ETM_MODULE 39
#define ESP32_MODEM_ADC_COMMON_FE_MODULE 40
#define ESP32_MODULE_MAX 41
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C6_H_ */

2
soc/espressif/Kconfig

@ -62,4 +62,6 @@ config RTC_CLK_CAL_CYCLES @@ -62,4 +62,6 @@ config RTC_CLK_CAL_CYCLES
If the crystal could not start, it will be switched to internal RC.
endmenu
rsource "Kconfig.ulp"
endif # SOC_FAMILY_ESPRESSIF_ESP32

85
soc/espressif/Kconfig.ulp

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
# Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
# SPDX-License-Identifier: Apache-2.0
menu "Ultra Low Power (ULP) Coprocessor"
config ULP_COPROC_ENABLED
bool "Ultra Low Power (ULP) Coprocessor"
help
Enable this feature if you plan to use the ULP Coprocessor.
Once this option is enabled, further ULP co-processor configuration will appear in the menu.
choice ULP_COPROC_TYPE
prompt "ULP Coprocessor type"
depends on ULP_COPROC_ENABLED
default ULP_COPROC_TYPE_LP_CORE if SOC_SERIES_ESP32C6
help
Choose the ULP Coprocessor type: ULP FSM (Finite State Machine) or ULP RISC-V.
config ULP_COPROC_TYPE_FSM
bool "ULP FSM (Finite State Machine)"
depends on SOC_SERIES_ESP32 || SOC_SERIES_ESP32S2 || SOC_SERIES_ESP32S3
config ULP_COPROC_TYPE_RISCV
bool "ULP RISC-V"
depends on SOC_SERIES_ESP32S2 || SOC_SERIES_ESP32S3
config ULP_COPROC_TYPE_LP_CORE
bool "LP core RISC-V"
depends on SOC_SERIES_ESP32C6
endchoice
menu "ULP RISC-V Settings"
depends on ULP_COPROC_TYPE_RISCV
config ULP_RISCV_INTERRUPT_ENABLE
bool "ULP RISC-V interrupts"
help
Turn on this setting to enabled interrupts on the ULP RISC-V core.
endmenu
menu "ULP Debugging Options"
config ULP_PANIC_OUTPUT_ENABLE
bool "Panic handler outputs to LP UART"
depends on ULP_COPROC_TYPE_LP_CORE
help
Set this option to enable panic handler functionality. If this option is
enabled then the LP Core will output a panic dump over LP UART,
similar to what the main core does. Output depends on LP UART already being
initialized and configured.
Disabling this option will reduce the LP core binary size by not
linking in panic handler functionality.
config ULP_HP_UART_CONSOLE_PRINT
bool "Route lp_core_printf to the console HP-UART"
depends on ULP_COPROC_TYPE_LP_CORE
help
Set this option to route lp_core_printf to the console HP-UART.
This allows you to easily view print outputs from the LP core, without
having to connect to the LP-UART. This option comes with the following
limitations:
1. There is no mutual exclusion between the HP-Core and the LP-Core accessing
the HP-UART, which means that if both cores are logging heavily the output
strings might get mangled together.
2. The HP-UART can only work while the HP-Core is running, which means that
if the HP-Core is in deep sleep, the LP-Core will not be able to print to the
console HP-UART.
Due to these limitations it is only recommended to use this option for easy debugging.
For more serious use-cases you should use the LP-UART.
config ULP_NORESET_UNDER_DEBUG
bool "Avoid resetting LP core when debugger is attached"
depends on ULP_COPROC_TYPE_LP_CORE
default y
help
Enable this feature to avoid resetting LP core in sleep mode when debugger is attached,
otherwise configured HW breakpoints and dcsr.ebreak* bits will be missed.
This is a workaround until it will be fixed in HW.
endmenu
endmenu # Ultra Low Power (ULP) Coprocessor

131
soc/espressif/esp32c6/default_lpcore.ld

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
/*
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/devicetree.h>
#include <zephyr/linker/sections.h>
#include <zephyr/linker/linker-defs.h>
#include <zephyr/linker/linker-tool.h>
#include "memory.h"
#define ALIGN_DOWN(SIZE, AL) (SIZE & ~(AL - 1))
/* Ensure the end where the shared memory starts is aligned to 8 bytes
if updating this also update the same in ulp_lp_core_memory_shared.c
*/
#define ALIGNED_COPROC_MEM ALIGN_DOWN(ULP_COPROC_RESERVE_MEM, 0x8)
#define RODATA_REGION ram
#define RAMABLE_REGION ram
#define ROMABLE_REGION ram
/* User available memory segments */
_aligned_coproc_mem = ALIGNED_COPROC_MEM;
_vector_table_org = LPSRAM_IRAM_START;
_vector_table_len = 0x80;
_ram_org = _vector_table_org + _vector_table_len;
_ram_len = _aligned_coproc_mem - _vector_table_len - ULP_SHARED_MEM;
_shared_mem_org = _ram_org + _ram_len;
_shared_mem_len = ULP_SHARED_MEM;
ENTRY(reset_vector)
MEMORY
{
/*first 128byte for exception/interrupt vectors*/
vector_table(RX) : ORIGIN = _vector_table_org , LENGTH = _vector_table_len
ram(RWX) : ORIGIN = _ram_org, LENGTH = _ram_len
shared_mem_ram(RW) : ORIGIN = _shared_mem_org, LENGTH = _shared_mem_len
}
SECTIONS
{
.vector.text :
{
__mtvec_base = .;
KEEP (*(.init.vector .init.vector.*))
} > vector_table
. = ORIGIN(ram);
.text ALIGN(4):
{
*(.text.vectors) /* Default reset vector must link to offset 0x80 */
__text_region_start = ABSOLUTE(.);
*(.text)
*(.text*)
__text_region_end = ABSOLUTE(.);
} >ram
#include <zephyr/linker/rel-sections.ld>
.rodata ALIGN(4):
{
__rodata_region_start = ABSOLUTE(.);
*(.rodata .srodata)
*(.rodata* .srodata*)
__rodata_region_end = .;
} > ram
#include <zephyr/linker/common-rom/common-rom-kernel-devices.ld>
.rodata.end ALIGN(4):
{
_rodata_reserved_end = ABSOLUTE(.);
} > ram
.data ALIGN(4):
{
_image_ram_start = ABSOLUTE(.);
*(.data)
*(.data*)
*(.sdata)
*(.sdata*)
} > ram
#include <snippets-data-sections.ld>
#include <zephyr/linker/common-ram.ld>
#include <snippets-ram-sections.ld>
.data.end ALIGN(4):
{
_image_ram_end = ABSOLUTE(.);
} > ram
.data.noinit (NOLOAD):
{
. = ALIGN(4);
*(.noinit)
*(.noinit.*)
. = ALIGN(4);
} > ram
.bss ALIGN(4) :
{
*(.bss)
*(.bss*)
*(.sbss)
*(.sbss*)
PROVIDE(end = .);
_heap_sentry = .;
} >ram
#include <zephyr/linker/ram-end.ld>
__stack_top = ORIGIN(ram) + LENGTH(ram);
#include <zephyr/linker/debug-sections.ld>
SECTION_PROLOGUE(.riscv.attributes, 0,)
{
KEEP(*(.riscv.attributes))
KEEP(*(.gnu.attributes))
}
. = ORIGIN(shared_mem_ram);
.shared_mem (ALIGN(4)) :
{
KEEP(*(.shared_mem))
} > shared_mem_ram
}

47
soc/espressif/esp32c6/hpcore_init_ulp.c

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
/*
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include "bootloader_flash_priv.h"
#include <zephyr/storage/flash_map.h>
#include "ulp_lp_core.h"
#include "lp_core_uart.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL);
void IRAM_ATTR lp_core_image_init(void)
{
const uint32_t lpcore_img_off = FIXED_PARTITION_OFFSET(slot0_lpcore_partition);
const uint32_t lpcore_img_size = 0x4000;
int ret = 0;
LOG_INF("Getting LPU image at %p, size %d", (void *)lpcore_img_off, lpcore_img_size);
const uint8_t *data = (const uint8_t *)bootloader_mmap(lpcore_img_off, lpcore_img_size);
ret = ulp_lp_core_load_binary(data, lpcore_img_size);
if (ret) {
LOG_ERR("Failed to load LP core image: %d", ret);
}
LOG_INF("LP core image loaded");
/* Set LP core wakeup source as the HP CPU */
ulp_lp_core_cfg_t cfg = {
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU,
};
ret = ulp_lp_core_run(&cfg);
if (ret) {
LOG_ERR("Failed to start LP core: %d", ret);
}
}
void soc_late_init_hook(void)
{
lp_core_image_init();
}

35
soc/espressif/esp32c6/memory.h

@ -5,15 +5,18 @@ @@ -5,15 +5,18 @@
#pragma once
/* LP-SRAM (16kB) memory */
#define LPSRAM_IRAM_START DT_REG_ADDR(DT_NODELABEL(sramlp))
#define LPSRAM_SIZE DT_REG_SIZE(DT_NODELABEL(sramlp))
#define LPSRAM_IRAM_START DT_REG_ADDR(DT_NODELABEL(sramlp))
#define LPSRAM_SIZE DT_REG_SIZE(DT_NODELABEL(sramlp))
#define ULP_SHARED_MEM DT_REG_SIZE(DT_NODELABEL(shmlp))
#define ULP_COPROC_RESERVE_MEM (0x4000)
/* HP-SRAM (512kB) memory */
#define HPSRAM_START DT_REG_ADDR(DT_NODELABEL(sramhp))
#define HPSRAM_SIZE DT_REG_SIZE(DT_NODELABEL(sramhp))
#define HPSRAM_DRAM_START HPSRAM_START
#define HPSRAM_IRAM_START HPSRAM_START
#define HPSRAM_START DT_REG_ADDR(DT_NODELABEL(sramhp))
#define HPSRAM_SIZE DT_REG_SIZE(DT_NODELABEL(sramhp))
#define HPSRAM_DRAM_START HPSRAM_START
#define HPSRAM_IRAM_START HPSRAM_START
/* ICache size is fixed to 32KB on ESP32-C6 */
#define ICACHE_SIZE 0x8000
#define ICACHE_SIZE 0x8000
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
@ -27,13 +30,13 @@ @@ -27,13 +30,13 @@
* buffers area (0x4087c610).
*/
#define DRAM_BUFFERS_START 0x4086ad08
#define DRAM_BUFFERS_END 0x4087c610
#define DRAM_STACK_START DRAM_BUFFERS_END
#define DRAM_ROM_BSS_DATA_START 0x4087e610
#define DRAM_BUFFERS_START 0x4086ad08
#define DRAM_BUFFERS_END 0x4087c610
#define DRAM_STACK_START DRAM_BUFFERS_END
#define DRAM_ROM_BSS_DATA_START 0x4087e610
/* Set the limit for the application runtime dynamic allocations */
#define DRAM_RESERVED_START DRAM_BUFFERS_END
#define DRAM_RESERVED_START DRAM_BUFFERS_END
/* For safety margin between bootloader data section and startup stacks */
#define BOOTLOADER_STACK_OVERHEAD 0x0
@ -49,14 +52,14 @@ @@ -49,14 +52,14 @@
/* Start of the lower region is determined by region size and the end of the higher region */
#define BOOTLOADER_IRAM_LOADER_SEG_START (BOOTLOADER_USER_SRAM_END - BOOTLOADER_IRAM_LOADER_SEG_LEN)
#define BOOTLOADER_IRAM_SEG_START (BOOTLOADER_IRAM_LOADER_SEG_START - BOOTLOADER_IRAM_SEG_LEN)
#define BOOTLOADER_DRAM_SEG_START (BOOTLOADER_IRAM_SEG_START - BOOTLOADER_DRAM_SEG_LEN)
#define BOOTLOADER_IRAM_SEG_START (BOOTLOADER_IRAM_LOADER_SEG_START - BOOTLOADER_IRAM_SEG_LEN)
#define BOOTLOADER_DRAM_SEG_START (BOOTLOADER_IRAM_SEG_START - BOOTLOADER_DRAM_SEG_LEN)
/* Flash */
#ifdef CONFIG_FLASH_SIZE
#define FLASH_SIZE CONFIG_FLASH_SIZE
#define FLASH_SIZE CONFIG_FLASH_SIZE
#else
#define FLASH_SIZE 0x400000
#define FLASH_SIZE 0x400000
#endif
/* Cached memory */

32
soc/espressif/esp32c6/soc_lpcore.c

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc_caps.h"
#include "esp_rom_caps.h"
#include "rom/ets_sys.h"
#include "ulp_lp_core_utils.h"
#include "ulp_lp_core_lp_timer_shared.h"
#include "ulp_lp_core_memory_shared.h"
#include "ulp_lp_core_print.h"
#include <soc.h>
#include <kernel_internal.h>
extern void main(void);
/* Initialize lp core related system functions before calling user's main*/
void lp_core_startup(void)
{
#if CONFIG_ULP_HP_UART_CONSOLE_PRINT && ESP_ROM_HAS_LP_ROM
ets_install_putc1(lp_core_print_char);
#endif
ulp_lp_core_update_wakeup_cause();
/* Start Zephyr */
z_cstart();
CODE_UNREACHABLE;
}

25
soc/espressif/esp32c6/start_lpcore.S

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
.section .text.vectors
.global reset_vector
/* The reset vector, jumps to startup code */
reset_vector:
/* _vector_table: Only 256-byte aligned addresses are allowed */
la t0, _vector_table
csrw mtvec, t0
j __start
__start:
/* setup the stack pointer */
la sp, __stack_top
call lp_core_startup
loop:
j loop

22
soc/espressif/esp32c6/vector_table_lpcore.S

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
.section .init.vector,"ax"
.global _vector_table
.type _vector_table, @function
_vector_table:
.option push
.option norvc
.rept 30
j _panic_handler
.endr
j _interrupt_handler // All interrupts are routed to mtvec + 4*30, i.e. the 31st entry
j _panic_handler
.option pop
.size _vector_table, .-_vector_table

142
soc/espressif/esp32c6/vectors_lpcore.S

@ -0,0 +1,142 @@ @@ -0,0 +1,142 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "riscv/rvruntime-frames.h"
#include <soc/soc_caps.h>
.equ SAVE_REGS, 32
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
/* Macro which first allocates space on the stack to save general
* purpose registers, and then save them. GP register is excluded.
* The default size allocated on the stack is CONTEXT_SIZE, but it
* can be overridden. */
.macro save_general_regs cxt_size=CONTEXT_SIZE
addi sp, sp, -\cxt_size
sw ra, RV_STK_RA(sp)
sw tp, RV_STK_TP(sp)
sw t0, RV_STK_T0(sp)
sw t1, RV_STK_T1(sp)
sw t2, RV_STK_T2(sp)
sw s0, RV_STK_S0(sp)
sw s1, RV_STK_S1(sp)
sw a0, RV_STK_A0(sp)
sw a1, RV_STK_A1(sp)
sw a2, RV_STK_A2(sp)
sw a3, RV_STK_A3(sp)
sw a4, RV_STK_A4(sp)
sw a5, RV_STK_A5(sp)
sw a6, RV_STK_A6(sp)
sw a7, RV_STK_A7(sp)
sw s2, RV_STK_S2(sp)
sw s3, RV_STK_S3(sp)
sw s4, RV_STK_S4(sp)
sw s5, RV_STK_S5(sp)
sw s6, RV_STK_S6(sp)
sw s7, RV_STK_S7(sp)
sw s8, RV_STK_S8(sp)
sw s9, RV_STK_S9(sp)
sw s10, RV_STK_S10(sp)
sw s11, RV_STK_S11(sp)
sw t3, RV_STK_T3(sp)
sw t4, RV_STK_T4(sp)
sw t5, RV_STK_T5(sp)
sw t6, RV_STK_T6(sp)
.endm
.macro save_mepc
csrr t0, mepc
sw t0, RV_STK_MEPC(sp)
.endm
/* Restore the general purpose registers (excluding gp) from the context on
* the stack. The context is then deallocated. The default size is CONTEXT_SIZE
* but it can be overridden. */
.macro restore_general_regs cxt_size=CONTEXT_SIZE
lw ra, RV_STK_RA(sp)
lw tp, RV_STK_TP(sp)
lw t0, RV_STK_T0(sp)
lw t1, RV_STK_T1(sp)
lw t2, RV_STK_T2(sp)
lw s0, RV_STK_S0(sp)
lw s1, RV_STK_S1(sp)
lw a0, RV_STK_A0(sp)
lw a1, RV_STK_A1(sp)
lw a2, RV_STK_A2(sp)
lw a3, RV_STK_A3(sp)
lw a4, RV_STK_A4(sp)
lw a5, RV_STK_A5(sp)
lw a6, RV_STK_A6(sp)
lw a7, RV_STK_A7(sp)
lw s2, RV_STK_S2(sp)
lw s3, RV_STK_S3(sp)
lw s4, RV_STK_S4(sp)
lw s5, RV_STK_S5(sp)
lw s6, RV_STK_S6(sp)
lw s7, RV_STK_S7(sp)
lw s8, RV_STK_S8(sp)
lw s9, RV_STK_S9(sp)
lw s10, RV_STK_S10(sp)
lw s11, RV_STK_S11(sp)
lw t3, RV_STK_T3(sp)
lw t4, RV_STK_T4(sp)
lw t5, RV_STK_T5(sp)
lw t6, RV_STK_T6(sp)
addi sp,sp, \cxt_size
.endm
.macro restore_mepc
lw t0, RV_STK_MEPC(sp)
csrw mepc, t0
.endm
/* _panic_handler: handle all exception */
.section .text.handlers,"ax"
.global _panic_handler
.type _panic_handler, @function
_panic_handler:
save_general_regs RV_STK_FRMSZ
save_mepc
addi t0, sp, RV_STK_FRMSZ /* Restore sp with the value when trap happened */
/* Save CSRs */
sw t0, RV_STK_SP(sp)
csrr t0, mstatus
sw t0, RV_STK_MSTATUS(sp)
csrr t0, mcause
sw t0, RV_STK_MCAUSE(sp)
csrr t0, mtvec
sw t0, RV_STK_MTVEC(sp)
csrr t0, mhartid
sw t0, RV_STK_MHARTID(sp)
csrr t0, mtval
sw t0, RV_STK_MTVAL(sp)
csrr a1, mcause /* Exception cause */
mv a0, sp /* RvExcFrame *regs */
call ulp_lp_core_panic_handler
_end:
j _end /* loop forever */
/* _interrupt_handler: handle all interrupt */
.section .text.handlers,"ax"
.global _interrupt_handler
.type _interrupt_handler, @function
_interrupt_handler:
/* Save registers & mepc to stack */
save_general_regs
save_mepc
call ulp_lp_core_intr_handler
/* Restore registers & mepc from stack */
restore_mepc
restore_general_regs
/* Exit, this will also re-enable the interrupts */
mret
Loading…
Cancel
Save