mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/merge_esp32c3_bootloader_support' into 'master'
esp32c3: add initial bootloader and target component support Closes IDF-2435 and IDF-2436 See merge request espressif/esp-idf!11433
This commit is contained in:
commit
f50dd23872
182
components/bootloader/subproject/main/ld/esp32c3/bootloader.ld
Normal file
182
components/bootloader/subproject/main/ld/esp32c3/bootloader.ld
Normal file
@ -0,0 +1,182 @@
|
||||
/** Simplified memory map for the bootloader.
|
||||
* Make sure the bootloader can load into main memory without overwriting itself.
|
||||
* We put 2nd bootloader in the high address space (before ROM stack/data/bss).
|
||||
* See memory usage for ROM bootloader at the end of this file.
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
iram_seg (RWX) : org = 0x403CE000, len = 0x2000
|
||||
iram_loader_seg (RWX) : org = 0x403D0000, len = 0x6000
|
||||
dram_seg (RW) : org = 0x3FCD6000, len = 0x4000
|
||||
}
|
||||
|
||||
/* Default entry point: */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.iram_loader.text :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_loader_text_start = ABSOLUTE(.);
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
|
||||
*liblog.a:(.literal .text .literal.* .text.*)
|
||||
*libgcc.a:(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
|
||||
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
|
||||
*libbootloader_support.a:bootloader_efuse_esp32c3.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
|
||||
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
|
||||
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
|
||||
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
|
||||
*libefuse.a:*.*(.literal .text .literal.* .text.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_loader_text_end = ABSOLUTE(.);
|
||||
} > iram_loader_seg
|
||||
|
||||
.iram.text :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
} > iram_seg
|
||||
|
||||
|
||||
/* Shared RAM */
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_dram_start = ABSOLUTE(.);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram_seg
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
_data_end = ABSOLUTE(.);
|
||||
} > dram_seg
|
||||
|
||||
.dram0.rodata :
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
|
||||
*(.xt_except_table)
|
||||
*(.gcc_except_table)
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
*(.eh_frame)
|
||||
. = (. + 3) & ~ 3;
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
__init_array_start = ABSOLUTE(.);
|
||||
KEEP (*crtbegin.*(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
__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)
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
/* Literals are also RO data. */
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
*(*.lit4)
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
_dram_end = ABSOLUTE(.);
|
||||
} > dram_seg
|
||||
|
||||
.iram.text :
|
||||
{
|
||||
_stext = .;
|
||||
_text_start = ABSOLUTE(.);
|
||||
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.iram .iram.*) /* catch stray IRAM_ATTR */
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} > iram_seg
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appendix: Memory Usage of ROM bootloader
|
||||
*
|
||||
* +--------+--------------+------+ 0x3FCC_B000
|
||||
* | ^ |
|
||||
* | | |
|
||||
* | | data/bss |
|
||||
* | | |
|
||||
* | v |
|
||||
* +------------------------------+ 0x3FCD_C910
|
||||
* | ^ |
|
||||
* | | |
|
||||
* | | stack |
|
||||
* | | |
|
||||
* | v |
|
||||
* +------------------------------+ 0x3FCD_E910
|
||||
*/
|
@ -25,10 +25,13 @@ endif
|
||||
|
||||
COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \
|
||||
src/bootloader_flash_config_esp32s3.o \
|
||||
src/bootloader_flash_config_esp32c3.o \
|
||||
src/bootloader_efuse_esp32s2.o \
|
||||
src/bootloader_efuse_esp32s3.o \
|
||||
src/bootloader_efuse_esp32c3.o \
|
||||
src/bootloader_random_esp32s2.o \
|
||||
src/bootloader_random_esp32s3.o
|
||||
src/bootloader_random_esp32s3.o \
|
||||
src/bootloader_random_esp32c3.o
|
||||
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
|
@ -42,7 +42,7 @@ void bootloader_console_init(void)
|
||||
{
|
||||
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
|
||||
|
||||
esp_rom_install_channel_putc(1, esp_rom_uart_putc);
|
||||
esp_rom_install_uart_printf();
|
||||
|
||||
// Wait for UART FIFO to be empty.
|
||||
esp_rom_uart_tx_wait_idle(0);
|
||||
@ -52,7 +52,9 @@ void bootloader_console_init(void)
|
||||
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
|
||||
// Switch to the new UART (this just changes UART number used for esp_rom_printf in ROM code).
|
||||
#if ESP_ROM_SUPPORT_MULTIPLE_UART
|
||||
esp_rom_uart_set_as_console(uart_num);
|
||||
#endif
|
||||
// If console is attached to UART1 or if non-default pins are used,
|
||||
// need to reconfigure pins using GPIO matrix
|
||||
if (uart_num != 0 ||
|
||||
@ -75,7 +77,7 @@ void bootloader_console_init(void)
|
||||
|
||||
// Set configured UART console baud rate
|
||||
uint32_t clock_hz = rtc_clk_apb_freq_get();
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
#if ESP_ROM_UART_CLK_IS_XTAL
|
||||
clock_hz = UART_CLK_FREQ_ROM; // From esp32-s3 on, UART clock source is selected to XTAL in ROM
|
||||
#endif
|
||||
esp_rom_uart_set_clock_baudrate(uart_num, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE);
|
||||
|
28
components/bootloader_support/src/bootloader_efuse_esp32c3.c
Normal file
28
components/bootloader_support/src/bootloader_efuse_esp32c3.c
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
// should return the same value as esp_efuse_get_chip_ver()
|
||||
/* No other revisions for ESP32-C3 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t bootloader_common_get_chip_ver_pkg(void)
|
||||
{
|
||||
// should return the same value as esp_efuse_get_pkg_ver()
|
||||
return 0;
|
||||
}
|
@ -404,12 +404,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
}
|
||||
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
// TODO: use the same ROM API here
|
||||
return spi_to_esp_err(SPI_Encrypt_Write(dest_addr, src, size));
|
||||
#endif
|
||||
} else {
|
||||
return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size));
|
||||
}
|
||||
@ -447,7 +442,9 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef g_rom_spiflash_dummy_len_plus // ESP32-C3 uses a macro to access ROM data here
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
#endif
|
||||
uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
|
||||
{
|
||||
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
|
||||
|
@ -0,0 +1,83 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include "string.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32c3/rom/gpio.h"
|
||||
#include "esp32c3/rom/spi_flash.h"
|
||||
#include "esp32c3/rom/efuse.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/spi_caps.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#define FLASH_IO_MATRIX_DUMMY_40M 0
|
||||
#define FLASH_IO_MATRIX_DUMMY_80M 0
|
||||
|
||||
void bootloader_flash_update_id()
|
||||
{
|
||||
esp_rom_spiflash_chip_t *chip = &rom_spiflash_legacy_data->chip;
|
||||
chip->device_id = bootloader_read_flash_id();
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(1), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
|
||||
{
|
||||
uint32_t spi_clk_div = 0;
|
||||
switch (pfhdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
spi_clk_div = 1;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
spi_clk_div = 2;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
spi_clk_div = 3;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
spi_clk_div = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
esp_rom_spiflash_config_clk(spi_clk_div, 0);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_set_dummy_out(void)
|
||||
{
|
||||
REG_SET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL);
|
||||
REG_SET_BIT(SPI_MEM_CTRL_REG(1), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t *pfhdr)
|
||||
{
|
||||
bootloader_configure_spi_pins(1);
|
||||
bootloader_flash_set_dummy_out();
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "bootloader_random";
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
ESP_LOGW(TAG, "RNG for ESP32-C3 not currently supported"); // IDF-2305
|
||||
// Don't forget to remove the following line
|
||||
// *libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
|
||||
// In the bootloader.ld when RNG support is ready for ESP32-C3
|
||||
}
|
||||
|
||||
void bootloader_random_disable(void)
|
||||
{
|
||||
ESP_LOGW(TAG, "RNG for ESP32-C3 not currently supported"); // IDF-2305
|
||||
}
|
313
components/bootloader_support/src/esp32c3/bootloader_esp32c3.c
Normal file
313
components/bootloader_support/src/esp32c3/bootloader_esp32c3.c
Normal file
@ -0,0 +1,313 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_efuse.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/assist_debug_reg.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "esp32c3/rom/efuse.h"
|
||||
#include "esp32c3/rom/spi_flash.h"
|
||||
#include "esp32c3/rom/cache.h"
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#include "esp32c3/rom/spi_flash.h"
|
||||
#include "esp32c3/rom/rtc.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_mem.h"
|
||||
#include "regi2c_ctrl.h"
|
||||
#include "bootloader_console.h"
|
||||
|
||||
static const char *TAG = "boot.esp32c3";
|
||||
|
||||
void IRAM_ATTR bootloader_configure_spi_pins(int drv)
|
||||
{
|
||||
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
||||
uint8_t wp_pin = esp_rom_efuse_get_flash_wp_gpio();
|
||||
uint8_t clk_gpio_num = SPI_CLK_GPIO_NUM;
|
||||
uint8_t q_gpio_num = SPI_Q_GPIO_NUM;
|
||||
uint8_t d_gpio_num = SPI_D_GPIO_NUM;
|
||||
uint8_t cs0_gpio_num = SPI_CS0_GPIO_NUM;
|
||||
uint8_t hd_gpio_num = SPI_HD_GPIO_NUM;
|
||||
uint8_t wp_gpio_num = SPI_WP_GPIO_NUM;
|
||||
if (spiconfig == 0) {
|
||||
|
||||
} else {
|
||||
clk_gpio_num = spiconfig & 0x3f;
|
||||
q_gpio_num = (spiconfig >> 6) & 0x3f;
|
||||
d_gpio_num = (spiconfig >> 12) & 0x3f;
|
||||
cs0_gpio_num = (spiconfig >> 18) & 0x3f;
|
||||
hd_gpio_num = (spiconfig >> 24) & 0x3f;
|
||||
wp_gpio_num = wp_pin;
|
||||
}
|
||||
esp_rom_gpio_pad_set_drv(clk_gpio_num, drv);
|
||||
esp_rom_gpio_pad_set_drv(q_gpio_num, drv);
|
||||
esp_rom_gpio_pad_set_drv(d_gpio_num, drv);
|
||||
esp_rom_gpio_pad_set_drv(cs0_gpio_num, drv);
|
||||
if (hd_gpio_num <= MAX_PAD_GPIO_NUM) {
|
||||
esp_rom_gpio_pad_set_drv(hd_gpio_num, drv);
|
||||
}
|
||||
if (wp_gpio_num <= MAX_PAD_GPIO_NUM) {
|
||||
esp_rom_gpio_pad_set_drv(wp_gpio_num, drv);
|
||||
}
|
||||
}
|
||||
|
||||
static void bootloader_reset_mmu(void)
|
||||
{
|
||||
Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
Cache_MMU_Init();
|
||||
|
||||
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
|
||||
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
|
||||
}
|
||||
|
||||
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
uint32_t size;
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
// Set flash chip size
|
||||
esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode
|
||||
Cache_Resume_ICache(autoload);
|
||||
}
|
||||
|
||||
static void print_flash_info(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
ESP_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
|
||||
ESP_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
|
||||
ESP_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
|
||||
ESP_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
|
||||
ESP_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
|
||||
|
||||
const char *str;
|
||||
switch (bootloader_hdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
str = "40MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
str = "26.7MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
str = "20MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
str = "80MHz";
|
||||
break;
|
||||
default:
|
||||
str = "20MHz";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Speed : %s", str);
|
||||
|
||||
/* SPI mode could have been set to QIO during boot already,
|
||||
so test the SPI registers not the flash header */
|
||||
uint32_t spi_ctrl = REG_READ(SPI_MEM_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_MEM_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_QUAD) {
|
||||
str = "QOUT";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_DIO) {
|
||||
str = "DIO";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_DUAL) {
|
||||
str = "DOUT";
|
||||
} else if (spi_ctrl & SPI_MEM_FASTRD_MODE) {
|
||||
str = "FAST READ";
|
||||
} else {
|
||||
str = "SLOW READ";
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Mode : %s", str);
|
||||
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
str = "1MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
str = "2MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
str = "4MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
str = "8MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
str = "16MB";
|
||||
break;
|
||||
default:
|
||||
str = "2MB";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Flash Size : %s", str);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR bootloader_init_flash_configure(void)
|
||||
{
|
||||
bootloader_flash_dummy_config(&bootloader_image_hdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_init_spi_flash(void)
|
||||
{
|
||||
bootloader_init_flash_configure();
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
||||
if (spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_SPI && spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
|
||||
ESP_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
#endif
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
//ensure the flash is write-protected
|
||||
bootloader_enable_wp();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
{
|
||||
REG_SET_BIT(SYSTEM_CPU_PERI_CLK_EN_REG, SYSTEM_CLK_EN_ASSIST_DEBUG);
|
||||
REG_CLR_BIT(SYSTEM_CPU_PERI_RST_EN_REG, SYSTEM_RST_EN_ASSIST_DEBUG);
|
||||
REG_WRITE(ASSIST_DEBUG_CORE_0_RCD_EN_REG, ASSIST_DEBUG_CORE_0_RCD_PDEBUGEN | ASSIST_DEBUG_CORE_0_RCD_RECORDEN);
|
||||
}
|
||||
|
||||
static void wdt_reset_info_dump(int cpu)
|
||||
{
|
||||
// TODO ESP32-C3 IDF-2118
|
||||
ESP_LOGE(TAG, "WDT reset info dump is not supported yet", cpu_name);
|
||||
}
|
||||
|
||||
static void bootloader_check_wdt_reset(void)
|
||||
{
|
||||
int wdt_rst = 0;
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[0] == TG0WDT_CPU_RESET || rst_reas[0] == TG1WDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
}
|
||||
wdt_reset_cpu0_info_enable();
|
||||
}
|
||||
|
||||
static void bootloader_super_wdt_auto_feed(void)
|
||||
{
|
||||
REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, RTC_CNTL_SWD_WKEY_VALUE);
|
||||
REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_AUTO_FEED_EN);
|
||||
REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, 0);
|
||||
}
|
||||
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
// TODO ESP32-C3 IDF-2452
|
||||
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1);
|
||||
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
|
||||
}
|
||||
|
||||
static inline void bootloader_glitch_reset_disable(void)
|
||||
{
|
||||
// TODO ESP32-C3 IDF-2453
|
||||
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, 0);
|
||||
}
|
||||
|
||||
esp_err_t bootloader_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
bootloader_hardware_init();
|
||||
bootloader_glitch_reset_disable();
|
||||
bootloader_super_wdt_auto_feed();
|
||||
// protect memory region
|
||||
bootloader_init_mem();
|
||||
/* check that static RAM is after the stack */
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
// clear bss section
|
||||
bootloader_clear_bss_section();
|
||||
// reset MMU
|
||||
bootloader_reset_mmu();
|
||||
// config clock
|
||||
bootloader_clock_configure();
|
||||
// initialize console, from now on, we can use esp_log
|
||||
bootloader_console_init();
|
||||
/* print 2nd bootloader banner */
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// read chip revision and check if it's compatible to bootloader
|
||||
if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// initialize spi flash
|
||||
if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// check whether a WDT reset happend
|
||||
bootloader_check_wdt_reset();
|
||||
// config WDT
|
||||
bootloader_config_wdt();
|
||||
// enable RNG early entropy source
|
||||
bootloader_enable_random();
|
||||
err:
|
||||
return ret;
|
||||
}
|
48
components/bootloader_support/src/esp32c3/bootloader_sha.c
Normal file
48
components/bootloader_support/src/esp32c3/bootloader_sha.c
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "bootloader_sha.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp32c3/rom/sha.h"
|
||||
|
||||
static SHA_CTX ctx;
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start()
|
||||
{
|
||||
// Enable SHA hardware
|
||||
ets_sha_enable();
|
||||
ets_sha_init(&ctx, SHA2_256);
|
||||
return &ctx; // Meaningless non-NULL value
|
||||
}
|
||||
|
||||
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
assert(data_len % 4 == 0);
|
||||
ets_sha_update(&ctx, data, data_len, false);
|
||||
}
|
||||
|
||||
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
|
||||
if (digest == NULL) {
|
||||
bzero(&ctx, sizeof(ctx));
|
||||
return;
|
||||
}
|
||||
ets_sha_finish(&ctx, digest);
|
||||
}
|
296
components/bootloader_support/src/esp32c3/flash_encrypt.c
Normal file
296
components/bootloader_support/src/esp32c3/flash_encrypt.c
Normal file
@ -0,0 +1,296 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32c3/rom/secure_boot.h"
|
||||
#include "esp32c3/rom/cache.h"
|
||||
#include "esp32c3/rom/efuse.h"
|
||||
|
||||
static const char *TAG = "flash_encrypt";
|
||||
|
||||
/* Static functions for stages of flash encryption */
|
||||
static esp_err_t initialise_flash_encryption(void);
|
||||
static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis);
|
||||
static esp_err_t encrypt_bootloader(void);
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
|
||||
|
||||
esp_err_t esp_flash_encrypt_check_and_update(void)
|
||||
{
|
||||
// TODO ESP32-C3 IDF-2116
|
||||
uint32_t cnt = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_SPI_BOOT_CRYPT_CNT);
|
||||
ESP_LOGV(TAG, "SPI_BOOT_CRYPT_CNT 0x%x", cnt);
|
||||
|
||||
bool flash_crypt_wr_dis = false; // TODO: check if CRYPT_CNT is write disabled
|
||||
|
||||
_Static_assert(EFUSE_SPI_BOOT_CRYPT_CNT == 0x7, "assuming CRYPT_CNT is only 3 bits wide");
|
||||
|
||||
if (cnt == 1 || cnt == 3 || cnt == 7) {
|
||||
/* Flash is already encrypted */
|
||||
int left;
|
||||
if (cnt == 7 /* || disabled */) {
|
||||
left = 0;
|
||||
} else if (cnt == 3) {
|
||||
left = 1;
|
||||
} else {
|
||||
left = 2;
|
||||
}
|
||||
ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
|
||||
return ESP_OK;
|
||||
} else {
|
||||
/* Flash is not encrypted, so encrypt it! */
|
||||
return encrypt_flash_contents(cnt, flash_crypt_wr_dis);
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t initialise_flash_encryption(void)
|
||||
{
|
||||
/* Before first flash encryption pass, need to initialise key & crypto config */
|
||||
|
||||
/* Find out if a key is already set */
|
||||
bool has_aes128 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, NULL);
|
||||
bool has_aes256_1 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, NULL);
|
||||
bool has_aes256_2 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, NULL);
|
||||
|
||||
bool has_key = has_aes128 || (has_aes256_1 && has_aes256_2);
|
||||
|
||||
if (!has_key && (has_aes256_1 || has_aes256_2)) {
|
||||
ESP_LOGE(TAG, "Invalid efuse key blocks: Both AES-256 key blocks must be set.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (has_key) {
|
||||
ESP_LOGI(TAG, "Using pre-existing key in efuse");
|
||||
|
||||
ESP_LOGE(TAG, "TODO: Check key is read & write protected"); // TODO
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Generating new flash encryption key...");
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES256
|
||||
const unsigned BLOCKS_NEEDED = 2;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2;
|
||||
#else
|
||||
const unsigned BLOCKS_NEEDED = 1;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
#endif
|
||||
|
||||
if (ets_efuse_count_unused_key_blocks() < BLOCKS_NEEDED) {
|
||||
ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
for (ets_efuse_purpose_t purpose = PURPOSE_START; purpose <= PURPOSE_END; purpose++) {
|
||||
uint32_t buf[8] = {0};
|
||||
bootloader_fill_random(buf, sizeof(buf));
|
||||
ets_efuse_block_t block = ets_efuse_find_unused_key_block();
|
||||
ESP_LOGD(TAG, "Writing ETS_EFUSE_BLOCK_KEY%d with purpose %d",
|
||||
block - ETS_EFUSE_BLOCK_KEY0, purpose);
|
||||
bootloader_debug_buffer(buf, sizeof(buf), "Key content");
|
||||
int r = ets_efuse_write_key(block, purpose, buf, sizeof(buf));
|
||||
bzero(buf, sizeof(buf));
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "Key generation complete");
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "TODO: burn remaining security protection bits");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Encrypt all flash data that should be encrypted */
|
||||
static esp_err_t encrypt_flash_contents(uint32_t spi_boot_crypt_cnt, bool flash_crypt_wr_dis)
|
||||
{
|
||||
esp_err_t err;
|
||||
esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
|
||||
int num_partitions;
|
||||
|
||||
/* If the last spi_boot_crypt_cnt bit is burned or write-disabled, the
|
||||
device can't re-encrypt itself. */
|
||||
if (flash_crypt_wr_dis || spi_boot_crypt_cnt == EFUSE_SPI_BOOT_CRYPT_CNT) {
|
||||
ESP_LOGE(TAG, "Cannot re-encrypt data (SPI_BOOT_CRYPT_CNT 0x%02x write disabled %d", spi_boot_crypt_cnt, flash_crypt_wr_dis);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (spi_boot_crypt_cnt == 0) {
|
||||
/* Very first flash of encrypted data: generate keys, etc. */
|
||||
err = initialise_flash_encryption();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_bootloader();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = encrypt_and_load_partition_table(partition_table, &num_partitions);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Now iterate the just-loaded partition table, looking for entries to encrypt
|
||||
*/
|
||||
|
||||
/* Go through each partition and encrypt if necessary */
|
||||
for (int i = 0; i < num_partitions; i++) {
|
||||
err = encrypt_partition(i, &partition_table[i]);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "All flash regions checked for encryption pass");
|
||||
|
||||
/* Set least significant 0-bit in spi_boot_crypt_cnt */
|
||||
int ffs_inv = __builtin_ffs((~spi_boot_crypt_cnt) & 0x7);
|
||||
/* ffs_inv shouldn't be zero, as zero implies spi_boot_crypt_cnt == 0xFF */
|
||||
uint32_t new_spi_boot_crypt_cnt = spi_boot_crypt_cnt + (1 << (ffs_inv - 1));
|
||||
ESP_LOGD(TAG, "SPI_BOOT_CRYPT_CNT 0x%x -> 0x%x", spi_boot_crypt_cnt, new_spi_boot_crypt_cnt);
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
REG_SET_FIELD(EFUSE_PGM_DATA2_REG, EFUSE_SPI_BOOT_CRYPT_CNT, new_spi_boot_crypt_cnt);
|
||||
ets_efuse_program(ETS_EFUSE_BLOCK0);
|
||||
|
||||
ESP_LOGI(TAG, "Flash encryption completed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_bootloader(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t image_length;
|
||||
/* Check for plaintext bootloader (verification will fail if it's already encrypted) */
|
||||
if (esp_image_verify_bootloader(&image_length) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
|
||||
err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (esp_secure_boot_enabled()) {
|
||||
// TODO: anything different for secure boot?
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "no valid bootloader was found");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions)
|
||||
{
|
||||
esp_err_t err;
|
||||
/* Check for plaintext partition table */
|
||||
err = bootloader_flash_read(ESP_PARTITION_TABLE_OFFSET, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data");
|
||||
return err;
|
||||
}
|
||||
if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
|
||||
esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data - not plaintext?");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Valid partition table loaded */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition)
|
||||
{
|
||||
esp_err_t err;
|
||||
bool should_encrypt = (partition->flags & PART_FLAG_ENCRYPTED);
|
||||
|
||||
if (partition->type == PART_TYPE_APP) {
|
||||
/* check if the partition holds a valid unencrypted app */
|
||||
esp_image_metadata_t data_ignored;
|
||||
err = esp_image_verify(ESP_IMAGE_VERIFY,
|
||||
&partition->pos,
|
||||
&data_ignored);
|
||||
should_encrypt = (err == ESP_OK);
|
||||
} else if (partition->type == PART_TYPE_DATA && partition->subtype == PART_SUBTYPE_DATA_OTA) {
|
||||
/* check if we have ota data partition and the partition should be encrypted unconditionally */
|
||||
should_encrypt = true;
|
||||
}
|
||||
|
||||
if (!should_encrypt) {
|
||||
return ESP_OK;
|
||||
} else {
|
||||
/* should_encrypt */
|
||||
ESP_LOGI(TAG, "Encrypting partition %d at offset 0x%x (length 0x%x)...", index, partition->pos.offset, partition->pos.size);
|
||||
|
||||
err = esp_flash_encrypt_region(partition->pos.offset, partition->pos.size);
|
||||
ESP_LOGI(TAG, "Done encrypting");
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition %d", index);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t buf[FLASH_SECTOR_SIZE / sizeof(uint32_t)];
|
||||
|
||||
if (src_addr % FLASH_SECTOR_SIZE != 0) {
|
||||
ESP_LOGE(TAG, "esp_flash_encrypt_region bad src_addr 0x%x", src_addr);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
|
||||
uint32_t sec_start = i + src_addr;
|
||||
err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
err = bootloader_flash_erase_sector(sec_start / FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
err = bootloader_flash_write(sec_start, buf, FLASH_SECTOR_SIZE, true);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
flash_failed:
|
||||
ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
|
||||
return err;
|
||||
}
|
45
components/bootloader_support/src/esp32c3/secure_boot.c
Normal file
45
components/bootloader_support/src/esp32c3/secure_boot.c
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32c3/rom/secure_boot.h"
|
||||
#include "esp_rom_efuse.h"
|
||||
|
||||
static const char *TAG = "secure_boot";
|
||||
|
||||
esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
{
|
||||
uint8_t hash[32];
|
||||
|
||||
if (esp_rom_efuse_is_secure_boot_enabled()) {
|
||||
ESP_LOGI(TAG, "secure boot is already enabled, continuing..");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Verifying bootloader signature...\n");
|
||||
int r = ets_secure_boot_verify_bootloader(hash, false);
|
||||
if (r != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to verify bootloader signature");
|
||||
return r;
|
||||
}
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
REG_SET_BIT(EFUSE_PGM_DATA3_REG, EFUSE_SECURE_BOOT_EN);
|
||||
ets_efuse_program(ETS_EFUSE_BLOCK0);
|
||||
|
||||
assert(esp_rom_efuse_is_secure_boot_enabled());
|
||||
ESP_LOGI(TAG, "Secure boot permanently enabled");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp32c3/rom/secure_boot.h"
|
||||
|
||||
static const char *TAG = "secure_boot";
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
ets_secure_boot_key_digests_t trusted_keys = { 0 };
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
const uint8_t *data;
|
||||
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
|
||||
if ((src_addr + length) % 4096 != 0) {
|
||||
ESP_LOGE(TAG, "addr 0x%x length 0x%x doesn't end on a sector boundary", src_addr, length);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
|
||||
if (data == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length + sizeof(ets_secure_boot_signature_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Calculate digest of main image
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
bootloader_sha256_handle_t handle = bootloader_sha256_start();
|
||||
bootloader_sha256_data(handle, data, length);
|
||||
bootloader_sha256_finish(handle, digest);
|
||||
#else
|
||||
/* Use thread-safe esp-idf SHA function */
|
||||
esp_sha(SHA2_256, data, length, digest);
|
||||
#endif
|
||||
|
||||
int r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
|
||||
if (r == ETS_OK) {
|
||||
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
|
||||
// TODO: calling this function in IDF app context is unsafe
|
||||
r = ets_secure_boot_verify_signature(sig, digest, &trusted_keys);
|
||||
}
|
||||
bootloader_munmap(data);
|
||||
|
||||
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature_block(uint32_t sig_block_flash_offs, const uint8_t *image_digest)
|
||||
{
|
||||
ets_secure_boot_key_digests_t trusted_keys;
|
||||
|
||||
assert(sig_block_flash_offs % 4096 == 0); // TODO: enforce this in a better way
|
||||
|
||||
const ets_secure_boot_signature_t *sig = bootloader_mmap(sig_block_flash_offs, sizeof(ets_secure_boot_signature_t));
|
||||
|
||||
if (sig == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", sig_block_flash_offs);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "No trusted key digests were found in efuse!");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Verifying with RSA-PSS...");
|
||||
// TODO: calling this function in IDF app context is unsafe
|
||||
r = ets_secure_boot_verify_signature(sig, image_digest, &trusted_keys);
|
||||
}
|
||||
|
||||
bootloader_munmap(sig);
|
||||
|
||||
return (r == 0) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
@ -607,6 +607,11 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
|
||||
// Set up the obfuscation value to use for loading
|
||||
while (ram_obfs_value[0] == 0 || ram_obfs_value[1] == 0) {
|
||||
bootloader_fill_random(ram_obfs_value, sizeof(ram_obfs_value));
|
||||
#if CONFIG_IDF_ENV_FPGA
|
||||
/* FPGA doesn't always emulate the RNG */
|
||||
ram_obfs_value[0] ^= 0x33;
|
||||
ram_obfs_value[1] ^= 0x66;
|
||||
#endif
|
||||
}
|
||||
uint32_t *dest = (uint32_t *)load_addr;
|
||||
#endif
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "unity.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_util.h"
|
||||
|
71
components/esp32c3/CMakeLists.txt
Normal file
71
components/esp32c3/CMakeLists.txt
Normal file
@ -0,0 +1,71 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER)
|
||||
if(NOT "${target}" STREQUAL "esp32c3")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
# For bootloader, all we need from esp32c3 is headers
|
||||
idf_component_register(INCLUDE_DIRS include REQUIRES riscv)
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32c3.peripherals.ld")
|
||||
else()
|
||||
# Regular app build
|
||||
|
||||
set(srcs "cache_err_int.c"
|
||||
"clk.c"
|
||||
"crosscore_int.c"
|
||||
"dport_access.c"
|
||||
"esp_hmac.c"
|
||||
"esp_crypto_lock.c"
|
||||
"hw_random.c"
|
||||
"system_api_esp32c3.c")
|
||||
set(include_dirs "include")
|
||||
|
||||
set(requires driver efuse soc riscv) #unfortunately rom/uart uses SOC registers directly
|
||||
|
||||
# driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t
|
||||
# app_update is added here because cpu_start.c uses esp_ota_get_app_description() function.
|
||||
# esp_timer is added here because cpu_start.c uses esp_timer
|
||||
set(priv_requires
|
||||
app_trace app_update bootloader_support log mbedtls nvs_flash
|
||||
pthread spi_flash vfs espcoredump esp_common esp_timer)
|
||||
|
||||
set(fragments linker.lf ld/esp32c3_fragments.lf)
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
LDFRAGMENTS "${fragments}"
|
||||
REQUIRES "${requires}"
|
||||
PRIV_REQUIRES "${priv_requires}"
|
||||
REQUIRED_IDF_TARGETS esp32c3)
|
||||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/esp32c3_out.ld")
|
||||
|
||||
# Process the template file through the linker script generation mechanism, and use the output for linking the
|
||||
# final binary
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/ld/esp32c3.project.ld.in"
|
||||
PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp32c3.project.ld")
|
||||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32c3.peripherals.ld")
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC gcc)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u call_user_start_cpu0")
|
||||
|
||||
idf_build_get_property(config_dir CONFIG_DIR)
|
||||
# Preprocess esp32c3.ld linker script to include configuration, becomes esp32c3_out.ld
|
||||
set(LD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ld)
|
||||
add_custom_command(
|
||||
OUTPUT esp32c3_out.ld
|
||||
COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o esp32c3_out.ld -I ${config_dir} ${LD_DIR}/esp32c3.ld
|
||||
MAIN_DEPENDENCY ${LD_DIR}/esp32c3.ld ${sdkconfig_header}
|
||||
COMMENT "Generating linker script..."
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(esp32c3_linker_script DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/esp32c3_out.ld)
|
||||
add_dependencies(${COMPONENT_LIB} esp32c3_linker_script)
|
||||
|
||||
# disable stack protection in files which are involved in initialization of that feature
|
||||
set_source_files_properties(
|
||||
cpu_start.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-fno-stack-protector)
|
||||
endif()
|
219
components/esp32c3/Kconfig
Normal file
219
components/esp32c3/Kconfig
Normal file
@ -0,0 +1,219 @@
|
||||
menu "ESP32C3-Specific"
|
||||
visible if IDF_TARGET_ESP32C3
|
||||
|
||||
choice ESP32C3_DEFAULT_CPU_FREQ_MHZ
|
||||
prompt "CPU frequency"
|
||||
default ESP32C3_DEFAULT_CPU_FREQ_40 if IDF_ENV_FPGA
|
||||
default ESP32C3_DEFAULT_CPU_FREQ_160 if !IDF_ENV_FPGA
|
||||
help
|
||||
CPU frequency to be set on application startup.
|
||||
|
||||
config ESP32C3_DEFAULT_CPU_FREQ_40
|
||||
bool "40 MHz"
|
||||
depends on IDF_ENV_FPGA
|
||||
config ESP32C3_DEFAULT_CPU_FREQ_80
|
||||
bool "80 MHz"
|
||||
config ESP32C3_DEFAULT_CPU_FREQ_160
|
||||
bool "160 MHz"
|
||||
endchoice
|
||||
|
||||
config ESP32C3_DEFAULT_CPU_FREQ_MHZ
|
||||
int
|
||||
default 40 if ESP32C3_DEFAULT_CPU_FREQ_40
|
||||
default 80 if ESP32C3_DEFAULT_CPU_FREQ_80
|
||||
default 160 if ESP32C3_DEFAULT_CPU_FREQ_160
|
||||
|
||||
choice ESP32C3_UNIVERSAL_MAC_ADDRESSES
|
||||
bool "Number of universally administered (by IEEE) MAC address"
|
||||
default ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||
help
|
||||
Configure the number of universally administered (by IEEE) MAC addresses.
|
||||
During initialization, MAC addresses for each network interface are generated or derived from a
|
||||
single base MAC address.
|
||||
If the number of universal MAC addresses is Two, all interfaces (WiFi station, WiFi softap) receive a
|
||||
universally administered MAC address. They are generated sequentially by adding 0, and 1 (respectively)
|
||||
to the final octet of the base MAC address. If the number of universal MAC addresses is one,
|
||||
only WiFi station receives a universally administered MAC address.
|
||||
It's generated by adding 0 to the base MAC address.
|
||||
The WiFi softap receives local MAC addresses. It's derived from the universal WiFi station MAC addresses.
|
||||
When using the default (Espressif-assigned) base MAC address, either setting can be used. When using
|
||||
a custom universal MAC address range, the correct setting will depend on the allocation of MAC
|
||||
addresses in this range (either 1 or 2 per device.)
|
||||
|
||||
config ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||
bool "Two"
|
||||
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
|
||||
select ESP_MAC_ADDR_UNIVERSE_BT
|
||||
config ESP32C3_UNIVERSAL_MAC_ADDRESSES_THREE
|
||||
bool "Three"
|
||||
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
|
||||
select ESP_MAC_ADDR_UNIVERSE_WIFI_AP
|
||||
select ESP_MAC_ADDR_UNIVERSE_BT
|
||||
endchoice
|
||||
|
||||
config ESP32C3_UNIVERSAL_MAC_ADDRESSES
|
||||
int
|
||||
default 2 if ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||
default 3 if ESP32C3_UNIVERSAL_MAC_ADDRESSES_THREE
|
||||
|
||||
config ESP_MAC_ADDR_UNIVERSE_BT_OFFSET
|
||||
int
|
||||
default 2 if ESP32C3_UNIVERSAL_MAC_ADDRESSES_THREE
|
||||
default 1 if ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||
|
||||
config ESP32C3_DEBUG_OCDAWARE
|
||||
bool "Make exception and panic handlers JTAG/OCD aware"
|
||||
default y
|
||||
select FREERTOS_DEBUG_OCDAWARE
|
||||
help
|
||||
The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and
|
||||
instead of panicking, have the debugger stop on the offending instruction.
|
||||
|
||||
config ESP32C3_DEBUG_STUBS_ENABLE
|
||||
bool "OpenOCD debug stubs"
|
||||
default COMPILER_OPTIMIZATION_LEVEL_DEBUG
|
||||
depends on !ESP32C3_TRAX
|
||||
help
|
||||
Debug stubs are used by OpenOCD to execute pre-compiled onboard code which does some useful debugging,
|
||||
e.g. GCOV data dump.
|
||||
|
||||
config ESP32C3_BROWNOUT_DET
|
||||
# TODO ESP32-C3 IDF-2397
|
||||
bool
|
||||
default n
|
||||
help
|
||||
The ESP32-S3 has a built-in brownout detector which can detect if the voltage is lower than
|
||||
a specific value. If this happens, it will reset the chip in order to prevent unintended
|
||||
behaviour.
|
||||
|
||||
choice ESP32C3_BROWNOUT_DET_LVL_SEL
|
||||
prompt "Brownout voltage level"
|
||||
depends on ESP32C3_BROWNOUT_DET
|
||||
default ESP32C3_BROWNOUT_DET_LVL_SEL_7
|
||||
help
|
||||
The brownout detector will reset the chip when the supply voltage is approximately
|
||||
below this level. Note that there may be some variation of brownout voltage level
|
||||
between each ESP3-S3 chip.
|
||||
|
||||
#The voltage levels here are estimates, more work needs to be done to figure out the exact voltages
|
||||
#of the brownout threshold levels.
|
||||
config ESP32C3_BROWNOUT_DET_LVL_SEL_7
|
||||
bool "2.44V"
|
||||
config ESP32C3_BROWNOUT_DET_LVL_SEL_6
|
||||
bool "2.56V"
|
||||
config ESP32C3_BROWNOUT_DET_LVL_SEL_5
|
||||
bool "2.67V"
|
||||
config ESP32C3_BROWNOUT_DET_LVL_SEL_4
|
||||
bool "2.84V"
|
||||
config ESP32C3_BROWNOUT_DET_LVL_SEL_3
|
||||
bool "2.98V"
|
||||
config ESP32C3_BROWNOUT_DET_LVL_SEL_2
|
||||
bool "3.19V"
|
||||
config ESP32C3_BROWNOUT_DET_LVL_SEL_1
|
||||
bool "3.30V"
|
||||
endchoice
|
||||
|
||||
config ESP32C3_BROWNOUT_DET_LVL
|
||||
int
|
||||
default 1 if ESP32C3_BROWNOUT_DET_LVL_SEL_1
|
||||
default 2 if ESP32C3_BROWNOUT_DET_LVL_SEL_2
|
||||
default 3 if ESP32C3_BROWNOUT_DET_LVL_SEL_3
|
||||
default 4 if ESP32C3_BROWNOUT_DET_LVL_SEL_4
|
||||
default 5 if ESP32C3_BROWNOUT_DET_LVL_SEL_5
|
||||
default 6 if ESP32C3_BROWNOUT_DET_LVL_SEL_6
|
||||
default 7 if ESP32C3_BROWNOUT_DET_LVL_SEL_7
|
||||
|
||||
choice ESP32C3_TIME_SYSCALL
|
||||
prompt "Timers used for gettimeofday function"
|
||||
default ESP32C3_TIME_SYSCALL_USE_RTC_SYSTIMER
|
||||
help
|
||||
This setting defines which hardware timers are used to
|
||||
implement 'gettimeofday' and 'time' functions in C library.
|
||||
|
||||
- If both high-resolution (systimer) and RTC timers are used, timekeeping will
|
||||
continue in deep sleep. Time will be reported at 1 microsecond
|
||||
resolution. This is the default, and the recommended option.
|
||||
- If only high-resolution timer (systimer) is used, gettimeofday will
|
||||
provide time at microsecond resolution.
|
||||
Time will not be preserved when going into deep sleep mode.
|
||||
- If only RTC timer is used, timekeeping will continue in
|
||||
deep sleep, but time will be measured at 6.(6) microsecond
|
||||
resolution. Also the gettimeofday function itself may take
|
||||
longer to run.
|
||||
- If no timers are used, gettimeofday and time functions
|
||||
return -1 and set errno to ENOSYS.
|
||||
- When RTC is used for timekeeping, two RTC_STORE registers are
|
||||
used to keep time in deep sleep mode.
|
||||
|
||||
config ESP32C3_TIME_SYSCALL_USE_RTC_SYSTIMER
|
||||
bool "RTC and high-resolution timer"
|
||||
select ESP_TIME_FUNCS_USE_RTC_TIMER
|
||||
select ESP_TIME_FUNCS_USE_ESP_TIMER
|
||||
config ESP32C3_TIME_SYSCALL_USE_RTC
|
||||
bool "RTC"
|
||||
select ESP_TIME_FUNCS_USE_RTC_TIMER
|
||||
config ESP32C3_TIME_SYSCALL_USE_SYSTIMER
|
||||
bool "High-resolution timer"
|
||||
select ESP_TIME_FUNCS_USE_ESP_TIMER
|
||||
config ESP32C3_TIME_SYSCALL_USE_NONE
|
||||
bool "None"
|
||||
select ESP_TIME_FUNCS_USE_NONE
|
||||
endchoice
|
||||
|
||||
choice ESP32C3_RTC_CLK_SRC
|
||||
prompt "RTC clock source"
|
||||
default ESP32C3_RTC_CLK_SRC_INT_RC
|
||||
help
|
||||
Choose which clock is used as RTC clock source.
|
||||
|
||||
config ESP32C3_RTC_CLK_SRC_INT_RC
|
||||
bool "Internal 150kHz RC oscillator"
|
||||
config ESP32C3_RTC_CLK_SRC_EXT_CRYS
|
||||
bool "External 32kHz crystal"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
config ESP32C3_RTC_CLK_SRC_EXT_OSC
|
||||
bool "External 32kHz oscillator at 32K_XP pin"
|
||||
config ESP32C3_RTC_CLK_SRC_INT_8MD256
|
||||
bool "Internal 8MHz oscillator, divided by 256 (~32kHz)"
|
||||
endchoice
|
||||
|
||||
config ESP32C3_RTC_CLK_CAL_CYCLES
|
||||
int "Number of cycles for RTC_SLOW_CLK calibration"
|
||||
default 3000 if ESP32C3_RTC_CLK_SRC_EXT_CRYS || ESP32C3_RTC_CLK_SRC_EXT_OSC || ESP32C3_RTC_CLK_SRC_INT_8MD256
|
||||
default 1024 if ESP32C3_RTC_CLK_SRC_INT_RC
|
||||
range 0 125000
|
||||
help
|
||||
When the startup code initializes RTC_SLOW_CLK, it can perform
|
||||
calibration by comparing the RTC_SLOW_CLK frequency with main XTAL
|
||||
frequency. This option sets the number of RTC_SLOW_CLK cycles measured
|
||||
by the calibration routine. Higher numbers increase calibration
|
||||
precision, which may be important for applications which spend a lot of
|
||||
time in deep sleep. Lower numbers reduce startup time.
|
||||
|
||||
When this option is set to 0, clock calibration will not be performed at
|
||||
startup, and approximate clock frequencies will be assumed:
|
||||
|
||||
- 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024.
|
||||
- 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more.
|
||||
In case more value will help improve the definition of the launch of the crystal.
|
||||
If the crystal could not start, it will be switched to internal RC.
|
||||
|
||||
config ESP32C3_NO_BLOBS
|
||||
bool "No Binary Blobs"
|
||||
depends on !BT_ENABLED
|
||||
default n
|
||||
help
|
||||
If enabled, this disables the linking of binary libraries in the application build. Note
|
||||
that after enabling this Wi-Fi/Bluetooth will not work.
|
||||
|
||||
config ESP32C3_ALLOW_RTC_FAST_MEM_AS_HEAP
|
||||
bool "Enable RTC fast memory for dynamic allocations"
|
||||
depends on !ESP32C3_MEMPROT_FEATURE
|
||||
default y
|
||||
help
|
||||
This config option allows to add RTC fast memory region to system heap with capability
|
||||
similar to that of DRAM region but without DMA. This memory will be consumed first per
|
||||
heap initialization order by early startup services and scheduler related code. Speed
|
||||
wise RTC fast memory operates on APB clock and hence does not have much performance impact.
|
||||
|
||||
endmenu # ESP32C3-Specific
|
1
components/esp32c3/Makefile.projbuild
Normal file
1
components/esp32c3/Makefile.projbuild
Normal file
@ -0,0 +1 @@
|
||||
# ESP32-C3 is not supported in the GNU Make build system.
|
34
components/esp32c3/cache_err_int.c
Normal file
34
components/esp32c3/cache_err_int.c
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*
|
||||
The cache has an interrupt that can be raised as soon as an access to a cached
|
||||
region (flash) is done without the cache being enabled. We use that here
|
||||
to panic the CPU, which from a debugging perspective is better than grabbing bad
|
||||
data from the bus.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
// TODO ESP32-C3 IDF-2450
|
||||
void esp_cache_err_int_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
int IRAM_ATTR esp_cache_err_get_cpuid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
38
components/esp32c3/clk.c
Normal file
38
components/esp32c3/clk.c
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp32c3/clk.h"
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
int IRAM_ATTR esp_clk_cpu_freq(void)
|
||||
{
|
||||
return ets_get_cpu_frequency() * MHZ;
|
||||
}
|
||||
|
||||
int IRAM_ATTR esp_clk_apb_freq(void)
|
||||
{
|
||||
return MIN(80, ets_get_cpu_frequency()) * MHZ;
|
||||
}
|
||||
|
||||
int IRAM_ATTR esp_clk_xtal_freq(void)
|
||||
{
|
||||
return rtc_clk_xtal_freq_get() * MHZ;
|
||||
}
|
4
components/esp32c3/component.mk
Normal file
4
components/esp32c3/component.mk
Normal file
@ -0,0 +1,4 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
COMPONENT_CONFIG_ONLY := 1
|
97
components/esp32c3/crosscore_int.c
Normal file
97
components/esp32c3/crosscore_int.c
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdint.h>
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "hal/cpu_hal.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portmacro.h"
|
||||
|
||||
#define REASON_YIELD BIT(0)
|
||||
#define REASON_FREQ_SWITCH BIT(1)
|
||||
#define REASON_PRINT_BACKTRACE BIT(2)
|
||||
|
||||
static portMUX_TYPE reason_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
static volatile uint32_t reason[portNUM_PROCESSORS];
|
||||
|
||||
// TODO ESP32-C3 IDF-2449
|
||||
static inline void IRAM_ATTR esp_crosscore_isr_handle_yield(void)
|
||||
{
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
static void IRAM_ATTR esp_crosscore_isr(void *arg)
|
||||
{
|
||||
uint32_t my_reason_val;
|
||||
//A pointer to the correct reason array item is passed to this ISR.
|
||||
volatile uint32_t *my_reason = arg;
|
||||
|
||||
//Clear the interrupt first.
|
||||
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
|
||||
//Grab the reason and clear it.
|
||||
portENTER_CRITICAL_ISR(&reason_spinlock);
|
||||
my_reason_val = *my_reason;
|
||||
*my_reason = 0;
|
||||
portEXIT_CRITICAL_ISR(&reason_spinlock);
|
||||
|
||||
//Check what we need to do.
|
||||
if (my_reason_val & REASON_YIELD) {
|
||||
esp_crosscore_isr_handle_yield();
|
||||
}
|
||||
if (my_reason_val & REASON_FREQ_SWITCH) {
|
||||
/* Nothing to do here; the frequency switch event was already
|
||||
* handled by a hook in xtensa_vectors.S. Could be used in the future
|
||||
* to allow DFS features without the extra latency of the ISR hook.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the crosscore interrupt on this core.
|
||||
void esp_crosscore_int_init(void)
|
||||
{
|
||||
portENTER_CRITICAL(&reason_spinlock);
|
||||
reason[cpu_hal_get_core_id()] = 0;
|
||||
portEXIT_CRITICAL(&reason_spinlock);
|
||||
esp_err_t err = esp_intr_alloc(ETS_FROM_CPU_INTR0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void *)&reason[0], NULL);
|
||||
assert(err == ESP_OK);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR esp_crosscore_int_send(int core_id, uint32_t reason_mask)
|
||||
{
|
||||
assert(core_id < portNUM_PROCESSORS);
|
||||
//Mark the reason we interrupt the other CPU
|
||||
portENTER_CRITICAL(&reason_spinlock);
|
||||
reason[core_id] |= reason_mask;
|
||||
portEXIT_CRITICAL(&reason_spinlock);
|
||||
//Poke the other CPU.
|
||||
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0);
|
||||
}
|
||||
|
||||
void IRAM_ATTR esp_crosscore_int_send_yield(int core_id)
|
||||
{
|
||||
esp_crosscore_int_send(core_id, REASON_YIELD);
|
||||
}
|
||||
|
||||
void IRAM_ATTR esp_crosscore_int_send_freq_switch(int core_id)
|
||||
{
|
||||
esp_crosscore_int_send(core_id, REASON_FREQ_SWITCH);
|
||||
}
|
||||
|
||||
void IRAM_ATTR esp_crosscore_int_send_print_backtrace(int core_id)
|
||||
{
|
||||
esp_crosscore_int_send(core_id, REASON_PRINT_BACKTRACE);
|
||||
}
|
25
components/esp32c3/dport_access.c
Normal file
25
components/esp32c3/dport_access.c
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "soc/dport_access.h"
|
||||
|
||||
// Read a sequence of DPORT registers to the buffer.
|
||||
void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words)
|
||||
{
|
||||
for (uint32_t i = 0; i < num_words; ++i) {
|
||||
buff_out[i] = DPORT_SEQUENCE_REG_READ(address + i * 4);
|
||||
}
|
||||
}
|
98
components/esp32c3/esp_crypto_lock.c
Normal file
98
components/esp32c3/esp_crypto_lock.c
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <sys/lock.h>
|
||||
|
||||
#include "esp_crypto_lock.h"
|
||||
|
||||
/* Lock overview:
|
||||
SHA: independent
|
||||
AES: independent
|
||||
MPI/RSA: independent
|
||||
HMAC: needs SHA
|
||||
DS: needs HMAC (which needs SHA), AES and MPI
|
||||
*/
|
||||
|
||||
/* Lock for DS peripheral */
|
||||
static _lock_t s_crypto_ds_lock;
|
||||
|
||||
/* Lock for HMAC peripheral */
|
||||
static _lock_t s_crypto_hmac_lock;
|
||||
|
||||
/* Lock for the SHA peripheral, also used by the HMAC and DS peripheral */
|
||||
static _lock_t s_crypto_sha_lock;
|
||||
|
||||
/* Lock for the AES peripheral, also used by DS peripheral */
|
||||
static _lock_t s_crypto_aes_lock;
|
||||
|
||||
/* Lock for the MPI/RSA peripheral, also used by the DS peripheral */
|
||||
static _lock_t s_crypto_mpi_lock;
|
||||
|
||||
void esp_crypto_hmac_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_hmac_lock);
|
||||
esp_crypto_sha_lock_acquire();
|
||||
}
|
||||
|
||||
void esp_crypto_hmac_lock_release(void)
|
||||
{
|
||||
esp_crypto_sha_lock_release();
|
||||
_lock_release(&s_crypto_hmac_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_ds_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_ds_lock);
|
||||
esp_crypto_hmac_lock_acquire();
|
||||
esp_crypto_aes_lock_acquire();
|
||||
esp_crypto_mpi_lock_acquire();
|
||||
}
|
||||
|
||||
void esp_crypto_ds_lock_release(void)
|
||||
{
|
||||
esp_crypto_mpi_lock_release();
|
||||
esp_crypto_aes_lock_release();
|
||||
esp_crypto_hmac_lock_release();
|
||||
_lock_release(&s_crypto_ds_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_sha_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_sha_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_sha_lock_release(void)
|
||||
{
|
||||
_lock_release(&s_crypto_sha_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_aes_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_aes_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_aes_lock_release(void)
|
||||
{
|
||||
_lock_release(&s_crypto_aes_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_mpi_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_mpi_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_mpi_lock_release(void)
|
||||
{
|
||||
_lock_release(&s_crypto_mpi_lock);
|
||||
}
|
132
components/esp32c3/esp_hmac.c
Normal file
132
components/esp32c3/esp_hmac.c
Normal file
@ -0,0 +1,132 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp32c3/rom/hmac.h"
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#include "esp_hmac.h"
|
||||
#include "esp_crypto_lock.h"
|
||||
|
||||
#include "hal/hmac_hal.h"
|
||||
|
||||
#define SHA256_BLOCK_SZ 64
|
||||
#define SHA256_PAD_SZ 8
|
||||
|
||||
/**
|
||||
* @brief Apply the HMAC padding without the embedded length.
|
||||
*
|
||||
* @note This function does not check the data length, it is the responsability of the other functions in this
|
||||
* module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in.
|
||||
* Otherwise, this function has undefined behavior.
|
||||
* Note however, that for the actual HMAC implementation on ESP32C3, the length also needs to be applied at the end
|
||||
* of the block. This function alone deosn't do that.
|
||||
*/
|
||||
static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len)
|
||||
{
|
||||
memcpy(block, data, data_len);
|
||||
// Apply a one bit, followed by zero bits (refer to the ESP32C3 TRM).
|
||||
block[data_len] = 0x80;
|
||||
bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1);
|
||||
}
|
||||
|
||||
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
|
||||
const void *message,
|
||||
size_t message_len,
|
||||
uint8_t *hmac)
|
||||
{
|
||||
const uint8_t *message_bytes = (const uint8_t *)message;
|
||||
|
||||
if (!message || !hmac) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (key_id >= HMAC_KEY_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_crypto_hmac_lock_acquire();
|
||||
|
||||
// We also enable SHA and DS here. SHA is used by HMAC, DS will otherwise hold SHA in reset state.
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
|
||||
hmac_hal_start();
|
||||
|
||||
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_USER, key_id);
|
||||
if (conf_error) {
|
||||
esp_crypto_hmac_lock_release();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (message_len + 1 + SHA256_PAD_SZ <= SHA256_BLOCK_SZ) {
|
||||
// If message including padding is only one block...
|
||||
// Last message block, so apply SHA-256 padding rules in software
|
||||
uint8_t block[SHA256_BLOCK_SZ];
|
||||
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
|
||||
|
||||
write_and_padd(block, message_bytes, message_len);
|
||||
// Final block: append the bit length in this block and signal padding to peripheral
|
||||
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
|
||||
&bit_len, sizeof(bit_len));
|
||||
hmac_hal_write_one_block_512(block);
|
||||
} else {
|
||||
// If message including padding is needs more than one block
|
||||
|
||||
// write all blocks without padding except the last one
|
||||
size_t remaining_blocks = message_len / SHA256_BLOCK_SZ;
|
||||
for (int i = 1; i < remaining_blocks; i++) {
|
||||
hmac_hal_write_block_512(message_bytes);
|
||||
message_bytes += SHA256_BLOCK_SZ;
|
||||
hmac_hal_next_block_normal();
|
||||
}
|
||||
|
||||
// If message fits into one block but without padding, we must not write another block.
|
||||
if (remaining_blocks) {
|
||||
hmac_hal_write_block_512(message_bytes);
|
||||
message_bytes += SHA256_BLOCK_SZ;
|
||||
}
|
||||
|
||||
size_t remaining = message_len % SHA256_BLOCK_SZ;
|
||||
// Last message block, so apply SHA-256 padding rules in software
|
||||
uint8_t block[SHA256_BLOCK_SZ];
|
||||
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
|
||||
|
||||
// If the remaining message and appended padding doesn't fit into a single block, we have to write an
|
||||
// extra block with the rest of the message and potential padding first.
|
||||
if (remaining >= SHA256_BLOCK_SZ - SHA256_PAD_SZ) {
|
||||
write_and_padd(block, message_bytes, remaining);
|
||||
hmac_hal_next_block_normal();
|
||||
hmac_hal_write_block_512(block);
|
||||
bzero(block, SHA256_BLOCK_SZ);
|
||||
} else {
|
||||
write_and_padd(block, message_bytes, remaining);
|
||||
}
|
||||
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
|
||||
&bit_len, sizeof(bit_len));
|
||||
hmac_hal_next_block_padding();
|
||||
hmac_hal_write_block_512(block);
|
||||
}
|
||||
|
||||
// Read back result (bit swapped)
|
||||
hmac_hal_read_result_256(hmac);
|
||||
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
|
||||
esp_crypto_hmac_lock_release();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
68
components/esp32c3/hw_random.c
Normal file
68
components/esp32c3/hw_random.c
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_attr.h"
|
||||
#include "esp32c3/clk.h"
|
||||
#include "soc/wdev_reg.h"
|
||||
#include "hal/cpu_hal.h"
|
||||
|
||||
uint32_t IRAM_ATTR esp_random(void)
|
||||
{
|
||||
/* The PRNG which implements WDEV_RANDOM register gets 2 bits
|
||||
* of extra entropy from a hardware randomness source every APB clock cycle
|
||||
* (provided WiFi or BT are enabled). To make sure entropy is not drained
|
||||
* faster than it is added, this function needs to wait for at least 16 APB
|
||||
* clock cycles after reading previous word. This implementation may actually
|
||||
* wait a bit longer due to extra time spent in arithmetic and branch statements.
|
||||
*
|
||||
* As a (probably unncessary) precaution to avoid returning the
|
||||
* RNG state as-is, the result is XORed with additional
|
||||
* WDEV_RND_REG reads while waiting.
|
||||
*/
|
||||
|
||||
/* This code does not run in a critical section, so CPU frequency switch may
|
||||
* happens while this code runs (this will not happen in the current
|
||||
* implementation, but possible in the future). However if that happens,
|
||||
* the number of cycles spent on frequency switching will certainly be more
|
||||
* than the number of cycles we need to wait here.
|
||||
*/
|
||||
uint32_t cpu_to_apb_freq_ratio = esp_clk_cpu_freq() / esp_clk_apb_freq();
|
||||
|
||||
static uint32_t last_ccount = 0;
|
||||
uint32_t ccount;
|
||||
uint32_t result = 0;
|
||||
do {
|
||||
ccount = cpu_hal_get_cycle_count();
|
||||
result ^= REG_READ(WDEV_RND_REG);
|
||||
} while (ccount - last_ccount < cpu_to_apb_freq_ratio * 16);
|
||||
last_ccount = ccount;
|
||||
return result ^ REG_READ(WDEV_RND_REG);
|
||||
}
|
||||
|
||||
void esp_fill_random(void *buf, size_t len)
|
||||
{
|
||||
assert(buf != NULL);
|
||||
uint8_t *buf_bytes = (uint8_t *)buf;
|
||||
while (len > 0) {
|
||||
uint32_t word = esp_random();
|
||||
uint32_t to_copy = MIN(sizeof(word), len);
|
||||
memcpy(buf_bytes, &word, to_copy);
|
||||
buf_bytes += to_copy;
|
||||
len -= to_copy;
|
||||
}
|
||||
}
|
21
components/esp32c3/include/esp32c3/brownout.h
Normal file
21
components/esp32c3/include/esp32c3/brownout.h
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#ifndef __ESP_BROWNOUT_H
|
||||
#define __ESP_BROWNOUT_H
|
||||
|
||||
void esp_brownout_init(void);
|
||||
|
||||
#endif
|
33
components/esp32c3/include/esp32c3/cache_err_int.h
Normal file
33
components/esp32c3/include/esp32c3/cache_err_int.h
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
/**
|
||||
* @brief initialize cache invalid access interrupt
|
||||
*
|
||||
* This function enables cache invalid access interrupt source and connects it
|
||||
* to interrupt input number ETS_CACHEERR_INUM (see soc/soc.h). It is called
|
||||
* from the startup code.
|
||||
*/
|
||||
void esp_cache_err_int_init(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief get the CPU which caused cache invalid access interrupt
|
||||
* @return
|
||||
* - PRO_CPU_NUM, if PRO_CPU has caused cache IA interrupt
|
||||
* - APP_CPU_NUM, if APP_CPU has caused cache IA interrupt
|
||||
* - (-1) otherwise
|
||||
*/
|
||||
int esp_cache_err_get_cpuid(void);
|
84
components/esp32c3/include/esp32c3/clk.h
Normal file
84
components/esp32c3/include/esp32c3/clk.h
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file esp_clk.h
|
||||
*
|
||||
* This file contains declarations of clock related functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get the calibration value of RTC slow clock
|
||||
*
|
||||
* The value is in the same format as returned by rtc_clk_cal (microseconds,
|
||||
* in Q13.19 fixed-point format).
|
||||
*
|
||||
* @return the calibration value obtained using rtc_clk_cal, at startup time
|
||||
*/
|
||||
uint32_t esp_clk_slowclk_cal_get(void);
|
||||
|
||||
/**
|
||||
* @brief Update the calibration value of RTC slow clock
|
||||
*
|
||||
* The value has to be in the same format as returned by rtc_clk_cal (microseconds,
|
||||
* in Q13.19 fixed-point format).
|
||||
* This value is used by timekeeping functions (such as gettimeofday) to
|
||||
* calculate current time based on RTC counter value.
|
||||
* @param value calibration value obtained using rtc_clk_cal
|
||||
*/
|
||||
void esp_clk_slowclk_cal_set(uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Return current CPU clock frequency
|
||||
* When frequency switching is performed, this frequency may change.
|
||||
* However it is guaranteed that the frequency never changes with a critical
|
||||
* section.
|
||||
*
|
||||
* @return CPU clock frequency, in Hz
|
||||
*/
|
||||
int esp_clk_cpu_freq(void);
|
||||
|
||||
/**
|
||||
* @brief Return current APB clock frequency
|
||||
*
|
||||
* When frequency switching is performed, this frequency may change.
|
||||
* However it is guaranteed that the frequency never changes with a critical
|
||||
* section.
|
||||
*
|
||||
* @return APB clock frequency, in Hz
|
||||
*/
|
||||
int esp_clk_apb_freq(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read value of RTC counter, converting it to microseconds
|
||||
* @attention The value returned by this function may change abruptly when
|
||||
* calibration value of RTC counter is updated via esp_clk_slowclk_cal_set
|
||||
* function. This should not happen unless application calls esp_clk_slowclk_cal_set.
|
||||
* In ESP-IDF, esp_clk_slowclk_cal_set is only called in startup code.
|
||||
*
|
||||
* @return Value or RTC counter, expressed in microseconds
|
||||
*/
|
||||
uint64_t esp_clk_rtc_time(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
42
components/esp32c3/include/esp32c3/dport_access.h
Normal file
42
components/esp32c3/include/esp32c3/dport_access.h
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_DPORT_ACCESS_H_
|
||||
#define _ESP_DPORT_ACCESS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Read a sequence of DPORT registers to the buffer.
|
||||
*
|
||||
* @param[out] buff_out Contains the read data.
|
||||
* @param[in] address Initial address for reading registers.
|
||||
* @param[in] num_words The number of words.
|
||||
*/
|
||||
void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words);
|
||||
|
||||
#define DPORT_STALL_OTHER_CPU_START()
|
||||
#define DPORT_STALL_OTHER_CPU_END()
|
||||
#define DPORT_INTERRUPT_DISABLE()
|
||||
#define DPORT_INTERRUPT_RESTORE()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_DPORT_ACCESS_H_ */
|
356
components/esp32c3/include/esp32c3/memprot.h
Normal file
356
components/esp32c3/include/esp32c3/memprot.h
Normal file
@ -0,0 +1,356 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
/* INTERNAL API
|
||||
* generic interface to MMU memory protection features
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_attr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MEMPROT_IRAM0 = 0x00000000,
|
||||
MEMPROT_DRAM0 = 0x00000001,
|
||||
MEMPROT_UNKNOWN
|
||||
} mem_type_prot_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns splitting address for required memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return Splitting address for the memory region required.
|
||||
* The address is given by region-specific global symbol exported from linker script,
|
||||
* it is not read out from related configuration register.
|
||||
*/
|
||||
uint32_t *IRAM_ATTR esp_memprot_get_split_addr(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Initializes illegal memory access control (MMU) for required memory section.
|
||||
*
|
||||
* All memory access interrupts share ETS_MEMACCESS_ERR_INUM input channel, it is caller's
|
||||
* responsibility to properly detect actual intr. source as well as possible prioritization in case
|
||||
* of multiple source reported during one intr.handling routine run
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*/
|
||||
void esp_memprot_intr_init(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable the memory protection interrupt
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param enable enable/disable
|
||||
*/
|
||||
void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Detects whether any of the memory protection interrupts is active
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool esp_memprot_is_assoc_intr_any(void);
|
||||
|
||||
/**
|
||||
* @brief Detects whether specific memory protection interrupt is active
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool esp_memprot_is_assoc_intr(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Sets a request for clearing interrupt-on flag for specified memory region (register write)
|
||||
*
|
||||
* @note When called without actual interrupt-on flag set, subsequent occurrence of related interrupt is ignored.
|
||||
* Should be used only after the real interrupt appears, typically as the last step in interrupt handler's routine.
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*/
|
||||
void esp_memprot_clear_intr(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Detects which memory protection interrupt is active, check order: IRAM0, DRAM0
|
||||
*
|
||||
* @return Memory protection area type (see mem_type_prot_t enum)
|
||||
*/
|
||||
mem_type_prot_t IRAM_ATTR esp_memprot_get_intr_memtype(void);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt status register contents for specified memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return Contents of status register
|
||||
*/
|
||||
uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Get details of given interrupt status
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param faulting_address Faulting address causing the interrupt [out]
|
||||
* @param op_type Operation being processed at the faulting address [out]
|
||||
* IRAM0: 0 - read, 1 - write
|
||||
* DRAM0: 0 - read, 1 - write
|
||||
* @param op_subtype Additional info for op_type [out]
|
||||
* IRAM0: 0 - instruction segment access, 1 - data segment access
|
||||
* DRAM0: 0 - non-atomic operation, 1 - atomic operation
|
||||
*/
|
||||
void IRAM_ATTR esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype);
|
||||
|
||||
/**
|
||||
* @brief Gets string representation of required memory region identifier
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return mem_type as string
|
||||
*/
|
||||
const char *IRAM_ATTR esp_memprot_type_to_str(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Detects whether any of the interrupt locks is active (requires digital system reset to unlock)
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool esp_memprot_is_locked_any(void);
|
||||
|
||||
/**
|
||||
* @brief Sets lock for specified memory region.
|
||||
*
|
||||
* Locks can be unlocked only by digital system reset
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*/
|
||||
void esp_memprot_set_lock(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Gets lock status for required memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return true/false (locked/unlocked)
|
||||
*/
|
||||
bool esp_memprot_get_lock(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt permission control register contents for required memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return Permission control register contents
|
||||
*/
|
||||
uint32_t esp_memprot_get_ena_reg(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt permission settings for unified management block
|
||||
*
|
||||
* Gets interrupt permission settings register contents for required memory region, returns settings for unified management blocks
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return Permission settings register contents
|
||||
*/
|
||||
uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt permission settings for split management block
|
||||
*
|
||||
* Gets interrupt permission settings register contents for required memory region, returns settings for split management blocks
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return Permission settings register contents
|
||||
*/
|
||||
uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Detects whether any of the memory protection interrupts is enabled
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool esp_memprot_is_intr_ena_any(void);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt-enabled flag for given memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return Interrupt-enabled value
|
||||
*/
|
||||
uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt-active flag for given memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return Interrupt-active value
|
||||
*/
|
||||
uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt-clear request flag for given memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return Interrupt-clear request value
|
||||
*/
|
||||
uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Gets read permission value for specified block and memory region
|
||||
*
|
||||
* Returns read permission bit value for required unified-management block (0-3) in given memory region.
|
||||
* Applicable to all memory types.
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param block Memory block identifier (0-3)
|
||||
*
|
||||
* @return Read permission value for required block
|
||||
*/
|
||||
uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block);
|
||||
|
||||
/**
|
||||
* @brief Gets write permission value for specified block and memory region
|
||||
*
|
||||
* Returns write permission bit value for required unified-management block (0-3) in given memory region.
|
||||
* Applicable to all memory types.
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param block Memory block identifier (0-3)
|
||||
*
|
||||
* @return Write permission value for required block
|
||||
*/
|
||||
uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block);
|
||||
|
||||
/**
|
||||
* @brief Gets execute permission value for specified block and memory region
|
||||
*
|
||||
* Returns execute permission bit value for required unified-management block (0-3) in given memory region.
|
||||
* Applicable only to IRAM memory types
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param block Memory block identifier (0-3)
|
||||
*
|
||||
* @return Execute permission value for required block
|
||||
*/
|
||||
uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block);
|
||||
|
||||
/**
|
||||
* @brief Sets permissions for specified block in DRAM region
|
||||
*
|
||||
* Sets Read and Write permission for specified unified-management block (0-3) in given memory region.
|
||||
* Applicable only to DRAM memory types
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param block Memory block identifier (0-3)
|
||||
* @param write_perm Write permission flag
|
||||
* @param read_perm Read permission flag
|
||||
*/
|
||||
void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm);
|
||||
|
||||
/**
|
||||
* @brief Sets permissions for high and low memory segment in DRAM region
|
||||
*
|
||||
* Sets Read and Write permission for both low and high memory segments given by splitting address.
|
||||
* The splitting address must be equal to or higher then beginning of block 5
|
||||
* Applicable only to DRAM memory types
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param split_addr Address to split the memory region to lower and higher segment
|
||||
* @param lw Low segment Write permission flag
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param hw High segment Write permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
*/
|
||||
void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr);
|
||||
|
||||
/**
|
||||
* @brief Sets permissions for specified block in IRAM region
|
||||
*
|
||||
* Sets Read, Write and Execute permission for specified unified-management block (0-3) in given memory region.
|
||||
* Applicable only to IRAM memory types
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param block Memory block identifier (0-3)
|
||||
* @param write_perm Write permission flag
|
||||
* @param exec_perm Execute permission flag
|
||||
*/
|
||||
void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm);
|
||||
|
||||
/**
|
||||
* @brief Sets permissions for high and low memory segment in IRAM region
|
||||
*
|
||||
* Sets Read, Write and Execute permission for both low and high memory segments given by splitting address.
|
||||
* The splitting address must be equal to or higher then beginning of block 5
|
||||
* Applicable only to IRAM memory types
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param split_addr Address to split the memory region to lower and higher segment
|
||||
* @param lw Low segment Write permission flag
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param lx Low segment Execute permission flag
|
||||
* @param hw High segment Write permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
* @param hx High segment Execute permission flag
|
||||
*/
|
||||
void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx);
|
||||
|
||||
/**
|
||||
* @brief Activates memory protection for all supported memory region types
|
||||
*
|
||||
* @note The feature is disabled when JTAG interface is connected
|
||||
*
|
||||
* @param invoke_panic_handler map mem.prot interrupt to ETS_MEMACCESS_ERR_INUM and thus invokes panic handler when fired ('true' not suitable for testing)
|
||||
* @param lock_feature sets LOCK bit, see esp_memprot_set_lock() ('true' not suitable for testing)
|
||||
*/
|
||||
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature);
|
||||
|
||||
/**
|
||||
* @brief Get permission settings bits for IRAM split mgmt based on current split address
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lw Low segment Write permission flag
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param lx Low segment Execute permission flag
|
||||
* @param hw High segment Write permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
* @param hx High segment Execute permission flag
|
||||
*/
|
||||
void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx);
|
||||
|
||||
/**
|
||||
* @brief Get permission settings bits for DRAM split mgmt based on current split address
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lw Low segment Write permission flag
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param hw High segment Write permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
*/
|
||||
void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
40
components/esp32c3/include/esp32c3/rtc.h
Normal file
40
components/esp32c3/include/esp32c3/rtc.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file esp32c3/rtc.h
|
||||
*
|
||||
* This file contains declarations of rtc related functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get current value of RTC counter in microseconds
|
||||
*
|
||||
* Note: this function may take up to 1 RTC_SLOW_CLK cycle to execute
|
||||
*
|
||||
* @return current value of RTC counter in microseconds
|
||||
*/
|
||||
uint64_t esp_rtc_get_time_us(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
77
components/esp32c3/include/esp_clk.h
Normal file
77
components/esp32c3/include/esp_clk.h
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @file esp_clk.h
|
||||
*
|
||||
* This file contains declarations of clock related functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get the calibration value of RTC slow clock
|
||||
*
|
||||
* The value is in the same format as returned by rtc_clk_cal (microseconds,
|
||||
* in Q13.19 fixed-point format).
|
||||
*
|
||||
* @return the calibration value obtained using rtc_clk_cal, at startup time
|
||||
*/
|
||||
uint32_t esp_clk_slowclk_cal_get(void);
|
||||
|
||||
/**
|
||||
* @brief Update the calibration value of RTC slow clock
|
||||
*
|
||||
* The value has to be in the same format as returned by rtc_clk_cal (microseconds,
|
||||
* in Q13.19 fixed-point format).
|
||||
* This value is used by timekeeping functions (such as gettimeofday) to
|
||||
* calculate current time based on RTC counter value.
|
||||
* @param value calibration value obtained using rtc_clk_cal
|
||||
*/
|
||||
void esp_clk_slowclk_cal_set(uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Return current CPU clock frequency
|
||||
* When frequency switching is performed, this frequency may change.
|
||||
* However it is guaranteed that the frequency never changes with a critical
|
||||
* section.
|
||||
*
|
||||
* @return CPU clock frequency, in Hz
|
||||
*/
|
||||
int esp_clk_cpu_freq(void);
|
||||
|
||||
/**
|
||||
* @brief Return current APB clock frequency
|
||||
*
|
||||
* When frequency switching is performed, this frequency may change.
|
||||
* However it is guaranteed that the frequency never changes with a critical
|
||||
* section.
|
||||
*
|
||||
* @return APB clock frequency, in Hz
|
||||
*/
|
||||
int esp_clk_apb_freq(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read value of RTC counter, converting it to microseconds
|
||||
* @attention The value returned by this function may change abruptly when
|
||||
* calibration value of RTC counter is updated via esp_clk_slowclk_cal_set
|
||||
* function. This should not happen unless application calls esp_clk_slowclk_cal_set.
|
||||
* In ESP-IDF, esp_clk_slowclk_cal_set is only called in startup code.
|
||||
*
|
||||
* @return Value or RTC counter, expressed in microseconds
|
||||
*/
|
||||
uint64_t esp_clk_rtc_time(void);
|
87
components/esp32c3/include/esp_crypto_lock.h
Normal file
87
components/esp32c3/include/esp_crypto_lock.h
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for HMAC cryptography peripheral
|
||||
*
|
||||
* Internally also locks the SHA peripheral, as the HMAC depends on the SHA peripheral
|
||||
*/
|
||||
void esp_crypto_hmac_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for HMAC cryptography peripheral
|
||||
*
|
||||
* Internally also releases the SHA peripheral, as the HMAC depends on the SHA peripheral
|
||||
*/
|
||||
void esp_crypto_hmac_lock_release(void);
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for DS cryptography peripheral
|
||||
*
|
||||
* Internally also locks the HMAC (which locks SHA), AES and MPI peripheral, as the DS depends on these peripherals
|
||||
*/
|
||||
void esp_crypto_ds_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for DS cryptography peripheral
|
||||
*
|
||||
* Internally also releases the HMAC (which locks SHA), AES and MPI peripheral, as the DS depends on these peripherals
|
||||
*/
|
||||
void esp_crypto_ds_lock_release(void);
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for the SHA cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_sha_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for the SHA cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_sha_lock_release(void);
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for the aes cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_aes_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for the aes cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_aes_lock_release(void);
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for the mpi cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_mpi_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for the mpi/rsa cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_mpi_lock_release(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
67
components/esp32c3/include/esp_hmac.h
Normal file
67
components/esp32c3/include/esp_hmac.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_HMAC_H_
|
||||
#define _ESP_HMAC_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The possible efuse keys for the HMAC peripheral
|
||||
*/
|
||||
typedef enum {
|
||||
HMAC_KEY0 = 0,
|
||||
HMAC_KEY1,
|
||||
HMAC_KEY2,
|
||||
HMAC_KEY3,
|
||||
HMAC_KEY4,
|
||||
HMAC_KEY5,
|
||||
HMAC_KEY_MAX
|
||||
} hmac_key_id_t;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Calculate the HMAC of a given message.
|
||||
*
|
||||
* Calculate the HMAC \c hmac of a given message \c message with length \c message_len.
|
||||
* SHA256 is used for the calculation (fixed on ESP32S2).
|
||||
*
|
||||
* @note Uses the HMAC peripheral in "upstream" mode.
|
||||
*
|
||||
* @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calcuation.
|
||||
* The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
|
||||
* @param message the message for which to calculate the HMAC
|
||||
* @param message_len message length
|
||||
* return ESP_ERR_INVALID_STATE if unsuccessful
|
||||
* @param [out] hmac the hmac result; the buffer behind the provided pointer must be 32 bytes long
|
||||
*
|
||||
* @return
|
||||
* * ESP_OK, if the calculation was successful,
|
||||
* * ESP_FAIL, if the hmac calculation failed
|
||||
*/
|
||||
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
|
||||
const void *message,
|
||||
size_t message_len,
|
||||
uint8_t *hmac);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _ESP_HMAC_H_
|
101
components/esp32c3/ld/esp32c3.ld
Normal file
101
components/esp32c3/ld/esp32c3.ld
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* ESP32-C3 Linker Script Memory Layout
|
||||
* This file describes the memory layout (memory blocks) by virtual memory addresses.
|
||||
* This linker script is passed through the C preprocessor to include configuration options.
|
||||
* Please use preprocessor features sparingly!
|
||||
* Restrict to simple macros with numeric values, and/or #if/#endif blocks.
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#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
|
||||
|
||||
#if CONFIG_ESP32C3_USE_FIXED_STATIC_RAM_SIZE
|
||||
ASSERT((CONFIG_ESP32C3_FIXED_STATIC_RAM_SIZE <= I_D_SRAM_SIZE), "Fixed static ram data does not fit.")
|
||||
#define DRAM0_0_SEG_LEN CONFIG_ESP3C3_FIXED_STATIC_RAM_SIZE
|
||||
#else
|
||||
#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE
|
||||
#endif // CONFIG_ESP32C3_USE_FIXED_STATIC_RAM_SIZE
|
||||
MEMORY
|
||||
{
|
||||
/**
|
||||
* All these values assume the flash cache is on, and have the blocks this uses subtracted from the length
|
||||
* of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but
|
||||
* are connected to the data port of the CPU and eg allow byte-wise access.
|
||||
*/
|
||||
|
||||
/* IRAM for PRO CPU. */
|
||||
iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped instruction data */
|
||||
iram0_2_seg (RX) : org = 0x42000020, len = 0x8000000-0x20
|
||||
|
||||
/**
|
||||
* (0x20 offset above is a convenience for the app binary image generation.
|
||||
* Flash cache has 64KB pages. The .bin file which is flashed to the chip
|
||||
* has a 0x18 byte file header, and each segment has a 0x08 byte segment
|
||||
* header. Setting this offset makes it simple to meet the flash cache MMU's
|
||||
* constraint that (paddr % 64KB == vaddr % 64KB).)
|
||||
*/
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/**
|
||||
* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
|
||||
* Enabling Bluetooth & Trace Memory features in menuconfig will decrease the amount of RAM available.
|
||||
*/
|
||||
dram0_0_seg (RW) : org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped constant data */
|
||||
drom0_0_seg (R) : org = 0x3C000020, len = 0x8000000-0x20
|
||||
|
||||
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/**
|
||||
* RTC fast memory (executable). Persists over deep sleep.
|
||||
*/
|
||||
rtc_iram_seg(RWX) : org = 0x50000000, len = 0x2000
|
||||
}
|
||||
|
||||
#if CONFIG_ESP32C3_USE_FIXED_STATIC_RAM_SIZE
|
||||
/* static data ends at defined address */
|
||||
_static_data_end = 0x3FCA0000 + DRAM0_0_SEG_LEN;
|
||||
#else
|
||||
_static_data_end = _bss_end;
|
||||
#endif // CONFIG_ESP32C3_USE_FIXED_STATIC_RAM_SIZE
|
||||
|
||||
/* Heap ends at top of dram0_0_seg */
|
||||
_heap_end = 0x40000000;
|
||||
|
||||
_data_seg_org = ORIGIN(rtc_data_seg);
|
||||
|
||||
/**
|
||||
* The lines below define location alias for .rtc.data section
|
||||
* As C3 only has RTC fast memory, this is not configurable like on other targets
|
||||
*/
|
||||
REGION_ALIAS("rtc_data_seg", rtc_iram_seg );
|
||||
REGION_ALIAS("rtc_slow_seg", rtc_iram_seg );
|
||||
REGION_ALIAS("rtc_data_location", rtc_iram_seg );
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
REGION_ALIAS("default_code_seg", iram0_2_seg);
|
||||
#else
|
||||
REGION_ALIAS("default_code_seg", iram0_0_seg);
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
REGION_ALIAS("default_rodata_seg", drom0_0_seg);
|
||||
#else
|
||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
29
components/esp32c3/ld/esp32c3.peripherals.ld
Normal file
29
components/esp32c3/ld/esp32c3.peripherals.ld
Normal file
@ -0,0 +1,29 @@
|
||||
PROVIDE ( UART0 = 0x60000000 );
|
||||
PROVIDE ( UART1 = 0x60010000 );
|
||||
PROVIDE ( UART2 = 0x6002e000 );
|
||||
PROVIDE ( SPIMEM1 = 0x60002000 );
|
||||
PROVIDE ( SPIMEM0 = 0x60003000 );
|
||||
PROVIDE ( GPIO = 0x60004000 );
|
||||
PROVIDE ( SIGMADELTA = 0x60004f00 );
|
||||
PROVIDE ( RTCCNTL = 0x60008000 );
|
||||
PROVIDE ( RTCIO = 0x60008400 );
|
||||
PROVIDE ( SENS = 0x60008800 );
|
||||
PROVIDE ( HINF = 0x6000B000 );
|
||||
PROVIDE ( I2S1 = 0x6002d000 );
|
||||
PROVIDE ( I2C0 = 0x60013000 );
|
||||
PROVIDE ( UHCI0 = 0x60014000 );
|
||||
PROVIDE ( UHCI1 = 0x6000c000 );
|
||||
PROVIDE ( HOST = 0x60015000 );
|
||||
PROVIDE ( RMT = 0x60016000 );
|
||||
PROVIDE ( RMTMEM = 0x60016400 );
|
||||
PROVIDE ( PCNT = 0x60017000 );
|
||||
PROVIDE ( SLC = 0x60018000 );
|
||||
PROVIDE ( LEDC = 0x60019000 );
|
||||
PROVIDE ( TIMERG0 = 0x6001F000 );
|
||||
PROVIDE ( TIMERG1 = 0x60020000 );
|
||||
PROVIDE ( GPSPI2 = 0x60024000 );
|
||||
PROVIDE ( GPSPI3 = 0x60025000 );
|
||||
PROVIDE ( SYSCON = 0x60026000 );
|
||||
PROVIDE ( GPSPI4 = 0x60037000 );
|
||||
PROVIDE ( APB_SARADC = 0x60040000 );
|
||||
PROVIDE ( GDMA = 0x6003F000 );
|
395
components/esp32c3/ld/esp32c3.project.ld.in
Normal file
395
components/esp32c3/ld/esp32c3.project.ld.in
Normal file
@ -0,0 +1,395 @@
|
||||
/* Default entry point */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/**
|
||||
* RTC fast memory holds RTC wake stub code,
|
||||
* including from any source file named rtc_wake_stub*.c
|
||||
*/
|
||||
.rtc.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
|
||||
mapping[rtc_text]
|
||||
|
||||
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
|
||||
_rtc_text_end = ABSOLUTE(.);
|
||||
} > rtc_iram_seg
|
||||
|
||||
/**
|
||||
* This section is required to skip rtc.text area because rtc_iram_seg and
|
||||
* rtc_data_seg are reflect the same address space on different buses.
|
||||
*/
|
||||
.rtc.dummy :
|
||||
{
|
||||
_rtc_dummy_start = ABSOLUTE(.);
|
||||
_rtc_fast_start = ABSOLUTE(.);
|
||||
. = SIZEOF(.rtc.text);
|
||||
_rtc_dummy_end = ABSOLUTE(.);
|
||||
} > rtc_data_seg
|
||||
|
||||
/**
|
||||
* This section located in RTC FAST Memory area.
|
||||
* It holds data marked with RTC_FAST_ATTR attribute.
|
||||
* See the file "esp_attr.h" for more information.
|
||||
*/
|
||||
.rtc.force_fast :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_rtc_force_fast_start = ABSOLUTE(.);
|
||||
|
||||
_coredump_rtc_fast_start = ABSOLUTE(.);
|
||||
mapping[rtc_fast_coredump]
|
||||
_coredump_rtc_fast_end = ABSOLUTE(.);
|
||||
|
||||
*(.rtc.force_fast .rtc.force_fast.*)
|
||||
. = ALIGN(4) ;
|
||||
_rtc_force_fast_end = ABSOLUTE(.);
|
||||
} > rtc_data_seg
|
||||
|
||||
/**
|
||||
* RTC data section holds RTC wake stub
|
||||
* data/rodata, including from any source file
|
||||
* named rtc_wake_stub*.c and the data marked with
|
||||
* RTC_DATA_ATTR, RTC_RODATA_ATTR attributes.
|
||||
* The memory location of the data is dependent on
|
||||
* CONFIG_ESP32C3_RTCDATA_IN_FAST_MEM option.
|
||||
*/
|
||||
.rtc.data :
|
||||
{
|
||||
_rtc_data_start = ABSOLUTE(.);
|
||||
|
||||
/* coredump mapping */
|
||||
_coredump_rtc_start = ABSOLUTE(.);
|
||||
mapping[rtc_coredump]
|
||||
_coredump_rtc_end = ABSOLUTE(.);
|
||||
|
||||
/* should be placed after coredump mapping */
|
||||
mapping[rtc_data]
|
||||
|
||||
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
|
||||
_rtc_data_end = ABSOLUTE(.);
|
||||
} > rtc_data_location
|
||||
|
||||
/* RTC bss, from any source file named rtc_wake_stub*.c */
|
||||
.rtc.bss (NOLOAD) :
|
||||
{
|
||||
_rtc_bss_start = ABSOLUTE(.);
|
||||
*rtc_wake_stub*.*(.bss .bss.*)
|
||||
*rtc_wake_stub*.*(COMMON)
|
||||
|
||||
mapping[rtc_bss]
|
||||
|
||||
_rtc_bss_end = ABSOLUTE(.);
|
||||
} > rtc_data_location
|
||||
|
||||
/**
|
||||
* This section holds data that should not be initialized at power up
|
||||
* and will be retained during deep sleep.
|
||||
* User data marked with RTC_NOINIT_ATTR will be placed
|
||||
* into this section. See the file "esp_attr.h" for more information.
|
||||
* The memory location of the data is dependent on CONFIG_ESP32C3_RTCDATA_IN_FAST_MEM option.
|
||||
*/
|
||||
.rtc_noinit (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_rtc_noinit_start = ABSOLUTE(.);
|
||||
*(.rtc_noinit .rtc_noinit.*)
|
||||
. = ALIGN(4) ;
|
||||
_rtc_noinit_end = ABSOLUTE(.);
|
||||
} > rtc_data_location
|
||||
|
||||
/**
|
||||
* This section located in RTC SLOW Memory area.
|
||||
* It holds data marked with RTC_SLOW_ATTR attribute.
|
||||
* See the file "esp_attr.h" for more information.
|
||||
*/
|
||||
.rtc.force_slow :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_rtc_force_slow_start = ABSOLUTE(.);
|
||||
*(.rtc.force_slow .rtc.force_slow.*)
|
||||
. = ALIGN(4) ;
|
||||
_rtc_force_slow_end = ABSOLUTE(.);
|
||||
} > rtc_slow_seg
|
||||
|
||||
/* Get size of rtc slow data based on rtc_data_location alias */
|
||||
_rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
|
||||
? (_rtc_force_slow_end - _rtc_data_start)
|
||||
: (_rtc_force_slow_end - _rtc_force_slow_start);
|
||||
|
||||
_rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
|
||||
? (_rtc_force_fast_end - _rtc_fast_start)
|
||||
: (_rtc_noinit_end - _rtc_fast_start);
|
||||
|
||||
ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)),
|
||||
"RTC_SLOW segment data does not fit.")
|
||||
|
||||
ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)),
|
||||
"RTC_FAST segment data does not fit.")
|
||||
|
||||
.iram0.text :
|
||||
{
|
||||
_iram_start = ABSOLUTE(.);
|
||||
/* Vectors go to start of IRAM */
|
||||
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
|
||||
KEEP(*(.exception_vectors.text));
|
||||
. = ALIGN(4);
|
||||
|
||||
_invalid_pc_placeholder = ABSOLUTE(.);
|
||||
|
||||
/* Code marked as running out of IRAM */
|
||||
_iram_text_start = ABSOLUTE(.);
|
||||
|
||||
mapping[iram0_text]
|
||||
|
||||
} > iram0_0_seg
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
_bt_data_start = ABSOLUTE(.);
|
||||
*libbt.a:(.data .data.*)
|
||||
. = ALIGN (4);
|
||||
_bt_data_end = ABSOLUTE(.);
|
||||
_btdm_data_start = ABSOLUTE(.);
|
||||
*libbtdm_app.a:(.data .data.*)
|
||||
. = ALIGN (4);
|
||||
_btdm_data_end = ABSOLUTE(.);
|
||||
_nimble_data_start = ABSOLUTE(.);
|
||||
*libnimble.a:(.data .data.*)
|
||||
. = ALIGN (4);
|
||||
_nimble_data_end = ABSOLUTE(.);
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
__global_pointer$ = . + 0x800;
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
|
||||
/* coredump mapping */
|
||||
_coredump_dram_start = ABSOLUTE(.);
|
||||
mapping[dram_coredump]
|
||||
_coredump_dram_end = ABSOLUTE(.);
|
||||
|
||||
/* should be placed after coredump mapping */
|
||||
_esp_system_init_fn_array_start = ABSOLUTE(.);
|
||||
KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*)))
|
||||
_esp_system_init_fn_array_end = ABSOLUTE(.);
|
||||
|
||||
mapping[dram0_data]
|
||||
|
||||
_data_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > dram0_0_seg
|
||||
|
||||
/**
|
||||
* This section holds data that should not be initialized at power up.
|
||||
* The section located in Internal SRAM memory region. The macro _NOINIT
|
||||
* can be used as attribute to place data into this section.
|
||||
* See the "esp_attr.h" file for more information.
|
||||
*/
|
||||
.noinit (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_noinit_start = ABSOLUTE(.);
|
||||
*(.noinit .noinit.*)
|
||||
. = ALIGN(4) ;
|
||||
_noinit_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
|
||||
/* Shared RAM */
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
_bt_bss_start = ABSOLUTE(.);
|
||||
*libbt.a:(.bss .bss.* COMMON)
|
||||
. = ALIGN (4);
|
||||
_bt_bss_end = ABSOLUTE(.);
|
||||
_btdm_bss_start = ABSOLUTE(.);
|
||||
*libbtdm_app.a:(.bss .bss.* COMMON)
|
||||
. = ALIGN (4);
|
||||
_btdm_bss_end = ABSOLUTE(.);
|
||||
_nimble_bss_start = ABSOLUTE(.);
|
||||
*libnimble.a:(.bss .bss.* COMMON)
|
||||
. = ALIGN (4);
|
||||
_nimble_bss_end = ABSOLUTE(.);
|
||||
|
||||
mapping[dram0_bss]
|
||||
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.share.mem)
|
||||
*(.gnu.linkonce.b.*)
|
||||
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
|
||||
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.")
|
||||
|
||||
.flash.text :
|
||||
{
|
||||
_stext = .;
|
||||
_instruction_reserved_start = ABSOLUTE(.);
|
||||
_text_start = ABSOLUTE(.);
|
||||
|
||||
mapping[flash_text]
|
||||
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_instruction_reserved_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
|
||||
/**
|
||||
* Similar to _iram_start, this symbol goes here so it is
|
||||
* resolved by addr2line in preference to the first symbol in
|
||||
* the flash.text segment.
|
||||
*/
|
||||
_flash_cache_start = ABSOLUTE(0);
|
||||
} > default_code_seg
|
||||
|
||||
.flash_rodata_dummy (NOLOAD):
|
||||
{
|
||||
. = SIZEOF(.flash.text);
|
||||
. = ALIGN(0x10000) + 0x20;
|
||||
_rodata_reserved_start = .;
|
||||
} > drom0_0_seg
|
||||
|
||||
/* When modifying the alignment, don't forget to update tls_section_alignment in pxPortInitialiseStack */
|
||||
.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! */
|
||||
|
||||
mapping[flash_rodata]
|
||||
|
||||
*(.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 */
|
||||
__init_array_start = ABSOLUTE(.);
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array .ctors .ctors.*))
|
||||
__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.*)
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
_rodata_reserved_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > default_rodata_seg
|
||||
|
||||
/* Marks the end of IRAM code segment */
|
||||
.iram0.text_end (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
.iram0.data :
|
||||
{
|
||||
. = ALIGN(16);
|
||||
_iram_data_start = ABSOLUTE(.);
|
||||
|
||||
/* coredump mapping */
|
||||
_coredump_iram_start = ABSOLUTE(.);
|
||||
mapping[iram_coredump]
|
||||
_coredump_iram_end = ABSOLUTE(.);
|
||||
|
||||
/* should be placed after coredump mapping */
|
||||
mapping[iram0_data]
|
||||
|
||||
_iram_data_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
.iram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(16);
|
||||
_iram_bss_start = ABSOLUTE(.);
|
||||
|
||||
mapping[iram0_bss]
|
||||
|
||||
_iram_bss_end = ABSOLUTE(.);
|
||||
. = ALIGN(16);
|
||||
_iram_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
/* Marks the end of data, bss and possibly rodata */
|
||||
.dram0.heap_start (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
}
|
||||
|
||||
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||
"IRAM0 segment data does not fit.")
|
||||
|
||||
ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
|
||||
"DRAM segment data does not fit.")
|
132
components/esp32c3/ld/esp32c3_fragments.lf
Normal file
132
components/esp32c3/ld/esp32c3_fragments.lf
Normal file
@ -0,0 +1,132 @@
|
||||
[sections:text]
|
||||
entries:
|
||||
.text+
|
||||
.literal+
|
||||
|
||||
[sections:data]
|
||||
entries:
|
||||
.data+
|
||||
|
||||
[sections:bss]
|
||||
entries:
|
||||
.bss+
|
||||
|
||||
[sections:common]
|
||||
entries:
|
||||
COMMON
|
||||
|
||||
[sections:rodata]
|
||||
entries:
|
||||
.rodata+
|
||||
|
||||
[sections:rtc_text]
|
||||
entries:
|
||||
.rtc.text+
|
||||
.rtc.literal
|
||||
|
||||
[sections:rtc_data]
|
||||
entries:
|
||||
.rtc.data+
|
||||
|
||||
[sections:rtc_rodata]
|
||||
entries:
|
||||
.rtc.rodata+
|
||||
|
||||
[sections:rtc_bss]
|
||||
entries:
|
||||
.rtc.bss
|
||||
|
||||
[sections:rtc_fast_coredump]
|
||||
entries:
|
||||
.rtc.fast.coredump+
|
||||
|
||||
[sections:rtc_coredump]
|
||||
entries:
|
||||
.rtc.coredump+
|
||||
|
||||
[sections:dram_coredump]
|
||||
entries:
|
||||
.dram1.coredump+
|
||||
|
||||
[sections:iram_coredump]
|
||||
entries:
|
||||
.iram.data.coredump+
|
||||
|
||||
[sections:iram]
|
||||
entries:
|
||||
.iram1+
|
||||
|
||||
[sections:iram_data]
|
||||
entries:
|
||||
.iram.data+
|
||||
|
||||
[sections:iram_bss]
|
||||
entries:
|
||||
.iram.bss+
|
||||
|
||||
[sections:dram]
|
||||
entries:
|
||||
.dram1+
|
||||
|
||||
[sections:wifi_iram]
|
||||
entries:
|
||||
.wifi0iram+
|
||||
|
||||
[sections:wifi_rx_iram]
|
||||
entries:
|
||||
.wifirxiram+
|
||||
|
||||
[scheme:default]
|
||||
entries:
|
||||
if APP_BUILD_USE_FLASH_SECTIONS = y:
|
||||
text -> flash_text
|
||||
rodata -> flash_rodata
|
||||
else:
|
||||
text -> iram0_text
|
||||
rodata -> dram0_data
|
||||
data -> dram0_data
|
||||
bss -> dram0_bss
|
||||
common -> dram0_bss
|
||||
iram -> iram0_text
|
||||
iram_data -> iram0_data
|
||||
iram_bss -> iram0_bss
|
||||
dram -> dram0_data
|
||||
rtc_text -> rtc_text
|
||||
rtc_data -> rtc_data
|
||||
rtc_rodata -> rtc_data
|
||||
rtc_bss -> rtc_bss
|
||||
wifi_iram -> flash_text
|
||||
wifi_rx_iram -> flash_text
|
||||
dram_coredump -> dram_coredump
|
||||
iram_coredump -> iram_coredump
|
||||
rtc_coredump -> rtc_coredump
|
||||
rtc_fast_coredump -> rtc_fast_coredump
|
||||
|
||||
[scheme:rtc]
|
||||
entries:
|
||||
text -> rtc_text
|
||||
data -> rtc_data
|
||||
rodata -> rtc_data
|
||||
bss -> rtc_bss
|
||||
common -> rtc_bss
|
||||
|
||||
[scheme:noflash]
|
||||
entries:
|
||||
text -> iram0_text
|
||||
rodata -> dram0_data
|
||||
|
||||
[scheme:noflash_data]
|
||||
entries:
|
||||
rodata -> dram0_data
|
||||
|
||||
[scheme:noflash_text]
|
||||
entries:
|
||||
text -> iram0_text
|
||||
|
||||
[scheme:wifi_iram]
|
||||
entries:
|
||||
wifi_iram -> iram0_text
|
||||
|
||||
[scheme:wifi_rx_iram]
|
||||
entries:
|
||||
wifi_rx_iram -> iram0_text
|
9
components/esp32c3/linker.lf
Normal file
9
components/esp32c3/linker.lf
Normal file
@ -0,0 +1,9 @@
|
||||
[mapping:gcc]
|
||||
archive: libgcc.a
|
||||
entries:
|
||||
lib2funcs (noflash_text)
|
||||
|
||||
[mapping:gcov]
|
||||
archive: libgcov.a
|
||||
entries:
|
||||
* (noflash)
|
5
components/esp32c3/project_include.cmake
Normal file
5
components/esp32c3/project_include.cmake
Normal file
@ -0,0 +1,5 @@
|
||||
set(compile_options "-Wno-error=format="
|
||||
"-nostartfiles"
|
||||
"-Wno-format")
|
||||
|
||||
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
|
141
components/esp32c3/system_api_esp32c3.c
Normal file
141
components/esp32c3/system_api_esp32c3.c
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright 2013-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_private/system_internal.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32c3/rom/cache.h"
|
||||
#include "esp32c3/cache_err_int.h"
|
||||
#include "riscv/riscv_interrupts.h"
|
||||
#include "riscv/interrupt.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
|
||||
/* "inner" restart function for after RTOS, interrupts & anything else on this
|
||||
* core are already stopped. Stalls other core, resets hardware,
|
||||
* triggers restart.
|
||||
*/
|
||||
void IRAM_ATTR esp_restart_noos(void)
|
||||
{
|
||||
// Disable interrupts
|
||||
riscv_global_interrupts_disable();
|
||||
// Enable RTC watchdog for 1 second
|
||||
wdt_hal_context_t rtc_wdt_ctx;
|
||||
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE1, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
//Enable flash boot mode so that flash booting after restart is protected by the RTC WDT.
|
||||
wdt_hal_set_flashboot_en(&rtc_wdt_ctx, true);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
|
||||
// Reset and stall the other CPU.
|
||||
// CPU must be reset before stalling, in case it was running a s32c1i
|
||||
// instruction. This would cause memory pool to be locked by arbiter
|
||||
// to the stalled CPU, preventing current CPU from accessing this pool.
|
||||
const uint32_t core_id = cpu_hal_get_core_id();
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
const uint32_t other_core_id = (core_id == 0) ? 1 : 0;
|
||||
esp_cpu_reset(other_core_id);
|
||||
esp_cpu_stall(other_core_id);
|
||||
#endif
|
||||
|
||||
// Disable TG0/TG1 watchdogs
|
||||
wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
|
||||
wdt_hal_write_protect_disable(&wdt0_context);
|
||||
wdt_hal_disable(&wdt0_context);
|
||||
wdt_hal_write_protect_enable(&wdt0_context);
|
||||
|
||||
wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
|
||||
wdt_hal_write_protect_disable(&wdt1_context);
|
||||
wdt_hal_disable(&wdt1_context);
|
||||
wdt_hal_write_protect_enable(&wdt1_context);
|
||||
|
||||
// Flush any data left in UART FIFOs
|
||||
esp_rom_uart_tx_wait_idle(0);
|
||||
esp_rom_uart_tx_wait_idle(1);
|
||||
// Disable cache
|
||||
Cache_Disable_ICache();
|
||||
|
||||
// 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_MACPWR_RST |
|
||||
SYSTEM_RW_BTMAC_RST | SYSTEM_RW_BTLP_RST);
|
||||
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);
|
||||
REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0);
|
||||
// Set CPU back to XTAL source, no PLL, same as hard reset
|
||||
#if !CONFIG_IDF_ENV_FPGA
|
||||
rtc_clk_cpu_freq_set_xtal();
|
||||
#endif
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
// Clear entry point for APP CPU
|
||||
REG_WRITE(SYSTEM_CORE_1_CONTROL_1_REG, 0);
|
||||
#endif
|
||||
|
||||
// Reset CPUs
|
||||
if (core_id == 0) {
|
||||
// Running on PRO CPU: APP CPU is stalled. Can reset both CPUs.
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
esp_cpu_reset(1);
|
||||
#endif
|
||||
esp_cpu_reset(0);
|
||||
}
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
else {
|
||||
// Running on APP CPU: need to reset PRO CPU and unstall it,
|
||||
// then reset APP CPU
|
||||
esp_cpu_reset(0);
|
||||
esp_cpu_unstall(0);
|
||||
esp_cpu_reset(1);
|
||||
}
|
||||
#endif
|
||||
while (true) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void esp_chip_info(esp_chip_info_t *out_info)
|
||||
{
|
||||
memset(out_info, 0, sizeof(*out_info));
|
||||
out_info->model = CHIP_ESP32C3;
|
||||
out_info->cores = 1;
|
||||
out_info->features = CHIP_FEATURE_WIFI_BGN | CHIP_FEATURE_BLE;
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ESP_ROM_HAS_CRC_LE (1) // ROM CRC library supports Little Endian
|
||||
#define ESP_ROM_HAS_CRC_BE (1) // ROM CRC library supports Big Endian
|
||||
#define ESP_ROM_HAS_JPEG_DECODE (1) // ROM has JPEG decode library
|
||||
#define ESP_ROM_HAS_CRC_LE (1) // ROM CRC library supports Little Endian
|
||||
#define ESP_ROM_HAS_CRC_BE (1) // ROM CRC library supports Big Endian
|
||||
#define ESP_ROM_HAS_JPEG_DECODE (1) // ROM has JPEG decode library
|
||||
#define ESP_ROM_SUPPORT_MULTIPLE_UART (1) // ROM has multiple UARTs available for logging
|
||||
|
@ -36,3 +36,4 @@ PROVIDE ( esp_rom_md5_final = 0x4005db1c );
|
||||
|
||||
PROVIDE ( esp_rom_printf = ets_printf );
|
||||
PROVIDE ( esp_rom_delay_us = ets_delay_us );
|
||||
PROVIDE ( esp_rom_install_uart_printf = ets_install_uart_printf );
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ESP_ROM_HAS_CRC_LE (1) // ROM CRC library supports Little Endian
|
||||
#define ESP_ROM_HAS_CRC_BE (1) // ROM CRC library supports Big Endian
|
||||
#define ESP_ROM_HAS_JPEG_DECODE (1) // ROM has JPEG decode library
|
||||
#define ESP_ROM_HAS_CRC_LE (1) // ROM CRC library supports Little Endian
|
||||
#define ESP_ROM_HAS_CRC_BE (1) // ROM CRC library supports Big Endian
|
||||
#define ESP_ROM_HAS_JPEG_DECODE (1) // ROM has JPEG decode library
|
||||
#define ESP_ROM_UART_CLK_IS_XTAL (1) // UART clock source is selected to XTAL in ROM
|
||||
|
@ -24,8 +24,6 @@ PROVIDE ( esp_rom_uart_tx_one_char = uart_tx_one_char );
|
||||
PROVIDE ( esp_rom_uart_tx_wait_idle = uart_tx_wait_idle );
|
||||
PROVIDE ( esp_rom_uart_rx_one_char = uart_rx_one_char );
|
||||
PROVIDE ( esp_rom_uart_rx_string = UartRxString );
|
||||
PROVIDE ( esp_rom_uart_set_as_console = uart_tx_switch );
|
||||
PROVIDE ( esp_rom_uart_putc = ets_write_char_uart );
|
||||
|
||||
PROVIDE ( esp_rom_md5_init = MD5Init );
|
||||
PROVIDE ( esp_rom_md5_update = MD5Update );
|
||||
@ -33,3 +31,4 @@ PROVIDE ( esp_rom_md5_final = MD5Final );
|
||||
|
||||
PROVIDE ( esp_rom_printf = ets_printf );
|
||||
PROVIDE ( esp_rom_delay_us = ets_delay_us );
|
||||
PROVIDE ( esp_rom_install_uart_printf = ets_install_uart_printf );
|
||||
|
@ -14,4 +14,5 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ESP_ROM_HAS_CRC_LE (1) // ROM CRC library supports Little Endian
|
||||
#define ESP_ROM_HAS_CRC_LE (1) // ROM CRC library supports Little Endian
|
||||
#define ESP_ROM_SUPPORT_MULTIPLE_UART (1) // ROM has multiple UARTs available for logging
|
||||
|
@ -35,3 +35,4 @@ PROVIDE ( esp_rom_md5_final = 0x4000530c );
|
||||
|
||||
PROVIDE ( esp_rom_printf = ets_printf );
|
||||
PROVIDE ( esp_rom_delay_us = ets_delay_us );
|
||||
PROVIDE ( esp_rom_install_uart_printf = ets_install_uart_printf );
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ESP_ROM_HAS_CRC_LE (1) // ROM CRC library supports Little Endian
|
||||
#define ESP_ROM_HAS_CRC_BE (1) // ROM CRC library supports Big Endian
|
||||
#define ESP_ROM_HAS_JPEG_DECODE (1) // ROM has JPEG decode library
|
||||
#define ESP_ROM_HAS_CRC_LE (1) // ROM CRC library supports Little Endian
|
||||
#define ESP_ROM_HAS_CRC_BE (1) // ROM CRC library supports Big Endian
|
||||
#define ESP_ROM_HAS_JPEG_DECODE (1) // ROM has JPEG decode library
|
||||
#define ESP_ROM_SUPPORT_MULTIPLE_UART (1) // ROM has multiple UARTs available for logging
|
||||
#define ESP_ROM_UART_CLK_IS_XTAL (1) // UART clock source is selected to XTAL in ROM
|
||||
|
@ -38,3 +38,4 @@ PROVIDE ( esp_rom_md5_final = 0x40037740 );
|
||||
|
||||
PROVIDE ( esp_rom_printf = ets_printf );
|
||||
PROVIDE ( esp_rom_delay_us = ets_delay_us );
|
||||
PROVIDE ( esp_rom_install_uart_printf = ets_install_uart_printf );
|
||||
|
@ -51,6 +51,11 @@ void esp_rom_install_channel_putc(int channel, void (*putc)(char c));
|
||||
*/
|
||||
void esp_rom_disable_logging(void);
|
||||
|
||||
/**
|
||||
* @brief Install UART1 as the default console channel, equivalent to `esp_rom_install_channel_putc(1, esp_rom_uart_putc)`
|
||||
*/
|
||||
void esp_rom_install_uart_printf(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -141,7 +141,7 @@ void IRAM_ATTR call_start_cpu1(void)
|
||||
esp_rom_install_channel_putc(1, NULL);
|
||||
esp_rom_install_channel_putc(2, NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
ets_install_uart_printf();
|
||||
esp_rom_install_uart_printf();
|
||||
esp_rom_uart_set_as_console(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user