Merge branch 'refactor/move_from_xtensa' into 'master'

Movements from xtensa

Closes IDF-2164

See merge request espressif/esp-idf!10556
This commit is contained in:
Angus Gratton
2021-03-11 00:24:25 +00:00
52 changed files with 510 additions and 731 deletions

View File

@@ -159,14 +159,15 @@
#include "sdkconfig.h"
#include "soc/soc.h"
#include "soc/dport_access.h"
#if CONFIG_IDF_TARGET_ESP32
#if !CONFIG_IDF_TARGET_ESP32C3
#include "soc/dport_reg.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#endif
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#include "soc/sensitive_reg.h"
#endif
#if __XTENSA__
#include "xtensa-debug-module.h"
#include "eri.h"
#include "trax.h"
#endif
#include "soc/timer_periph.h"
#include "freertos/FreeRTOS.h"
@@ -210,18 +211,6 @@ const static char *TAG = "esp_apptrace";
#define ESP_APPTRACE_LOGV( format, ... ) ESP_APPTRACE_LOG_LEV(V, ESP_LOG_VERBOSE, format, ##__VA_ARGS__)
#define ESP_APPTRACE_LOGO( format, ... ) ESP_APPTRACE_LOG_LEV(E, ESP_LOG_NONE, format, ##__VA_ARGS__)
// TODO: move these (and same definitions in trax.c to dport_reg.h)
#if CONFIG_IDF_TARGET_ESP32
#define TRACEMEM_MUX_PROBLK0_APPBLK1 0
#define TRACEMEM_MUX_BLK0_ONLY 1
#define TRACEMEM_MUX_BLK1_ONLY 2
#define TRACEMEM_MUX_PROBLK1_APPBLK0 3
#elif CONFIG_IDF_TARGET_ESP32S2
#define TRACEMEM_MUX_BLK0_NUM 19
#define TRACEMEM_MUX_BLK1_NUM 20
#define TRACEMEM_BLK_NUM2ADDR(_n_) (0x3FFB8000UL + 0x4000UL*((_n_)-4))
#endif
// TRAX is disabled, so we use its registers for our own purposes
// | 31..XXXXXX..24 | 23 .(host_connect). 23 | 22 .(host_data). 22| 21..(block_id)..15 | 14..(block_len)..0 |
#define ESP_APPTRACE_TRAX_CTRL_REG ERI_TRAX_DELAYCNT

View File

@@ -364,7 +364,7 @@ esp_err_t bootloader_init(void)
{
assert(&_bss_start <= &_bss_end);
assert(&_data_start <= &_data_end);
int *sp = get_sp();
int *sp = esp_cpu_get_sp();
assert(sp < &_bss_start);
assert(sp < &_data_start);
}

View File

@@ -402,7 +402,7 @@ static bool verify_load_addresses(int segment_index, intptr_t load_addr, intptr_
if (esp_ptr_in_dram(load_addr_p) && esp_ptr_in_dram(load_end_p)) { /* Writing to DRAM */
/* Check if we're clobbering the stack */
intptr_t sp = (intptr_t)get_sp();
intptr_t sp = (intptr_t)esp_cpu_get_sp();
if (bootloader_util_regions_overlap(sp - STACK_LOAD_HEADROOM, SOC_ROM_STACK_START,
load_addr, load_end)) {
reason = "overlaps bootloader stack";

View File

@@ -84,7 +84,7 @@ void IRAM_ATTR esp_restart_noos(void)
esp_rom_uart_tx_wait_idle(2);
#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
if (esp_ptr_external_ram(get_sp())) {
if (esp_ptr_external_ram(esp_cpu_get_sp())) {
// If stack_addr is from External Memory (CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY is used)
// then need to switch SP to Internal Memory otherwise
// we will get the "Cache disabled but cached memory region accessed" error after Cache_Read_Disable.

View File

@@ -1,3 +1,4 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +15,10 @@
#ifndef __ESP_ATTR_H__
#define __ESP_ATTR_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "sdkconfig.h"
#define ROMFN_ATTR
@@ -147,4 +151,8 @@ FORCE_INLINE_ATTR TYPE& operator<<=(TYPE& a, int b) { a <<= b; return a; }
#define IDF_DEPRECATED(REASON)
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ESP_ATTR_H__ */

View File

@@ -19,10 +19,11 @@
#include "sdkconfig.h"
#include "hal/cpu_hal.h"
#include "esp_debug_helpers.h"
#include "hal/cpu_types.h"
#include "hal/mpu_hal.h"
#include "esp_cpu.h"
#include "hal/soc_hal.h"
#include "soc/soc_caps.h"
@@ -47,7 +48,7 @@ void IRAM_ATTR esp_cpu_reset(int cpu_id)
soc_hal_reset_core(cpu_id);
}
esp_err_t IRAM_ATTR esp_set_watchpoint(int no, void *adr, int size, int flags)
esp_err_t IRAM_ATTR esp_cpu_set_watchpoint(int no, void *adr, int size, int flags)
{
watchpoint_trigger_t trigger;
@@ -70,7 +71,7 @@ esp_err_t IRAM_ATTR esp_set_watchpoint(int no, void *adr, int size, int flags)
return ESP_OK;
}
void IRAM_ATTR esp_clear_watchpoint(int no)
void IRAM_ATTR esp_cpu_clear_watchpoint(int no)
{
cpu_hal_clear_watchpoint(no);
}
@@ -87,13 +88,6 @@ bool IRAM_ATTR esp_cpu_in_ocd_debug_mode(void)
#endif
}
void IRAM_ATTR esp_set_breakpoint_if_jtag(void *fn)
{
if (esp_cpu_in_ocd_debug_mode()) {
cpu_hal_set_breakpoint(0, fn);
}
}
#if __XTENSA__
void esp_cpu_configure_region_protection(void)

View File

@@ -0,0 +1,109 @@
// Copyright 2010-2016 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_CPU_H
#define _ESP_CPU_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "hal/cpu_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_WATCHPOINT_LOAD 0x40000000
#define ESP_WATCHPOINT_STORE 0x80000000
#define ESP_WATCHPOINT_ACCESS 0xC0000000
typedef uint32_t esp_cpu_ccount_t;
/** @brief Read current stack pointer address
*
*/
static inline void *esp_cpu_get_sp(void)
{
return cpu_hal_get_sp();
}
/**
* @brief Stall CPU using RTC controller
* @param cpu_id ID of the CPU to stall (0 = PRO, 1 = APP)
*/
void esp_cpu_stall(int cpu_id);
/**
* @brief Un-stall CPU using RTC controller
* @param cpu_id ID of the CPU to un-stall (0 = PRO, 1 = APP)
*/
void esp_cpu_unstall(int cpu_id);
/**
* @brief Reset CPU using RTC controller
* @param cpu_id ID of the CPU to reset (0 = PRO, 1 = APP)
*/
void esp_cpu_reset(int cpu_id);
/**
* @brief Returns true if a JTAG debugger is attached to CPU
* OCD (on chip debug) port.
*
* @note If "Make exception and panic handlers JTAG/OCD aware"
* is disabled, this function always returns false.
*/
bool esp_cpu_in_ocd_debug_mode(void);
static inline esp_cpu_ccount_t esp_cpu_get_ccount(void)
{
return cpu_hal_get_cycle_count();
}
static inline void esp_cpu_set_ccount(esp_cpu_ccount_t val)
{
cpu_hal_set_cycle_count(val);
}
/**
* @brief Set a watchpoint to break/panic when a certain memory range is accessed.
*
* @param no Watchpoint number. On the ESP32, this can be 0 or 1.
* @param adr Base address to watch
* @param size Size of the region, starting at the base address, to watch. Must
* be one of 2^n, with n in [0..6].
* @param flags One of ESP_WATCHPOINT_* flags
*
* @return ESP_ERR_INVALID_ARG on invalid arg, ESP_OK otherwise
*
* @warning The ESP32 watchpoint hardware watches a region of bytes by effectively
* masking away the lower n bits for a region with size 2^n. If adr does
* not have zero for these lower n bits, you may not be watching the
* region you intended.
*/
esp_err_t esp_cpu_set_watchpoint(int no, void *adr, int size, int flags);
/**
* @brief Clear a watchpoint
*
* @param no Watchpoint to clear
*
*/
void esp_cpu_clear_watchpoint(int no);
#ifdef __cplusplus
}
#endif
#endif // _ESP_CPU_H

View File

@@ -19,6 +19,8 @@
#include <stdbool.h>
#include <stddef.h>
#include "esp_cpu.h"
#if __XTENSA__
#include "xt_instr_macros.h"
// [refactor-todo] not actually needed in this header now,
@@ -29,59 +31,18 @@
#include "xtensa/config/specreg.h"
#endif
#include "hal/cpu_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Read current stack pointer address
*
/** @brief Read current stack pointer address.
* Superseded by esp_cpu_get_sp in esp_cpu.h.
*/
static inline void *get_sp(void)
static inline __attribute__((deprecated)) void *get_sp(void)
{
return cpu_hal_get_sp();
return esp_cpu_get_sp();
}
/**
* @brief Stall CPU using RTC controller
* @param cpu_id ID of the CPU to stall (0 = PRO, 1 = APP)
*/
void esp_cpu_stall(int cpu_id);
/**
* @brief Un-stall CPU using RTC controller
* @param cpu_id ID of the CPU to un-stall (0 = PRO, 1 = APP)
*/
void esp_cpu_unstall(int cpu_id);
/**
* @brief Reset CPU using RTC controller
* @param cpu_id ID of the CPU to reset (0 = PRO, 1 = APP)
*/
void esp_cpu_reset(int cpu_id);
/**
* @brief Returns true if a JTAG debugger is attached to CPU
* OCD (on chip debug) port.
*
* @note If "Make exception and panic handlers JTAG/OCD aware"
* is disabled, this function always returns false.
*/
bool esp_cpu_in_ocd_debug_mode(void);
/**
* @brief Convert the PC register value to its true address
*
* The address of the current instruction is not stored as an exact uint32_t
* representation in PC register. This function will convert the value stored in
* the PC register to a uint32_t address.
*
* @param pc_raw The PC as stored in register format.
*
* @return Address in uint32_t format
*/
static inline uint32_t esp_cpu_process_stack_pc(uint32_t pc)
{
if (pc & 0x80000000) {
@@ -92,18 +53,6 @@ static inline uint32_t esp_cpu_process_stack_pc(uint32_t pc)
return pc - 3;
}
typedef uint32_t esp_cpu_ccount_t;
static inline esp_cpu_ccount_t esp_cpu_get_ccount(void)
{
return cpu_hal_get_cycle_count();
}
static inline void esp_cpu_set_ccount(esp_cpu_ccount_t val)
{
cpu_hal_set_cycle_count(val);
}
/**
* @brief Configure CPU to disable access to invalid memory regions
*

View File

@@ -23,10 +23,7 @@ extern "C" {
#include <stdbool.h>
#include "esp_err.h"
#include "soc/soc.h" // [refactor-todo] IDF-2297
#define ESP_WATCHPOINT_LOAD 0x40000000
#define ESP_WATCHPOINT_STORE 0x80000000
#define ESP_WATCHPOINT_ACCESS 0xC0000000
#include "esp_cpu.h"
/*
* @brief Structure used for backtracing
@@ -53,32 +50,6 @@ typedef struct {
*/
void esp_set_breakpoint_if_jtag(void *fn);
/**
* @brief Set a watchpoint to break/panic when a certain memory range is accessed.
*
* @param no Watchpoint number. On the ESP32, this can be 0 or 1.
* @param adr Base address to watch
* @param size Size of the region, starting at the base address, to watch. Must
* be one of 2^n, with n in [0..6].
* @param flags One of ESP_WATCHPOINT_* flags
*
* @return ESP_ERR_INVALID_ARG on invalid arg, ESP_OK otherwise
*
* @warning The ESP32 watchpoint hardware watches a region of bytes by effectively
* masking away the lower n bits for a region with size 2^n. If adr does
* not have zero for these lower n bits, you may not be watching the
* region you intended.
*/
esp_err_t esp_set_watchpoint(int no, void *adr, int size, int flags);
/**
* @brief Clear a watchpoint
*
* @param no Watchpoint to clear
*
*/
void esp_clear_watchpoint(int no);
/**
* Get the first frame of the current stack's backtrace
*
@@ -127,6 +98,24 @@ bool esp_backtrace_get_next_frame(esp_backtrace_frame_t *frame);
*/
esp_err_t esp_backtrace_print(int depth);
/**
* @brief Set a watchpoint to break/panic when a certain memory range is accessed.
* Superseded by esp_cpu_set_watchpoint in esp_cpu.h.
*/
static inline __attribute__((deprecated)) esp_err_t esp_set_watchpoint(int no, void *adr, int size, int flags)
{
return esp_cpu_set_watchpoint(no, adr, size, flags);
}
/**
* @brief Set a watchpoint to break/panic when a certain memory range is accessed.
* Superseded by esp_cpu_clear_watchpoint in esp_cpu.h.
*/
static inline __attribute__((deprecated)) void esp_clear_watchpoint(int no)
{
esp_cpu_clear_watchpoint(no);
}
#endif
#ifdef __cplusplus
}

View File

@@ -13,8 +13,6 @@
// limitations under the License.
#include <esp_expression_with_stack.h>
#include <freertos/xtensa_rtos.h>
#include <freertos/xtensa_context.h>
#include <setjmp.h>
#include <string.h>
#include "freertos/FreeRTOS.h"

View File

@@ -0,0 +1,88 @@
// 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 <stdio.h>
#include "esp_err.h"
#include "esp_log.h"
#include "xt_trax.h"
#include "trax.h"
#include "hal/trace_ll.h"
#include "soc/dport_reg.h"
#include "sdkconfig.h"
// Utility functions for enabling TRAX in early startup (hence the use
// of ESP_EARLY_LOGX) in Xtensa targets.
#if defined(CONFIG_ESP32_TRAX) || defined(CONFIG_ESP32S2_TRAX)
#define WITH_TRAX 1
#endif
static const char* __attribute__((unused)) TAG = "trax";
int trax_enable(trax_ena_select_t which)
{
#if !WITH_TRAX
ESP_EARLY_LOGE(TAG, "trax_enable called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
#if CONFIG_IDF_TARGET_ESP32
#ifndef CONFIG_ESP32_TRAX_TWOBANKS
if (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP) return ESP_ERR_NO_MEM;
#endif
if (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP) {
trace_ll_set_mode((which == TRAX_ENA_PRO_APP_SWAP)?TRACEMEM_MUX_PROBLK1_APPBLK0:TRACEMEM_MUX_PROBLK0_APPBLK1);
} else {
trace_ll_set_mode(TRACEMEM_MUX_BLK0_ONLY);
}
trace_ll_mem_enable(0, (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP || which == TRAX_ENA_PRO));
trace_ll_mem_enable(1, (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP || which == TRAX_ENA_APP));
return ESP_OK;
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (which != TRAX_ENA_PRO) {
return ESP_ERR_INVALID_ARG;
}
trace_ll_set_mem_block(TRACEMEM_MUX_BLK1_NUM);
return ESP_OK;
#endif
}
int trax_start_trace(trax_downcount_unit_t units_until_stop)
{
#if !WITH_TRAX
ESP_EARLY_LOGE(TAG, "trax_start_trace called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
if (xt_trax_trace_is_active()) {
ESP_EARLY_LOGI(TAG, "Stopping active trace first.");
//Trace is active. Stop trace.
xt_trax_trigger_traceend_after_delay(0);
}
if (units_until_stop == TRAX_DOWNCOUNT_INSTRUCTIONS) {
xt_trax_start_trace_instructions();
} else {
xt_trax_start_trace_words();
}
return ESP_OK;
}
int trax_trigger_traceend_after_delay(int delay)
{
#if !WITH_TRAX
ESP_EARLY_LOGE(TAG, "trax_trigger_traceend_after_delay called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
xt_trax_trigger_traceend_after_delay(delay);
return ESP_OK;
}

View File

@@ -1,8 +1,22 @@
// Copyright 2015-2016 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 "esp_err.h"
#include "eri.h"
#include "xtensa-debug-module.h"
#include "xt_trax.h"
typedef enum {
TRAX_DOWNCOUNT_WORDS,
@@ -17,7 +31,6 @@ typedef enum {
TRAX_ENA_PRO_APP_SWAP
} trax_ena_select_t;
/**
* @brief Enable the trax memory blocks to be used as Trax memory.
*

View File

@@ -3,6 +3,11 @@ set(srcs "dport_panic_highint_hdl.S"
"reset_reason.c"
"../../arch/xtensa/panic_arch.c"
"../../arch/xtensa/panic_handler_asm.S"
"../../arch/xtensa/expression_with_stack.c"
"../../arch/xtensa/expression_with_stack_asm.S"
"../../arch/xtensa/debug_helpers.c"
"../../arch/xtensa/debug_helpers_asm.S"
"../../arch/xtensa/trax.c"
)
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})

View File

@@ -2,6 +2,8 @@ set(srcs "clk.c"
"reset_reason.c"
"../../async_memcpy_impl_gdma.c"
"apb_backup_dma.c"
"../../arch/riscv/expression_with_stack.c"
"../../arch/riscv/expression_with_stack_asm.S"
"../../arch/riscv/panic_arch.c")
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})

View File

@@ -4,6 +4,11 @@ set(srcs "async_memcpy_impl_cp_dma.c"
"reset_reason.c"
"../../arch/xtensa/panic_arch.c"
"../../arch/xtensa/panic_handler_asm.S"
"../../arch/xtensa/expression_with_stack.c"
"../../arch/xtensa/expression_with_stack_asm.S"
"../../arch/xtensa/debug_helpers.c"
"../../arch/xtensa/debug_helpers_asm.S"
"../../arch/xtensa/trax.c"
)
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})

View File

@@ -4,6 +4,11 @@ set(srcs "dport_panic_highint_hdl.S"
"../../async_memcpy_impl_gdma.c"
"../../arch/xtensa/panic_arch.c"
"../../arch/xtensa/panic_handler_asm.S"
"../../arch/xtensa/expression_with_stack.c"
"../../arch/xtensa/expression_with_stack_asm.S"
"../../arch/xtensa/debug_helpers.c"
"../../arch/xtensa/debug_helpers_asm.S"
"../../arch/xtensa/trax.c"
)
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})

View File

@@ -306,7 +306,7 @@ static int fibonacci(int n, void* func(void))
RSR(WINDOWSTART, start);
printf("WINDOWBASE = %-2d WINDOWSTART = 0x%x\n", base, start);
if (n <= 1) {
StackType_t *last_addr_stack = get_sp();
StackType_t *last_addr_stack = esp_cpu_get_sp();
StackType_t *used_stack = (StackType_t *) (start_addr_stack - last_addr_stack);
printf("addr_stack = %p, used[%p]/all[0x%x] space in stack\n", last_addr_stack, used_stack, size_stack);
func();
@@ -319,7 +319,7 @@ static int fibonacci(int n, void* func(void))
static void test_task(void *func)
{
start_addr_stack = get_sp();
start_addr_stack = esp_cpu_get_sp();
if (esp_ptr_external_ram(start_addr_stack)) {
printf("restart_task: uses external stack, addr_stack = %p\n", start_addr_stack);
} else {
@@ -336,7 +336,7 @@ static void func_do_exception(void)
static void init_restart_task(void)
{
StackType_t *stack_for_task = (StackType_t *) heap_caps_calloc(1, size_stack, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
printf("init_task: current addr_stack = %p, stack_for_task = %p\n", get_sp(), stack_for_task);
printf("init_task: current addr_stack = %p, stack_for_task = %p\n", esp_cpu_get_sp(), stack_for_task);
static StaticTask_t task_buf;
xTaskCreateStaticPinnedToCore(test_task, "test_task", size_stack, esp_restart, 5, stack_for_task, &task_buf, 1);
while (1) { };
@@ -345,7 +345,7 @@ static void init_restart_task(void)
static void init_task_do_exception(void)
{
StackType_t *stack_for_task = (StackType_t *) heap_caps_calloc(1, size_stack, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
printf("init_task: current addr_stack = %p, stack_for_task = %p\n", get_sp(), stack_for_task);
printf("init_task: current addr_stack = %p, stack_for_task = %p\n", esp_cpu_get_sp(), stack_for_task);
static StaticTask_t task_buf;
xTaskCreateStaticPinnedToCore(test_task, "test_task", size_stack, func_do_exception, 5, stack_for_task, &task_buf, 1);
while (1) { };

View File

@@ -77,15 +77,15 @@ FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void)
memset(s_coredump_stack, COREDUMP_STACK_FILL_BYTE, ESP_COREDUMP_STACK_SIZE);
/* watchpoint 1 can be used for task stack overflow detection, re-use it, it is no more necessary */
//esp_clear_watchpoint(1);
//esp_set_watchpoint(1, s_coredump_stack, 1, ESP_WATCHPOINT_STORE);
//esp_cpu_clear_watchpoint(1);
//esp_cpu_set_watchpoint(1, s_coredump_stack, 1, ESP_WATCHPOINT_STORE);
/* Replace the stack pointer depending on the architecture, but save the
* current stack pointer, in order to be able too restore it later.
* This function must be inlined. */
s_core_dump_backup = esp_core_dump_replace_sp(s_core_dump_sp);
ESP_COREDUMP_LOGI("Backing up stack @ %p and use core dump stack @ %p",
s_core_dump_backup, get_sp());
s_core_dump_backup, esp_cpu_get_sp());
}
/**
@@ -127,8 +127,8 @@ FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void)
/* If we are in ISR set watchpoint to the end of ISR stack */
if (esp_core_dump_in_isr_context()) {
uint8_t* topStack = esp_core_dump_get_isr_stack_top();
esp_clear_watchpoint(1);
esp_set_watchpoint(1, topStack+xPortGetCoreID()*configISR_STACK_SIZE, 1, ESP_WATCHPOINT_STORE);
esp_cpu_clear_watchpoint(1);
esp_cpu_set_watchpoint(1, topStack+xPortGetCoreID()*configISR_STACK_SIZE, 1, ESP_WATCHPOINT_STORE);
} else {
/* for tasks user should enable stack overflow detection in menuconfig
TODO: if not enabled in menuconfig enable it ourselves */

View File

@@ -337,7 +337,7 @@ void vPortSetStackWatchpoint(void *pxStackStart)
{
uint32_t addr = (uint32_t)pxStackStart;
addr = (addr + (STACK_WATCH_AREA_SIZE - 1)) & (~(STACK_WATCH_AREA_SIZE - 1));
esp_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_WATCHPOINT_STORE);
esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_WATCHPOINT_STORE);
}
uint32_t xPortGetTickRateHz(void) {

View File

@@ -428,7 +428,7 @@ void vPortSetStackWatchpoint( void* pxStackStart ) {
//This way, we make sure we trigger before/when the stack canary is corrupted, not after.
int addr=(int)pxStackStart;
addr=(addr+31)&(~31);
esp_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char*)addr, 32, ESP_WATCHPOINT_STORE);
esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char*)addr, 32, ESP_WATCHPOINT_STORE);
}
uint32_t xPortGetTickRateHz(void) {

View 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.
#pragma once
#include "soc/dport_reg.h"
static inline void trace_ll_mem_enable(int cpu, bool enable)
{
int reg[] = {DPORT_PRO_TRACEMEM_ENA_REG, DPORT_APP_TRACEMEM_ENA_REG};
DPORT_WRITE_PERI_REG(reg[cpu], enable);
}
static inline void trace_ll_set_mode(int mode)
{
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, mode);
}

View File

@@ -0,0 +1,23 @@
// 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.
#pragma once
#include "esp_bit_defs.h"
#include "soc/dport_reg.h"
static inline void trace_ll_set_mem_block(int block)
{
DPORT_WRITE_PERI_REG(DPORT_PMS_OCCUPY_3_REG, BIT(block-4));
}

View File

@@ -0,0 +1,24 @@
// 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.
#pragma once
#include <stdlib.h>
#include "soc/dport_reg.h"
static inline void trace_ll_set_mem_block(int block)
{
// IDF-1785
abort();
}

View File

@@ -167,7 +167,7 @@ lwip_hook_tcp_isn(const ip_addr_t *local_ip, u16_t local_port,
* APIs should not create any issues.
*/
#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
assert(!esp_ptr_external_ram(get_sp()));
assert(!esp_ptr_external_ram(esp_cpu_get_sp()));
#endif
struct MD5Context ctx;

View File

@@ -15,6 +15,7 @@ set(srcs
"newlib_init.c"
"syscalls.c"
"termios.c"
"stdatomic.c"
"time.c")
set(include_dirs platform_include)

View File

@@ -3,3 +3,4 @@ archive: libnewlib.a
entries:
heap (noflash)
abort (noflash)
stdatomic (noflash)

View File

@@ -16,13 +16,13 @@
#include "sdkconfig.h"
#include <stdbool.h>
#include <stdint.h>
#ifdef __XTENSA__
#include "xtensa/config/core-isa.h"
#include "xtensa/xtruntime.h"
//reserved to measure atomic operation time
#define atomic_benchmark_intr_disable()
#define atomic_benchmark_intr_restore(STATE)
// This allows nested interrupts disabling and restoring via local registers or stack.
// They can be called from interrupts too.
// WARNING: Only applies to current CPU.
@@ -37,6 +37,38 @@
XTOS_RESTORE_JUST_INTLEVEL(state); \
} while (0)
#ifndef XCHAL_HAVE_S32C1I
#error "XCHAL_HAVE_S32C1I not defined, include correct header!"
#endif
#define NO_ATOMICS_SUPPORT (XCHAL_HAVE_S32C1I == 0)
#else // RISCV
#include "freertos/portmacro.h"
// This allows nested interrupts disabling and restoring via local registers or stack.
// They can be called from interrupts too.
// WARNING: Only applies to current CPU.
#define _ATOMIC_ENTER_CRITICAL(void) ({ \
unsigned state = portENTER_CRITICAL_NESTED(); \
atomic_benchmark_intr_disable(); \
state; \
})
#define _ATOMIC_EXIT_CRITICAL(state) do { \
atomic_benchmark_intr_restore(state); \
portEXIT_CRITICAL_NESTED(state); \
} while (0)
#define NO_ATOMICS_SUPPORT 1 // [todo] Get the equivalent XCHAL_HAVE_S32C1I check for RISCV
#endif
//reserved to measure atomic operation time
#define atomic_benchmark_intr_disable()
#define atomic_benchmark_intr_restore(STATE)
#define CMP_EXCHANGE(n, type) bool __atomic_compare_exchange_ ## n (type* mem, type* expect, type desired, int success, int failure) \
{ \
bool ret = false; \
@@ -96,15 +128,10 @@
return ret; \
}
#ifndef XCHAL_HAVE_S32C1I
#error "XCHAL_HAVE_S32C1I not defined, include correct header!"
#endif
//this piece of code should only be compiled if the cpu doesn't support atomic compare and swap (s32c1i)
#if XCHAL_HAVE_S32C1I == 0
#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
#if NO_ATOMICS_SUPPORT
CMP_EXCHANGE(1, uint8_t)
CMP_EXCHANGE(2, uint16_t)
CMP_EXCHANGE(4, uint32_t)

View File

@@ -14,9 +14,9 @@ static StackType_t *shared_stack_sp = NULL;
void external_stack_function(void)
{
printf("Executing this printf from external stack! sp=%p\n", get_sp());
printf("Executing this printf from external stack! sp=%p\n", esp_cpu_get_sp());
shared_stack_sp = (StackType_t *)get_sp();
shared_stack_sp = (StackType_t *)esp_cpu_get_sp();
char *res = NULL;
/* Test return value from asprintf, this could potentially help catch a misaligned
@@ -30,9 +30,9 @@ void external_stack_function(void)
void another_external_stack_function(void)
{
//We can even use Freertos resources inside of this context.
printf("We can even use FreeRTOS resources... yielding, sp=%p\n", get_sp());
printf("We can even use FreeRTOS resources... yielding, sp=%p\n", esp_cpu_get_sp());
taskYIELD();
shared_stack_sp = (StackType_t *)get_sp();
shared_stack_sp = (StackType_t *)esp_cpu_get_sp();
}
TEST_CASE("test printf using shared buffer stack", "[newlib]")
@@ -43,7 +43,7 @@ TEST_CASE("test printf using shared buffer stack", "[newlib]")
SemaphoreHandle_t printf_lock = xSemaphoreCreateMutex();
TEST_ASSERT_NOT_NULL(printf_lock);
printf("current task sp: %p\n", get_sp());
printf("current task sp: %p\n", esp_cpu_get_sp());
printf("shared_stack: %p\n", (void *)shared_stack);
printf("shared_stack expected top: %p\n", (void *)(shared_stack + SHARED_STACK_SIZE));

View File

@@ -1,17 +1,16 @@
idf_build_get_property(target IDF_TARGET)
if(NOT "${target}" STREQUAL "esp32c3")
return()
endif()
if(BOOTLOADER_BUILD)
set(priv_requires soc)
else()
set(priv_requires soc freertos)
set(srcs
"expression_with_stack_riscv.c"
"expression_with_stack_riscv_asm.S"
"instruction_decode.c"
"interrupt.c"
"stdatomic.c"
"vectors.S")
endif()

View File

@@ -1,131 +0,0 @@
// Copyright 2015-2016 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_ATTR_H__
#define __ESP_ATTR_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "sdkconfig.h"
#define ROMFN_ATTR
//Normally, the linker script will put all code and rodata in flash,
//and all variables in shared RAM. These macros can be used to redirect
//particular functions/variables to other memory regions.
// Forces code into IRAM instead of flash
#define IRAM_ATTR _SECTION_ATTR_IMPL(".iram1", __COUNTER__)
// Forces data into DRAM instead of flash
#define DRAM_ATTR _SECTION_ATTR_IMPL(".dram1", __COUNTER__)
// Forces data to be 4 bytes aligned
#define WORD_ALIGNED_ATTR __attribute__((aligned(4)))
// Forces data to be placed to DMA-capable places
#define DMA_ATTR WORD_ALIGNED_ATTR DRAM_ATTR
// Forces a function to be inlined
#define FORCE_INLINE_ATTR static inline __attribute__((always_inline))
// Forces a string into DRAM instead of flash
// Use as ets_printf(DRAM_STR("Hello world!\n"));
#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;}))
// Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst"
#define RTC_IRAM_ATTR _SECTION_ATTR_IMPL(".rtc.text", __COUNTER__)
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
// Forces bss variable into external memory. "
#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__)
#else
#define EXT_RAM_ATTR
#endif
// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst"
// Any variable marked with this attribute will keep its value
// during a deep sleep / wake cycle.
#define RTC_DATA_ATTR _SECTION_ATTR_IMPL(".rtc.data", __COUNTER__)
// Forces read-only data into RTC memory. See "docs/deep-sleep-stub.rst"
#define RTC_RODATA_ATTR _SECTION_ATTR_IMPL(".rtc.rodata", __COUNTER__)
// Allows to place data into RTC_SLOW memory.
#define RTC_SLOW_ATTR _SECTION_ATTR_IMPL(".rtc.force_slow", __COUNTER__)
// Allows to place data into RTC_FAST memory.
#define RTC_FAST_ATTR _SECTION_ATTR_IMPL(".rtc.force_fast", __COUNTER__)
// Forces data into noinit section to avoid initialization after restart.
#define __NOINIT_ATTR _SECTION_ATTR_IMPL(".noinit", __COUNTER__)
// Forces data into RTC slow memory of .noinit section.
// Any variable marked with this attribute will keep its value
// after restart or during a deep sleep / wake cycle.
#define RTC_NOINIT_ATTR _SECTION_ATTR_IMPL(".rtc_noinit", __COUNTER__)
// Forces to not inline function
#define NOINLINE_ATTR __attribute__((noinline))
// This allows using enum as flags in C++
// Format: FLAG_ATTR(flag_enum_t)
#ifdef __cplusplus
// Inline is required here to avoid multiple definition error in linker
#define FLAG_ATTR_IMPL(TYPE, INT_TYPE) \
FORCE_INLINE_ATTR constexpr TYPE operator~ (TYPE a) { return (TYPE)~(INT_TYPE)a; } \
FORCE_INLINE_ATTR constexpr TYPE operator| (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a | (INT_TYPE)b); } \
FORCE_INLINE_ATTR constexpr TYPE operator& (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a & (INT_TYPE)b); } \
FORCE_INLINE_ATTR constexpr TYPE operator^ (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a ^ (INT_TYPE)b); } \
FORCE_INLINE_ATTR constexpr TYPE operator>> (TYPE a, int b) { return (TYPE)((INT_TYPE)a >> b); } \
FORCE_INLINE_ATTR constexpr TYPE operator<< (TYPE a, int b) { return (TYPE)((INT_TYPE)a << b); } \
FORCE_INLINE_ATTR TYPE& operator|=(TYPE& a, TYPE b) { a = a | b; return a; } \
FORCE_INLINE_ATTR TYPE& operator&=(TYPE& a, TYPE b) { a = a & b; return a; } \
FORCE_INLINE_ATTR TYPE& operator^=(TYPE& a, TYPE b) { a = a ^ b; return a; } \
FORCE_INLINE_ATTR TYPE& operator>>=(TYPE& a, int b) { a >>= b; return a; } \
FORCE_INLINE_ATTR TYPE& operator<<=(TYPE& a, int b) { a <<= b; return a; }
#define FLAG_ATTR_U32(TYPE) FLAG_ATTR_IMPL(TYPE, uint32_t)
#define FLAG_ATTR FLAG_ATTR_U32
#else
#define FLAG_ATTR(TYPE)
#endif
// Implementation for a unique custom section
//
// This prevents gcc producing "x causes a section type conflict with y"
// errors if two variables in the same source file have different linkage (maybe const & non-const) but are placed in the same custom section
//
// Using unique sections also means --gc-sections can remove unused
// data with a custom section type set
#define _SECTION_ATTR_IMPL(SECTION, COUNTER) __attribute__((section(SECTION "." _COUNTER_STRINGIFY(COUNTER))))
#define _COUNTER_STRINGIFY(COUNTER) #COUNTER
/* Use IDF_DEPRECATED attribute to mark anything deprecated from use in
ESP-IDF's own source code, but not deprecated for external users.
*/
#ifdef IDF_CI_BUILD
#define IDF_DEPRECATED(REASON) __attribute__((deprecated(REASON)))
#else
#define IDF_DEPRECATED(REASON)
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ESP_ATTR_H__ */

View File

@@ -1,133 +0,0 @@
// Copyright 2015-2019 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
#ifndef __ASSEMBLER__
#include <stdbool.h>
#include "esp_err.h"
#include "soc/soc.h"
#define ESP_WATCHPOINT_LOAD 0x40000000
#define ESP_WATCHPOINT_STORE 0x80000000
#define ESP_WATCHPOINT_ACCESS 0xC0000000
/*
* @brief Structure used for backtracing
*
* This structure stores the backtrace information of a particular stack frame
* (i.e. the PC and SP). This structure is used iteratively with the
* esp_cpu_get_next_backtrace_frame() function to traverse each frame within a
* single stack. The next_pc represents the PC of the current frame's caller, thus
* a next_pc of 0 indicates that the current frame is the last frame on the stack.
*
* @note Call esp_backtrace_get_start() to obtain initialization values for
* this structure
*/
typedef struct {
uint32_t pc; /* PC of the current frame */
uint32_t sp; /* SP of the current frame */
uint32_t next_pc; /* PC of the current frame's caller */
} esp_backtrace_frame_t;
/**
* @brief If an OCD is connected over JTAG. set breakpoint 0 to the given function
* address. Do nothing otherwise.
* @param fn Pointer to the target breakpoint position
*/
void esp_set_breakpoint_if_jtag(void *fn);
/**
* @brief Set a watchpoint to break/panic when a certain memory range is accessed.
*
* @param no Watchpoint number. On the ESP32, this can be 0 or 1.
* @param adr Base address to watch
* @param size Size of the region, starting at the base address, to watch. Must
* be one of 2^n, with n in [0..6].
* @param flags One of ESP_WATCHPOINT_* flags
*
* @return ESP_ERR_INVALID_ARG on invalid arg, ESP_OK otherwise
*
* @warning The ESP32 watchpoint hardware watches a region of bytes by effectively
* masking away the lower n bits for a region with size 2^n. If adr does
* not have zero for these lower n bits, you may not be watching the
* region you intended.
*/
esp_err_t esp_set_watchpoint(int no, void *adr, int size, int flags);
/**
* @brief Clear a watchpoint
*
* @param no Watchpoint to clear
*
*/
void esp_clear_watchpoint(int no);
/**
* Get the first frame of the current stack's backtrace
*
* Given the following function call flow (B -> A -> X -> esp_backtrace_get_start),
* this function will do the following.
* - Flush CPU registers and window frames onto the current stack
* - Return PC and SP of function A (i.e. start of the stack's backtrace)
* - Return PC of function B (i.e. next_pc)
*
* @note This function is implemented in assembly
*
* @param[out] pc PC of the first frame in the backtrace
* @param[out] sp SP of the first frame in the backtrace
* @param[out] next_pc PC of the first frame's caller
*/
extern void esp_backtrace_get_start(uint32_t *pc, uint32_t *sp, uint32_t *next_pc);
/**
* Get the next frame on a stack for backtracing
*
* Given a stack frame(i), this function will obtain the next stack frame(i-1)
* on the same call stack (i.e. the caller of frame(i)). This function is meant to be
* called iteratively when doing a backtrace.
*
* Entry Conditions: Frame structure containing valid SP and next_pc
* Exit Conditions:
* - Frame structure updated with SP and PC of frame(i-1). next_pc now points to frame(i-2).
* - If a next_pc of 0 is returned, it indicates that frame(i-1) is last frame on the stack
*
* @param[inout] frame Pointer to frame structure
*
* @return
* - True if the SP and PC of the next frame(i-1) are sane
* - False otherwise
*/
bool esp_backtrace_get_next_frame(esp_backtrace_frame_t *frame);
/**
* @brief Print the backtrace of the current stack
*
* @param depth The maximum number of stack frames to print (should be > 0)
*
* @return
* - ESP_OK Backtrace successfully printed to completion or to depth limit
* - ESP_FAIL Backtrace is corrupted
*/
esp_err_t esp_backtrace_print(int depth);
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -3,4 +3,3 @@ archive: libriscv.a
entries:
interrupt (noflash_text)
vectors (noflash_text)
stdatomic (noflash_text)

View File

@@ -1,129 +0,0 @@
// Copyright 2015-2019 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.
//replacement for gcc built-in functions
#include "sdkconfig.h"
#include <stdbool.h>
#include <stdint.h>
#include "freertos/portmacro.h"
//reserved to measure atomic operation time
#define atomic_benchmark_intr_disable()
#define atomic_benchmark_intr_restore(STATE)
// This allows nested interrupts disabling and restoring via local registers or stack.
// They can be called from interrupts too.
// WARNING: Only applies to current CPU.
#define _ATOMIC_ENTER_CRITICAL(void) ({ \
unsigned state = portENTER_CRITICAL_NESTED(); \
atomic_benchmark_intr_disable(); \
state; \
})
#define _ATOMIC_EXIT_CRITICAL(state) do { \
atomic_benchmark_intr_restore(state); \
portEXIT_CRITICAL_NESTED(state); \
} while (0)
#define CMP_EXCHANGE(n, type) bool __atomic_compare_exchange_ ## n (type* mem, type* expect, type desired, int success, int failure) \
{ \
bool ret = false; \
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
if (*mem == *expect) { \
ret = true; \
*mem = desired; \
} else { \
*expect = *mem; \
} \
_ATOMIC_EXIT_CRITICAL(state); \
return ret; \
}
#define FETCH_ADD(n, type) type __atomic_fetch_add_ ## n (type* ptr, type value, int memorder) \
{ \
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
type ret = *ptr; \
*ptr = *ptr + value; \
_ATOMIC_EXIT_CRITICAL(state); \
return ret; \
}
#define FETCH_SUB(n, type) type __atomic_fetch_sub_ ## n (type* ptr, type value, int memorder) \
{ \
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
type ret = *ptr; \
*ptr = *ptr - value; \
_ATOMIC_EXIT_CRITICAL(state); \
return ret; \
}
#define FETCH_AND(n, type) type __atomic_fetch_and_ ## n (type* ptr, type value, int memorder) \
{ \
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
type ret = *ptr; \
*ptr = *ptr & value; \
_ATOMIC_EXIT_CRITICAL(state); \
return ret; \
}
#define FETCH_OR(n, type) type __atomic_fetch_or_ ## n (type* ptr, type value, int memorder) \
{ \
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
type ret = *ptr; \
*ptr = *ptr | value; \
_ATOMIC_EXIT_CRITICAL(state); \
return ret; \
}
#define FETCH_XOR(n, type) type __atomic_fetch_xor_ ## n (type* ptr, type value, int memorder) \
{ \
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
type ret = *ptr; \
*ptr = *ptr ^ value; \
_ATOMIC_EXIT_CRITICAL(state); \
return ret; \
}
#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
CMP_EXCHANGE(1, uint8_t)
CMP_EXCHANGE(2, uint16_t)
CMP_EXCHANGE(4, uint32_t)
CMP_EXCHANGE(8, uint64_t)
FETCH_ADD(1, uint8_t)
FETCH_ADD(2, uint16_t)
FETCH_ADD(4, uint32_t)
FETCH_ADD(8, uint64_t)
FETCH_SUB(1, uint8_t)
FETCH_SUB(2, uint16_t)
FETCH_SUB(4, uint32_t)
FETCH_SUB(8, uint64_t)
FETCH_AND(1, uint8_t)
FETCH_AND(2, uint16_t)
FETCH_AND(4, uint32_t)
FETCH_AND(8, uint64_t)
FETCH_OR(1, uint8_t)
FETCH_OR(2, uint16_t)
FETCH_OR(4, uint32_t)
FETCH_OR(8, uint64_t)
FETCH_XOR(1, uint8_t)
FETCH_XOR(2, uint16_t)
FETCH_XOR(4, uint32_t)
FETCH_XOR(8, uint64_t)

View File

@@ -4281,4 +4281,9 @@
#define DPORT_MMU_ADDRESS_MASK 0xff
#define TRACEMEM_MUX_PROBLK0_APPBLK1 0
#define TRACEMEM_MUX_BLK0_ONLY 1
#define TRACEMEM_MUX_BLK1_ONLY 2
#define TRACEMEM_MUX_PROBLK1_APPBLK0 3
#endif /*_SOC_DPORT_REG_H_ */

View File

@@ -25,6 +25,10 @@ extern "C" {
#define DPORT_DATE_REG SYSTEM_DATE_REG
#define TRACEMEM_MUX_BLK0_NUM 19
#define TRACEMEM_MUX_BLK1_NUM 20
#define TRACEMEM_BLK_NUM2ADDR(_n_) (0x3FFB8000UL + 0x4000UL*((_n_)-4))
#ifndef __ASSEMBLER__
#include "dport_access.h"
#endif

View File

@@ -1291,6 +1291,4 @@ extern "C" {
}
#endif
#endif /*_SOC_SENSITIVE_REG_H_ */

View File

@@ -24,6 +24,10 @@ extern "C" {
#define DPORT_DATE_REG SYSTEM_DATE_REG
#define TRACEMEM_MUX_BLK0_NUM 19
#define TRACEMEM_MUX_BLK1_NUM 20
#define TRACEMEM_BLK_NUM2ADDR(_n_) (0x3FFB8000UL + 0x4000UL*((_n_)-4))
#ifndef __ASSEMBLER__
#include "dport_access.h"
#endif

View File

@@ -125,7 +125,7 @@ void IRAM_ATTR spi_flash_op_block_func(void *arg)
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void)
{
assert(esp_ptr_in_dram((const void *)get_sp()));
assert(esp_ptr_in_dram((const void *)esp_cpu_get_sp()));
spi_flash_op_lock();

View File

@@ -1,33 +1,17 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "esp32c3")
if("${target}" STREQUAL "esp32c3")
return()
endif()
if(BOOTLOADER_BUILD)
# bootloader only needs headers from this component
set(priv_requires soc)
else()
set(priv_requires soc freertos)
set(srcs "debug_helpers.c"
"debug_helpers_asm.S"
"expression_with_stack_xtensa.c"
"expression_with_stack_xtensa_asm.S"
"eri.c"
"trax.c"
"xtensa_intr.c"
"xtensa_intr_asm.S"
"${target}/trax_init.c"
)
if(IDF_TARGET STREQUAL "esp32s2")
list(APPEND srcs "stdatomic.c")
endif()
set(srcs "eri.c" "xt_trax.c")
if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "xtensa_intr.c" "xtensa_intr_asm.S")
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS include ${target}/include
LDFRAGMENTS linker.lf
PRIV_REQUIRES ${priv_requires})
LDFRAGMENTS linker.lf)
if(NOT BOOTLOADER_BUILD)
target_link_libraries(${COMPONENT_LIB} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/${target}/libxt_hal.a")
endif()
target_link_libraries(${COMPONENT_LIB} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/${target}/libxt_hal.a")

View File

@@ -1,46 +0,0 @@
// 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 <stdio.h>
#include "esp_err.h"
#include "esp_log.h"
#include "trax.h"
#include "soc/dport_reg.h"
#include "sdkconfig.h"
#define TRACEMEM_MUX_PROBLK0_APPBLK1 0
#define TRACEMEM_MUX_BLK0_ONLY 1
#define TRACEMEM_MUX_BLK1_ONLY 2
#define TRACEMEM_MUX_PROBLK1_APPBLK0 3
static const char* __attribute__((unused)) TAG = "trax";
int trax_enable(trax_ena_select_t which)
{
#ifndef CONFIG_ESP32_TRAX
ESP_LOGE(TAG, "Trax_enable called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
#ifndef CONFIG_ESP32_TRAX_TWOBANKS
if (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP) return ESP_ERR_NO_MEM;
#endif
if (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP) {
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, (which == TRAX_ENA_PRO_APP_SWAP)?TRACEMEM_MUX_PROBLK1_APPBLK0:TRACEMEM_MUX_PROBLK0_APPBLK1);
} else {
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, TRACEMEM_MUX_BLK0_ONLY);
}
DPORT_WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP || which == TRAX_ENA_PRO));
DPORT_WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, (which == TRAX_ENA_PRO_APP || which == TRAX_ENA_PRO_APP_SWAP || which == TRAX_ENA_APP));
return ESP_OK;
}

View File

@@ -1,38 +0,0 @@
// 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 <stdio.h>
#include "esp_err.h"
#include "esp_log.h"
#include "trax.h"
#include "soc/sensitive_reg.h"
#include "sdkconfig.h"
#define TRACEMEM_MUX_BLK0_NUM 19
#define TRACEMEM_MUX_BLK1_NUM 20
static const char* __attribute__((unused)) TAG = "trax";
int trax_enable(trax_ena_select_t which)
{
#ifndef CONFIG_ESP32S2_TRAX
ESP_LOGE(TAG, "Trax_enable called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
if (which != TRAX_ENA_PRO) {
return ESP_ERR_INVALID_ARG;
}
REG_WRITE(DPORT_PMS_OCCUPY_3_REG, BIT(TRACEMEM_MUX_BLK1_NUM-4));
return ESP_OK;
}

View File

@@ -1,40 +0,0 @@
// 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 <stdio.h>
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "trax.h"
#include "soc/sensitive_reg.h"
#include "sdkconfig.h"
#define TRACEMEM_MUX_BLK0_NUM 19
#define TRACEMEM_MUX_BLK1_NUM 20
static const char *__attribute__((unused)) TAG = "trax";
// IDF-1785
int trax_enable(trax_ena_select_t which)
{
#ifndef CONFIG_ESP32S3_TRAX
ESP_LOGE(TAG, "Trax_enable called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
if (which != TRAX_ENA_PRO) {
return ESP_ERR_INVALID_ARG;
}
// REG_WRITE(DPORT_PMS_OCCUPY_3_REG, BIT(TRACEMEM_MUX_BLK1_NUM-4));
return ESP_OK;
}

View File

@@ -0,0 +1,54 @@
// Copyright 2015-2016 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 <stdbool.h>
#include "eri.h"
#include "xtensa-debug-module.h"
// Low-level Xtensa TRAX utils
/**
* @brief Start a Trax trace on the current CPU with instructions as unit of delay.
* Memory blocks to be used as Trax memory must be enabled before
* calling this function, if needed.
*/
void xt_trax_start_trace_instructions(void);
/**
* @brief Start a Trax trace on the current CPU with words as unit of delay.
* Memory blocks to be used as Trax memory must be enabled before
* calling this function, if needed.
*/
void xt_trax_start_trace_words(void);
/**
* @brief Check if Trax trace is active on current CPU.
*
* @return bool. Return true if trace is active.
*/
bool xt_trax_trace_is_active(void);
/**
* @brief Trigger a Trax trace stop after the indicated delay. If this is called
* before and the previous delay hasn't ended yet, this will overwrite
* that delay with the new value. The delay will always start at the time
* the function is called.
*
* @param delay : The delay to stop the trace in, in the unit indicated to
* trax_start_trace. Note: the trace memory has 4K words available.
*/
void xt_trax_trigger_traceend_after_delay(int delay);

View File

@@ -2,8 +2,6 @@
archive: libxtensa.a
entries:
eri (noflash_text)
if IDF_TARGET_ESP32S2 = y:
stdatomic (noflash)
[mapping:xt_hal]
archive: libxt_hal.a

View File

@@ -13,51 +13,44 @@
// limitations under the License.
#include <stdio.h>
#include "esp_log.h"
#include <stdbool.h>
#include "esp_err.h"
#include "xtensa-debug-module.h"
#include "eri.h"
#include "trax.h"
#include "sdkconfig.h"
#if defined(CONFIG_ESP32_TRAX) || defined(CONFIG_ESP32S2_TRAX)
#define WITH_TRAX 1
#endif
static const char* TAG = "trax";
int trax_start_trace(trax_downcount_unit_t units_until_stop)
bool xt_trax_trace_is_active(void)
{
return eri_read(ERI_TRAX_TRAXSTAT)&TRAXSTAT_TRACT;
}
static void _xt_trax_start_trace(bool instructions)
{
#if !WITH_TRAX
ESP_EARLY_LOGE(TAG, "Trax_start_trace called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
uint32_t v;
if (eri_read(ERI_TRAX_TRAXSTAT)&TRAXSTAT_TRACT) {
ESP_EARLY_LOGI(TAG, "Stopping active trace first.");
//Trace is active. Stop trace.
eri_write(ERI_TRAX_DELAYCNT, 0);
eri_write(ERI_TRAX_TRAXCTRL, eri_read(ERI_TRAX_TRAXCTRL)|TRAXCTRL_TRSTP);
//ToDo: This will probably trigger a trace done interrupt. ToDo: Fix, but how? -JD
eri_write(ERI_TRAX_TRAXCTRL, 0);
}
eri_write(ERI_TRAX_PCMATCHCTRL, 31); //do not stop at any pc match
v=TRAXCTRL_TREN | TRAXCTRL_TMEN | TRAXCTRL_PTOWS | (1<<TRAXCTRL_SMPER_SHIFT);
if (units_until_stop == TRAX_DOWNCOUNT_INSTRUCTIONS) v|=TRAXCTRL_CNTU;
if (instructions) {
v|=TRAXCTRL_CNTU;
}
//Enable trace. This trace has no stop condition and will just keep on running.
eri_write(ERI_TRAX_TRAXCTRL, v);
return ESP_OK;
}
int trax_trigger_traceend_after_delay(int delay)
void xt_trax_start_trace_instructions(void)
{
_xt_trax_start_trace(true);
}
void xt_trax_start_trace_words(void)
{
_xt_trax_start_trace(false);
}
void xt_trax_trigger_traceend_after_delay(int delay)
{
#if !WITH_TRAX
ESP_EARLY_LOGE(TAG, "Trax_trigger_traceend_after_delay called, but trax is disabled in menuconfig!");
return ESP_ERR_NO_MEM;
#endif
eri_write(ERI_TRAX_DELAYCNT, delay);
eri_write(ERI_TRAX_TRAXCTRL, eri_read(ERI_TRAX_TRAXCTRL)|TRAXCTRL_TRSTP);
return ESP_OK;
//ToDo: This will probably trigger a trace done interrupt. ToDo: Fix, but how? -JD
eri_write(ERI_TRAX_TRAXCTRL, 0);
}

View File

@@ -80,7 +80,7 @@ Memory corruption can be one of the hardest classes of bugs to find and fix, as
- Increasing the Heap memory debugging `Configuration`_ level to "Light impact" or "Comprehensive" can give you a more accurate message with the first corrupt memory address.
- Adding regular calls to :cpp:func:`heap_caps_check_integrity_all` or :cpp:func:`heap_caps_check_integrity_addr` in your code will help you pin down the exact time that the corruption happened. You can move these checks around to "close in on" the section of code that corrupted the heap.
- Based on the memory address which is being corrupted, you can use :ref:`JTAG debugging <jtag-debugging-introduction>` to set a watchpoint on this address and have the CPU halt when it is written to.
- If you don't have JTAG, but you do know roughly when the corruption happens, then you can set a watchpoint in software just beforehand via :cpp:func:`esp_set_watchpoint`. A fatal exception will occur when the watchpoint triggers. For example ``esp_set_watchpoint(0, (void *)addr, 4, ESP_WATCHPOINT_STORE``. Note that watchpoints are per-CPU and are set on the current running CPU only, so if you don't know which CPU is corrupting memory then you will need to call this function on both CPUs.
- If you don't have JTAG, but you do know roughly when the corruption happens, then you can set a watchpoint in software just beforehand via :cpp:func:`esp_cpu_set_watchpoint`. A fatal exception will occur when the watchpoint triggers. For example ``esp_cpu_set_watchpoint(0, (void *)addr, 4, ESP_WATCHPOINT_STORE``. Note that watchpoints are per-CPU and are set on the current running CPU only, so if you don't know which CPU is corrupting memory then you will need to call this function on both CPUs.
- For buffer overflows, `heap tracing`_ in ``HEAP_TRACE_ALL`` mode lets you see which callers are allocating which addresses from the heap. See `Heap Tracing To Find Heap Corruption`_ for more details. If you can find the function which allocates memory with an address immediately before the address which is corrupted, this will probably be the function which overflows the buffer.
- Calling :cpp:func:`heap_caps_dump` or :cpp:func:`heap_caps_dump_all` can give an indication of what heap blocks are surrounding the corrupted region and may have overflowed/underflowed/etc.