esp32c3: added target component

This commit is contained in:
morris 2020-12-01 20:03:10 +08:00
parent 65aebef596
commit 8330b2541a
27 changed files with 2406 additions and 0 deletions

View 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
View 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

View File

@ -0,0 +1 @@
# ESP32-C3 is not supported in the GNU Make build system.

View 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
View 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;
}

View File

@ -0,0 +1,4 @@
#
# Component Makefile
#
COMPONENT_CONFIG_ONLY := 1

View 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);
}

View 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);
}
}

View 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);
}

View 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;
}

View 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;
}
}

View 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

View 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);

View 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

View 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_ */

View 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

View 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

View 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);

View 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

View 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_

View 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

View 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 );

View 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.")

View 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

View File

@ -0,0 +1,9 @@
[mapping:gcc]
archive: libgcc.a
entries:
lib2funcs (noflash_text)
[mapping:gcov]
archive: libgcov.a
entries:
* (noflash)

View File

@ -0,0 +1,5 @@
set(compile_options "-Wno-error=format="
"-nostartfiles"
"-Wno-format")
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)

View 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;
}