soc: esp32c3: added initial soc support files for esp32c3

by adding the soc specific files such: soc initialization code,
linker scripts and support for esp32c3 devkitm

Signed-off-by: Felipe Neves <ryukokki.felipe@gmail.com>
Signed-off-by: Felipe Neves <felipe.neves@espressif.com>
This commit is contained in:
Felipe Neves 2021-04-12 19:39:04 -03:00 committed by Anas Nashif
parent 4303cfdb3c
commit 5d736766ed
23 changed files with 1056 additions and 11 deletions

View file

@ -0,0 +1,59 @@
# SPDX-License-Identifier: Apache-2.0
if(CONFIG_BOOTLOADER_ESP_IDF)
include(ExternalProject)
## we use hello-world project, but I think any can be used.
set(espidf_components_dir ${ESP_IDF_PATH}/components)
set(espidf_prefix ${CMAKE_BINARY_DIR}/esp-idf)
set(espidf_build_dir ${espidf_prefix}/build)
ExternalProject_Add(
EspIdfBootloader
PREFIX ${espidf_prefix}
SOURCE_DIR ${espidf_components_dir}/bootloader/subproject
BINARY_DIR ${espidf_build_dir}/bootloader
CONFIGURE_COMMAND
${CMAKE_COMMAND} -G${CMAKE_GENERATOR}
-S ${espidf_components_dir}/bootloader/subproject
-B ${espidf_build_dir}/bootloader -DSDKCONFIG=${espidf_build_dir}/sdkconfig
-DIDF_PATH=${ESP_IDF_PATH} -DIDF_TARGET=${CONFIG_SOC}
-DSDKCONFIG_DEFAULTS=${ESP_IDF_PATH}/zephyr/esp32c3/sdkconfig.defaults
-DPYTHON_DEPS_CHECKED=1
BUILD_COMMAND
${CMAKE_COMMAND} --build .
INSTALL_COMMAND "" # This particular build system has no install command
)
ExternalProject_Add(
EspPartitionTable
SOURCE_DIR ${espidf_components_dir}/partition_table
BINARY_DIR ${espidf_build_dir}
CONFIGURE_COMMAND ""
BUILD_COMMAND
python ${ESP_IDF_PATH}/components/partition_table/gen_esp32part.py -q
--offset 0x1000 --flash-size 4MB ${ESP_IDF_PATH}/components/partition_table/partitions_singleapp.csv ${espidf_build_dir}/partitions_singleapp.bin
INSTALL_COMMAND ""
)
if(CONFIG_BUILD_OUTPUT_BIN)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
COMMAND python ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py
ARGS --chip esp32c3 elf2image --flash_mode dio --flash_freq 40m
-o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin
${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf)
endif()
add_dependencies(app EspIdfBootloader EspPartitionTable)
board_finalize_runner_args(esp32 "--esp-flash-bootloader=${espidf_build_dir}/bootloader/bootloader.bin")
board_finalize_runner_args(esp32 "--esp-flash-partition_table=${espidf_build_dir}/partitions_singleapp.bin")
board_finalize_runner_args(esp32 "--esp-boot-address=0x0000")
board_finalize_runner_args(esp32 "--esp-partition-table-address=0x8000")
board_finalize_runner_args(esp32 "--esp-app-address=0x10000")
endif()

View file

@ -0,0 +1,9 @@
# ESP32C3 devkitm board configuration
# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
# SPDX-License-Identifier: Apache-2.0
config BOARD_ESP32C3_DEVKITM
bool "ESP32C3 Devkit-M Board"
depends on SOC_ESP32C3
select CONSOLE_HAS_DRIVER

View file

@ -0,0 +1,8 @@
# ESP32C3 devkitm board configuration
# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
# SPDX-License-Identifier: Apache-2.0
config BOARD
default "esp32c3"
depends on BOARD_ESP32C3_DEVKITM

View file

@ -0,0 +1,3 @@
# SPDX-License-Identifier: Apache-2.0
include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake)

View file

@ -0,0 +1,116 @@
.. _esp32c3_devkitm:
ESP32-C3
#####
Overview
********
ESP32-C3 is a single-core Wi-Fi and Bluetooth 5 (LE) microcontroller SoC,
based on the open-source RISC-V architecture. It strikes the right balance of power,
I/O capabilities and security, thus offering the optimal cost-effective
solution for connected devices.
The availability of Wi-Fi and Bluetooth 5 (LE) connectivity not only makes the device configuration easy,
but it also facilitates a variety of use-cases based on dual connectivity. [1]_
The features include the following:
- 32-bit core RISC-V microcontroller with a maximum clock speed of 160 MHz
- 400 KB of internal RAM
- 802.11b/g/n/e/i
- A Bluetooth LE subsystem that supports features of Bluetooth 5 and Bluetooth mesh
- Various peripherals:
- 12-bit ADC with up to 18 channels
- TWAI compatible with CAN bus 2.0
- Temperature sensor
- 4x SPI
- 2x I2S
- 2x I2C
- 3x UART
- LED PWM with up to 16 channels
- Cryptographic hardware acceleration (RNG, ECC, RSA, SHA-2, AES)
System requirements
*******************
Build Environment Setup
=======================
Retrieve required submodules to build this port. This might take a while for the first time:
.. code-block:: console
west espressif update
.. note::
It is recommended running the command above after :file:`west update` so that submodules also get updated.
Flashing
========
The usual ``flash`` target will work with the ``esp32c3_devkitm`` board
configuration. Here is an example for the :ref:`hello_world`
application.
.. zephyr-app-commands::
:zephyr-app: samples/hello_world
:board: esp32c3_devkitm
:goals: flash
Refer to :ref:`build_an_application` and :ref:`application_run` for
more details.
It's impossible to determine which serial port the ESP32 board is
connected to, as it uses a generic RS232-USB converter. The default of
``/dev/ttyUSB0`` is provided as that's often the assigned name on a Linux
machine without any other such converters.
The baud rate of 921600bps is recommended. If experiencing issues when
flashing, try halving the value a few times (460800, 230400, 115200,
etc). It might be necessary to change the flash frequency or the flash
mode; please refer to the `esptool documentation`_ for guidance on these
settings.
All flashing options are now handled by the :ref:`west` tool, including flashing
with custom options such as a different serial port. The ``west`` tool supports
specific options for the ESP32C3 board, as listed here:
--esp-idf-path ESP_IDF_PATH
path to ESP-IDF
--esp-device ESP_DEVICE
serial port to flash, default /dev/ttyUSB0
--esp-baud-rate ESP_BAUD_RATE
serial baud rate, default 921600
--esp-flash-size ESP_FLASH_SIZE
flash size, default "detect"
--esp-flash-freq ESP_FLASH_FREQ
flash frequency, default "40m"
--esp-flash-mode ESP_FLASH_MODE
flash mode, default "dio"
--esp-tool ESP_TOOL if given, complete path to espidf. default is to
search for it in [ESP_IDF_PATH]/components/esptool_py/
esptool/esptool.py
--esp-flash-bootloader ESP_FLASH_BOOTLOADER
Bootloader image to flash
--esp-flash-partition_table ESP_FLASH_PARTITION_TABLE
Partition table to flash
For example, to flash to ``/dev/ttyUSB2``, use the following command after
having build the application in the ``build`` directory:
.. code-block:: console
west flash -d build/ --skip-rebuild --esp-device /dev/ttyUSB2
References
**********
.. [1] https://www.espressif.com/en/products/socs/esp32-c3
.. _`ESP32C3 Technical Reference Manual`: https://espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf
.. _`ESP32C3 Datasheet`: https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
/dts-v1/;
#include <espressif/esp32c3.dtsi>
/ {
model = "esp32c3_devkitm";
compatible = "espressif,esp32c3";
chosen {
zephyr,sram = &sram0;
};
};

View file

@ -0,0 +1,6 @@
identifier: esp32c3
name: ESP32-C3
type: mcu
arch: riscv
toolchain:
- zephyr

View file

@ -0,0 +1,10 @@
# SPDX-License-Identifier: Apache-2.0
CONFIG_BOARD_ESP32C3_DEVKITM=y
CONFIG_SOC_ESP32C3=y
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=1000000
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000
CONFIG_CONSOLE=y
CONFIG_XIP=n

View file

@ -51,4 +51,10 @@ if(CONFIG_BOOTLOADER_ESP_IDF)
board_finalize_runner_args(esp32 "--esp-flash-partition_table=${espidf_build_dir}/partitions_singleapp.bin")
board_finalize_runner_args(esp32 "--esp-boot-address=0x1000")
board_finalize_runner_args(esp32 "--esp-partition-table-address=0x8000")
board_finalize_runner_args(esp32 "--esp-app-address=0x10000")
endif()

View file

@ -13,6 +13,7 @@ zephyr_sources_ifdef(CONFIG_RISCV_MACHINE_TIMER riscv_machine_timer.c)
zephyr_sources_ifdef(CONFIG_RV32M1_LPTMR_TIMER rv32m1_lptmr_timer.c)
zephyr_sources_ifdef(CONFIG_CORTEX_M_SYSTICK cortex_m_systick.c)
zephyr_sources_ifdef(CONFIG_XTENSA_TIMER xtensa_sys_timer.c)
zephyr_sources_ifdef(CONFIG_ESP32C3_SYS_TIMER esp32c3_sys_timer.c)
zephyr_sources_ifdef(CONFIG_NATIVE_POSIX_TIMER native_posix_timer.c)
zephyr_sources_ifdef(CONFIG_SAM0_RTC_TIMER sam0_rtc_timer.c)
zephyr_sources_ifdef(CONFIG_LITEX_TIMER litex_timer.c)

View file

@ -249,6 +249,14 @@ config XTENSA_TIMER
Enables a system timer driver for Xtensa based on the CCOUNT
and CCOMPARE special registers.
config ESP32C3_SYS_TIMER
bool "ESP32C3 sys-timer support"
depends on SOC_ESP32C3
default y
help
This option enables the system timer driver for the Espressif ESP32C3
and provides the standard "system clock driver" interface.
config XTENSA_TIMER_ID
int "System timer CCOMPAREn register index"
default 1

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <soc/soc_caps.h>
#include <soc/soc.h>
#include <soc/interrupt_core0_reg.h>
#include <soc/periph_defs.h>
#include <soc/system_reg.h>
#include <hal/systimer_hal.h>
#include <hal/systimer_ll.h>
#include <rom/ets_sys.h>
#include <esp_attr.h>
#include <drivers/timer/system_timer.h>
#include <sys_clock.h>
#include <soc.h>
#define SYS_TIMER_CPU_IRQ 1
static void sys_timer_isr(const void *arg)
{
ARG_UNUSED(arg);
systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0);
sys_clock_announce(1);
}
int sys_clock_driver_init(const struct device *dev)
{
ARG_UNUSED(dev);
esp32c3_rom_intr_matrix_set(0, ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE, SYS_TIMER_CPU_IRQ);
IRQ_CONNECT(SYS_TIMER_CPU_IRQ, 0, sys_timer_isr, NULL, 0);
irq_enable(SYS_TIMER_CPU_IRQ);
systimer_hal_init();
systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1);
systimer_hal_enable_counter(SYSTIMER_COUNTER_1);
systimer_hal_counter_can_stall_by_cpu(SYSTIMER_COUNTER_1, 0, true);
systimer_hal_set_alarm_period(SYSTIMER_ALARM_0,
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC);
systimer_hal_select_alarm_mode(SYSTIMER_ALARM_0, SYSTIMER_ALARM_MODE_PERIOD);
systimer_hal_enable_alarm_int(SYSTIMER_ALARM_0);
return 0;
}
void sys_clock_set_timeout(int32_t ticks, bool idle)
{
ARG_UNUSED(idle);
ARG_UNUSED(ticks);
}
uint32_t sys_clock_elapsed(void)
{
/* Tickless is not supported yet */
return 0;
}
uint32_t sys_clock_cycle_get_32(void)
{
return systimer_ll_get_counter_value_low(SYSTIMER_COUNTER_1);
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <mem.h>
/ {
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu0: cpu@0 {
device_type = "cpu";
compatible = "riscv";
reg = <0>;
};
};
soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
sram0: memory@3fc7c000 {
compatible = "espressif,esp32c3";
reg = <0x3fc7c000 0x50000>;
};
};
};

View file

@ -15,12 +15,16 @@ import sys
class Esp32BinaryRunner(ZephyrBinaryRunner):
'''Runner front-end for espidf.'''
def __init__(self, cfg, device, baud=921600, flash_size='detect',
def __init__(self, cfg, device, boot_address, part_table_address,
app_address, baud=921600, flash_size='detect',
flash_freq='40m', flash_mode='dio', espidf='espidf',
bootloader_bin=None, partition_table_bin=None):
super().__init__(cfg)
self.elf = cfg.elf_file
self.device = device
self.boot_address = boot_address
self.part_table_address = part_table_address
self.app_address = app_address
self.baud = baud
self.flash_size = flash_size
self.flash_freq = flash_freq
@ -42,8 +46,13 @@ class Esp32BinaryRunner(ZephyrBinaryRunner):
# Required
parser.add_argument('--esp-idf-path', required=True,
help='path to ESP-IDF')
# Optional
parser.add_argument('--esp-boot-address', default='0x1000',
help='bootloader load address')
parser.add_argument('--esp-partition-table-address', default='0x8000',
help='partition table load address')
parser.add_argument('--esp-app-address', default='0x10000',
help='application load address')
parser.add_argument('--esp-device', default='/dev/ttyUSB0',
help='serial port to flash, default /dev/ttyUSB0')
parser.add_argument('--esp-baud-rate', default='921600',
@ -72,7 +81,9 @@ class Esp32BinaryRunner(ZephyrBinaryRunner):
'esptool', 'esptool.py')
return Esp32BinaryRunner(
cfg, args.esp_device, baud=args.esp_baud_rate,
cfg, args.esp_device, boot_address=args.esp_boot_address,
part_table_address=args.esp_partition_table_address,
app_address=args.esp_app_address,baud=args.esp_baud_rate,
flash_size=args.esp_flash_size, flash_freq=args.esp_flash_freq,
flash_mode=args.esp_flash_mode, espidf=espidf,
bootloader_bin=args.esp_flash_bootloader,
@ -81,7 +92,7 @@ class Esp32BinaryRunner(ZephyrBinaryRunner):
def do_run(self, command, **kwargs):
self.require(self.espidf)
bin_name = path.splitext(self.elf)[0] + path.extsep + 'bin'
cmd_flash = [self.espidf, '--chip', 'esp32', '--port', self.device,
cmd_flash = [self.espidf, '--chip', 'auto', '--port', self.device,
'--baud', self.baud, '--before', 'default_reset',
'--after', 'hard_reset', 'write_flash', '-u',
'--flash_mode', self.flash_mode,
@ -92,13 +103,13 @@ class Esp32BinaryRunner(ZephyrBinaryRunner):
if self.espidf.lower().endswith(".py") and sys.executable:
cmd_flash.insert(0, sys.executable)
if self.bootloader_bin:
cmd_flash.extend(['0x1000', self.bootloader_bin])
cmd_flash.extend(['0x8000', self.partition_table_bin])
cmd_flash.extend(['0x10000', bin_name])
else:
cmd_flash.extend(['0x1000', bin_name])
if self.bootloader_bin :
cmd_flash.extend([self.boot_address, self.bootloader_bin])
cmd_flash.extend([self.part_table_address, self.partition_table_bin])
cmd_flash.extend([self.app_address, bin_name])
else :
cmd_flash.extend([self.boot_address, bin_name])
self.logger.info("Flashing ESP32 on {} ({}bps)".
self.logger.info("Flashing esp32 chip on {} ({}bps)".
format(self.device, self.baud))
self.check_call(cmd_flash)

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_sources(
idle.c
vectors.S
soc_irq.S
soc.c
)

View file

@ -0,0 +1,29 @@
# ESP32C3 board configuration
# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
# SPDX-License-Identifier: Apache-2.0
if SOC_ESP32C3
config SOC
default "esp32c3"
config NUM_IRQS
default 32
config GEN_ISR_TABLES
default y
config GEN_SW_ISR_TABLE
default y
config GEN_IRQ_VECTOR_TABLE
default n
config XIP
default n
config ISR_STACK_SIZE
default 2048
endif

View file

@ -0,0 +1,22 @@
# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
# SPDX-License-Identifier: Apache-2.0
config SOC_ESP32C3
bool "ESP32C3"
select RISCV
select RISCV_SOC_INIT_GP_VALUE
config IDF_TARGET_ESP32C3
bool "ESP32C3 as target board"
default y
depends on SOC_ESP32C3
config ESPTOOLPY_FLASHFREQ_80M
bool
default y
depends on SOC_ESP32C3
config BOOTLOADER_ESP_IDF
bool "Use esp-idf 2nd stage bootloader"
default y
depends on SOC_ESP32C3

30
soc/riscv/esp32c3/idle.c Normal file
View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <toolchain.h>
#include <irq.h>
#include <arch/cpu.h>
/**
*
* @brief Power save idle routine
*
* This function will be called by the kernel idle loop or possibly within
* an implementation of _pm_save_idle in the kernel when the
* '_pm_save_flag' variable is non-zero.
*
* @return N/A
*/
void arch_cpu_idle(void)
{
/* curiously it arives here with the interrupts masked
* so umask it before wait for an event
*/
arch_irq_unlock(MSTATUS_IEN);
/* Wait for interrupt */
__asm__ volatile("wfi");
}

322
soc/riscv/esp32c3/linker.ld Normal file
View file

@ -0,0 +1,322 @@
/*
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Linker command/script file
*
* Linker script for the esp32c3 platform.
*/
#include <devicetree.h>
#include <autoconf.h>
#include <linker/sections.h>
#include <linker/linker-defs.h>
#include <linker/linker-tool.h>
#define ROMABLE_REGION drom0_0_seg :drom0_0_phdr
#define RAMABLE_REGION dram0_0_seg :dram0_0_phdr
#define IRAM_REGION iram0_0_seg :iram0_0_phdr
#define FLASH_CODE_REGION irom0_0_seg :irom0_0_phdr
#define SRAM_IRAM_START 0x4037C000
#define SRAM_DRAM_START 0x3FC7C000
#define ICACHE_SIZE 0x4000 /* ICache size is fixed to 16KB on ESP32-C3 */
#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
#define SRAM_DRAM_END 0x403D0000 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
#define SRAM_IRAM_ORG (SRAM_IRAM_START + ICACHE_SIZE)
#define SRAM_DRAM_ORG (SRAM_DRAM_START + ICACHE_SIZE)
#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG
/* Global symbols required for espressif hal build */
MEMORY
{
iram0_0_seg(RX): org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE
irom0_0_seg(RX): org = 0x42000020, len = 0x8000000-0x20
drom0_0_seg (R) : org = 0x3C000020, len = 0x8000000-0x20
dram0_0_seg(RW): org = SRAM_DRAM_ORG, len = I_D_SRAM_SIZE
rtc_iram_seg(RWX): org = 0x50000000, len = 0x2000
#ifdef CONFIG_GEN_ISR_TABLES
IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000
#endif
}
PHDRS
{
drom0_0_phdr PT_LOAD;
dram0_0_phdr PT_LOAD;
iram0_0_phdr PT_LOAD;
irom0_0_phdr PT_LOAD;
}
/* Default entry point: */
ENTRY(__start)
_rom_store_table = 0;
SECTIONS
{
#include <linker/rel-sections.ld>
.rtc.text :
{
. = ALIGN(4);
*(.rtc.literal .rtc.text)
*rtc_wake_stub*.o(.literal .text .literal.* .text.*)
} > rtc_iram_seg
/* This section is required to skip rtc.text area because the text and
* data segments reflect the same address space on different buses.
*/
.rtc.dummy (NOLOAD):
{
. = SIZEOF(.rtc.text);
} > rtc_iram_seg
.rtc.data :
{
_rtc_data_start = ABSOLUTE(.);
*(.rtc.data)
*(.rtc.rodata)
*rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_iram_seg
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.o(.bss .bss.*)
*rtc_wake_stub*.o(COMMON)
_rtc_bss_end = ABSOLUTE(.);
} > rtc_iram_seg
.iram0.text : ALIGN(4)
{
/* Vectors go to IRAM */
_iram_start = ABSOLUTE(.);
_iram_text_start = ABSOLUTE(.);
_init_start = ABSOLUTE(.);
KEEP(*(.exception_vectors.text));
. = ALIGN(256);
KEEP(*(.exception.entry*)); /* contains __irq_wrapper */
*(.exception.other*)
. = ALIGN(4);
. = ALIGN (4);
*(.entry.text)
*(.init.literal)
*(.init)
. = ALIGN(4);
*(.iram1 .iram1.*)
*(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text)
*libkernel.a:(.literal .text .literal.* .text.*)
*libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*)
*libzephyr.a:log_noos.*(.literal .text .literal.* .text.*)
*libzephyr.a:esp32c3_sys_timer.*(.literal .text .literal.* .text.*)
*libzephyr.a:log_core.*(.literal .text .literal.* .text.*)
*libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*)
*libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out)
*libzephyr.a:log_msg.*(.literal .text .literal.* .text.*)
*libzephyr.a:log_list.*(.literal .text .literal.* .text.*)
*libzephyr.a:uart_console.*(.literal.console_out .text.console_out)
*libzephyr.a:log_output.*(.literal .text .literal.* .text.*)
*libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*)
*liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*)
*libgcov.a:(.literal .text .literal.* .text.*)
. = ALIGN(4);
_init_end = ABSOLUTE(.);
_iram_text_end = ABSOLUTE(.); *(.srodata)
_iram_end = ABSOLUTE(.);
} GROUP_LINK_IN(IRAM_REGION)
/**
* This section is required to skip .iram0.text area because iram0_0_seg and
* dram0_0_seg reflect the same address space on different buses.
*/
.dram0.dummy (NOLOAD):
{
. = ORIGIN(dram0_0_seg) + _iram_end - _iram_start;
} > dram0_0_seg
#include <linker/common-ram.ld>
.dram0.data :
{
_data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
__global_pointer$ = . + 0x800;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
*libkernel.a:fatal.*(.rodata .rodata.*)
*libkernel.a:init.*(.rodata .rodata.*)
*libzephyr.a:cbprintf_complete*(.rodata .rodata.*)
*libzephyr.a:log_core.*(.rodata .rodata.*)
*libzephyr.a:log_backend_uart.*(.rodata .rodata.*)
*libzephyr.a:log_output.*(.rodata .rodata.*)
. = ALIGN(4);
__esp_log_const_start = .;
KEEP(*(SORT(.log_const_*)));
__esp_log_const_end = .;
. = ALIGN(4);
__esp_log_backends_start = .;
KEEP(*("._log_backend.*"));
__esp_log_backends_end = .;
KEEP(*(.jcr))
*(.dram1 .dram1.*)
_data_end = ABSOLUTE(.);
. = ALIGN(4);
} GROUP_LINK_IN(RAMABLE_REGION)
/* Shared RAM */
dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.share.mem)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} GROUP_LINK_IN(RAMABLE_REGION)
SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),)
{
. = ALIGN (8);
*(.noinit)
*(".noinit.*")
. = ALIGN (8);
_heap_start = ABSOLUTE(.);
} GROUP_LINK_IN(RAMABLE_REGION)
.flash.text : ALIGN(4)
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.*)
_text_end = ABSOLUTE(.);
_etext = .;
_flash_cache_start = ABSOLUTE(0);
} GROUP_LINK_IN(FLASH_CODE_REGION)
.flash_rodata_dummy (NOLOAD):
{
. = SIZEOF(.flash.text);
. = ALIGN(0x10000) + 0x20;
_rodata_reserved_start = .;
} GROUP_LINK_IN(ROMABLE_REGION)
.flash.rodata : ALIGN(0x10)
{
_rodata_start = ABSOLUTE(.);
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table .gcc_except_table.*)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
. = (. + 3) & ~ 3;
__eh_frame = ABSOLUTE(.);
KEEP(*(.eh_frame))
. = (. + 7) & ~ 3;
/*
* C++ constructor and destructor tables
* Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt.
*
* RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead.
* But the init_priority sections will be sorted for iteration in ascending order during startup.
* The rest of the init_array sections is sorted for iteration in descending order during startup, however.
* Hence a different section is generated for the init_priority functions which is iterated in
* ascending order during startup. The corresponding code can be found in startup.c.
*/
__init_priority_array_start = ABSOLUTE(.);
KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*))
__init_priority_array_end = ABSOLUTE(.);
__init_array_start = ABSOLUTE(.);
KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
/* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */
soc_reserved_memory_region_start = ABSOLUTE(.);
KEEP (*(.reserved_memory_address))
soc_reserved_memory_region_end = ABSOLUTE(.);
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_thread_local_start = ABSOLUTE(.);
*(.tdata)
*(.tdata.*)
*(.tbss)
*(.tbss.*)
*(.srodata)
*(".srodata.*")
*(.rodata)
*(.rodata.*)
_thread_local_end = ABSOLUTE(.);
_rodata_reserved_end = ABSOLUTE(.);
. = ALIGN(4);
} GROUP_LINK_IN(ROMABLE_REGION)
#include <linker/common-rom.ld>
#ifdef CONFIG_GEN_ISR_TABLES
#include <linker/intlist.ld>
#endif
#include <linker/debug-sections.ld>
/DISCARD/ : { *(.note.GNU-stack) }
SECTION_PROLOGUE(.riscv.attributes, 0,)
{
KEEP(*(.riscv.attributes))
KEEP(*(.gnu.attributes))
}
}

183
soc/riscv/esp32c3/soc.c Normal file
View file

@ -0,0 +1,183 @@
/*
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Include esp-idf headers first to avoid redefining BIT() macro */
#include <soc/rtc_cntl_reg.h>
#include <soc/timer_group_reg.h>
#include <soc/gpio_reg.h>
#include <soc/syscon_reg.h>
#include <soc/system_reg.h>
#include <soc/cache_memory.h>
#include "hal/soc_ll.h"
#include "esp_spi_flash.h"
#include <riscv/interrupt.h>
#include <kernel_structs.h>
#include <string.h>
#include <toolchain/gcc.h>
#include <soc.h>
#define ESP32C3_INTC_DEFAULT_PRIO 15
extern void z_cstart(void);
extern void esprv_intc_int_set_threshold(int priority_threshold);
/*
* This is written in C rather than assembly since, during the port bring up,
* Zephyr is being booted by the Espressif bootloader. With it, the C stack
* is already set up.
*/
void __attribute__((section(".iram1"))) __start(void)
{
volatile uint32_t *wdt_rtc_protect = (uint32_t *)RTC_CNTL_WDTWPROTECT_REG;
volatile uint32_t *wdt_rtc_reg = (uint32_t *)RTC_CNTL_WDTCONFIG0_REG;
extern uint32_t _bss_start;
extern uint32_t _bss_end;
/* Configure the global pointer register
* (This should be the first thing startup does, as any other piece of code could be
* relaxed by the linker to access something relative to __global_pointer$)
*/
__asm__ __volatile__(".option push\n"
".option norelax\n"
"la gp, __global_pointer$\n"
".option pop");
__asm__ __volatile__("la t0, _esp32c3_vector_table \n"
"csrw mtvec, t0 \n");
/* Disable normal interrupts. */
csr_read_clear(mstatus, MSTATUS_MIE);
/* Zero out BSS. Clobber _bss_start to avoid memset() elision. */
(void)memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
__asm__ __volatile__("" : : "g"(&_bss_start) : "memory");
#if !CONFIG_BOOTLOADER_ESP_IDF
/* The watchdog timer is enabled in the 1st stage (ROM) bootloader.
* We're done booting, so disable it.
* If 2nd stage bootloader from IDF is enabled, then that will take
* care of this.
*/
volatile uint32_t *wdt_timg_protect = (uint32_t *)TIMG_WDTWPROTECT_REG(0);
volatile uint32_t *wdt_timg_reg = (uint32_t *)TIMG_WDTCONFIG0_REG(0);
*wdt_rtc_protect = RTC_CNTL_WDT_WKEY_VALUE;
*wdt_rtc_reg &= ~RTC_CNTL_WDT_FLASHBOOT_MOD_EN;
*wdt_rtc_protect = 0;
*wdt_timg_protect = TIMG_WDT_WKEY_VALUE;
*wdt_timg_reg &= ~TIMG_WDT_FLASHBOOT_MOD_EN;
*wdt_timg_protect = 0;
#endif
#if CONFIG_BOOTLOADER_ESP_IDF
/* ESP-IDF 2nd stage bootloader enables RTC WDT to check on startup sequence
* related issues in application. Hence disable that as we are about to start
* Zephyr environment.
*/
*wdt_rtc_protect = RTC_CNTL_WDT_WKEY_VALUE;
*wdt_rtc_reg &= ~RTC_CNTL_WDT_EN;
*wdt_rtc_protect = 0;
#endif
/* Configure the Cache MMU size for instruction and rodata in flash. */
extern uint32_t esp32c3_rom_cache_set_idrom_mmu_size(uint32_t irom_size, uint32_t drom_size);
extern int _rodata_reserved_start;
uint32_t rodata_reserved_start_align =
(uint32_t)&_rodata_reserved_start & ~(MMU_PAGE_SIZE - 1);
uint32_t cache_mmu_irom_size =
((rodata_reserved_start_align - SOC_DROM_LOW) / MMU_PAGE_SIZE) * sizeof(uint32_t);
esp32c3_rom_cache_set_idrom_mmu_size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
/* set global esp32c3's INTC masking level */
esprv_intc_int_set_threshold(1);
/* Start Zephyr */
z_cstart();
CODE_UNREACHABLE;
}
/* Boot-time static default printk handler, possibly to be overridden later. */
int IRAM_ATTR arch_printk_char_out(int c)
{
if (c == '\n') {
esp32c3_rom_uart_tx_one_char('\r');
}
esp32c3_rom_uart_tx_one_char(c);
return 0;
}
void IRAM_ATTR esp_restart_noos(void)
{
/* Disable interrupts */
csr_read_clear(mstatus, MSTATUS_MIE);
/* Flush any data left in UART FIFOs */
esp32c3_rom_uart_tx_wait_idle(0);
esp32c3_rom_uart_tx_wait_idle(1);
esp32c3_rom_uart_tx_wait_idle(2);
/* 2nd stage bootloader reconfigures SPI flash signals. */
/* Reset them to the defaults expected by ROM */
WRITE_PERI_REG(GPIO_FUNC0_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC1_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC2_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC3_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC4_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC5_IN_SEL_CFG_REG, 0x30);
/* Reset wifi/bluetooth/ethernet/sdio (bb/mac) */
SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG,
SYSTEM_BB_RST | SYSTEM_FE_RST | SYSTEM_MAC_RST | SYSTEM_BT_RST |
SYSTEM_BTMAC_RST | SYSTEM_SDIO_RST | SYSTEM_EMAC_RST |
SYSTEM_MACPWR_RST | SYSTEM_RW_BTMAC_RST | SYSTEM_RW_BTLP_RST |
BLE_REG_REST_BIT | BLE_PWR_REG_REST_BIT | BLE_BB_REG_REST_BIT);
REG_WRITE(SYSTEM_CORE_RST_EN_REG, 0);
/* Reset timer/spi/uart */
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG,
SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST);
REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0);
/* Reset dma */
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0);
/* Reset core */
soc_ll_reset_core(0);
while (true) {
;
}
}
void sys_arch_reboot(int type)
{
esp_restart_noos();
}
void arch_irq_enable(unsigned int irq)
{
uint32_t key = irq_lock();
esprv_intc_int_set_priority(irq, ESP32C3_INTC_DEFAULT_PRIO);
esprv_intc_int_set_type(irq, 0);
esprv_intc_int_enable(1 << irq);
irq_unlock(key);
}
void arch_irq_disable(unsigned int irq)
{
esprv_intc_int_disable(1 << irq);
}
int arch_irq_is_enabled(unsigned int irq)
{
return (esprv_intc_get_interrupt_unmask() & (1 << irq));
}

46
soc/riscv/esp32c3/soc.h Normal file
View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __SOC_H__
#define __SOC_H__
#ifndef _ASMLANGUAGE
#include <rom/ets_sys.h>
#include <rom/spi_flash.h>
#include <zephyr/types.h>
#include <stdbool.h>
#endif
#include <arch/riscv/arch.h>
/* IRQ numbers */
#define RISCV_MACHINE_SOFT_IRQ 3 /* Machine Software Interrupt */
#define RISCV_MACHINE_TIMER_IRQ 7 /* Machine Timer Interrupt */
#define RISCV_MACHINE_EXT_IRQ 11 /* Machine External Interrupt */
/* ECALL Exception numbers */
#define SOC_MCAUSE_ECALL_EXP 11 /* Machine ECALL instruction */
#define SOC_MCAUSE_USER_ECALL_EXP 8 /* User ECALL instruction */
/* Interrupt Mask */
#define SOC_MCAUSE_IRQ_MASK (1 << 31)
/* Exception code Mask */
#define SOC_MCAUSE_EXP_MASK 0x7FFFFFFF
/* SOC-Specific EXIT ISR command */
#define SOC_ERET mret
#ifndef _ASMLANGUAGE
extern void esp32c3_rom_intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num);
extern void esp32c3_rom_uart_attach(void);
extern void esp32c3_rom_uart_tx_wait_idle(uint8_t uart_no);
extern STATUS esp32c3_rom_uart_tx_one_char(uint8_t chr);
extern STATUS esp32c3_rom_uart_rx_one_char(uint8_t *chr);
extern void esp32c3_rom_ets_set_user_start(uint32_t start);
#endif /* _ASMLANGUAGE */
#endif /* __SOC_H__ */

View file

@ -0,0 +1,19 @@
/* Copyright 2021 Espressif Systems (Shanghai) PTE LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <offsets.h>
#include <toolchain.h>
/* Exports */
GTEXT(__soc_is_irq)
GTEXT(__soc_handle_irq)
SECTION_FUNC(exception.other, __soc_is_irq)
csrr a0, mcause
srli a0, a0, 31
ret
SECTION_FUNC(exception.other, __soc_handle_irq)
ret

View file

@ -0,0 +1,35 @@
/* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc.h"
#include "soc/interrupt_reg.h"
#include "riscv/rvruntime-frames.h"
#include "soc/soc_caps.h"
#include <toolchain.h>
/* Imports */
GTEXT(__irq_wrapper)
/* This is the vector table. MTVEC points here.
*
* Use 4-byte intructions here. 1 instruction = 1 entry of the table.
* The CPU jumps to MTVEC (i.e. the first entry) in case of an exception,
* and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt.
*
* Note: for our CPU, we need to place this on a 256-byte boundary, as CPU
* only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00).
*/
.global _esp32c3_vector_table
.section .exception_vectors.text
.balign 0x100
.type _esp32c3_vector_table, @function
_esp32c3_vector_table:
.option push
.option norvc
.rept (32)
j __irq_wrapper /* 32 identical entries, all pointing to the interrupt handler */
.endr