forked from espressif/esp-idf
esp_hw_support: create esp_cpu
Create a esp_cpu header that contains CPU-related functions and utilities.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
@@ -400,7 +400,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";
|
||||
|
@@ -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.
|
||||
|
@@ -13,7 +13,7 @@ endif()
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS include
|
||||
REQUIRES ${requires}
|
||||
PRIV_REQUIRES efuse esp_system
|
||||
PRIV_REQUIRES efuse
|
||||
LDFRAGMENTS linker.lf)
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
@@ -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)
|
||||
|
109
components/esp_hw_support/include/esp_cpu.h
Normal file
109
components/esp_hw_support/include/esp_cpu.h
Normal 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
|
@@ -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
|
||||
*
|
||||
|
@@ -8,8 +8,7 @@ endif()
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
# Bootloader relies on some Kconfig options defined in esp_system.
|
||||
idf_component_register( INCLUDE_DIRS include
|
||||
SRCS "${srcs}")
|
||||
idf_component_register(SRCS "${srcs}")
|
||||
else()
|
||||
list(APPEND srcs "esp_err.c"
|
||||
"freertos_hooks.c"
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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) { };
|
||||
|
@@ -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 */
|
||||
|
@@ -309,7 +309,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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
@@ -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));
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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.
|
||||
|
||||
|
Reference in New Issue
Block a user