espcoredump: code refactoring and add support for RISC-V implemetation
This commit includes the refactoring of the core dump feature. Thanks to this refactoring, it is easier to integrate the support of RISC-V architecture for this feature. Fixes ESP-1758
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// 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_CORE_DUMP_BINARY_H_
|
||||
#define ESP_CORE_DUMP_BINARY_H_
|
||||
|
||||
#include "esp_core_dump_types.h"
|
||||
|
||||
/**
|
||||
* @brief Initiate the binary core dump generation.
|
||||
*
|
||||
* @param info Exception frame info generated when the panic occured.
|
||||
* @param write_cfg Structure containing the callbacks that will be called to
|
||||
* write the generated core dump file.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise \see esp_err_t.
|
||||
*/
|
||||
esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,117 @@
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Core dump checksum interface.
|
||||
*
|
||||
* This file contains all the functions required by the core dump component to
|
||||
* calculate checksums for data to write (or already written) on the flash.
|
||||
* Currently, both CRC32 and SHA256 are supported, but this interface is
|
||||
* implementation independent.
|
||||
*/
|
||||
|
||||
#ifndef CORE_DUMP_CHECKSUM_H_
|
||||
#define CORE_DUMP_CHECKSUM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum possible length for a checksum (regardless of the
|
||||
* implentation). This can be modified in the future if a new implementation
|
||||
* requires a larger size.
|
||||
*/
|
||||
#define COREDUMP_CHECKSUM_MAX_LEN 32
|
||||
|
||||
/**
|
||||
* @brief Type describing a checksum context. It is an abstract type as it is
|
||||
* implementation independent, it is defined in the C source counterpart.
|
||||
*/
|
||||
typedef struct core_dump_checksum_ctx core_dump_checksum_ctx;
|
||||
|
||||
/**
|
||||
* @brief Type returned by `esp_core_dump_checksum_finish()`. It describes a
|
||||
* checksum as an array of bytes. It can also be provided to `esp_core_dump_print_checksum()`.
|
||||
*/
|
||||
typedef uint8_t* core_dump_checksum_bytes;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get ELF core dump version.
|
||||
*
|
||||
* @note Currently, this is used in the core dump header to recognize the
|
||||
* checksum used for a certain dump, as the version varies with the checksum.
|
||||
*
|
||||
* @return Version of the core dump used.
|
||||
*/
|
||||
uint32_t esp_core_dump_elf_version(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize checksum calculation for the given context.
|
||||
*
|
||||
* @param wr_data Core dump checksum context to fill.
|
||||
*/
|
||||
void esp_core_dump_checksum_init(core_dump_checksum_ctx** wr_data);
|
||||
|
||||
/**
|
||||
* @brief Update checksum calculation by integrating the given data in the context.
|
||||
*
|
||||
* @param wr_data Core dump checksum context.
|
||||
* @param data Pointer to the data to integrate in the checksum calculation.
|
||||
* This is usually the new data to write (or already written) on
|
||||
* the flash.
|
||||
*/
|
||||
void esp_core_dump_checksum_update(core_dump_checksum_ctx* wr_data, void* data, size_t data_len);
|
||||
|
||||
/**
|
||||
* @brief Terminate and return checksum calculated for the given context.
|
||||
*
|
||||
* @param wr_data Core dump checksum context. It can be NULL only if chs_ptr is
|
||||
* also NULL.
|
||||
* @param chs_ptr Pointer used to return the checksum calculated. It can be
|
||||
* NULL, in this case, it will be ignored but the correct size
|
||||
* of the checksum will be returned.
|
||||
*
|
||||
* @return The size, in bytes, of the checksum.
|
||||
*/
|
||||
uint32_t esp_core_dump_checksum_finish(core_dump_checksum_ctx* wr_data, core_dump_checksum_bytes* chs_ptr);
|
||||
|
||||
/**
|
||||
* @brief Return the size of the checksums.
|
||||
*
|
||||
* @note This is equivalent to `esp_core_dump_checksum_finish(NULL, NULL)`.
|
||||
*
|
||||
* @return The size, in bytes, of the checksums.
|
||||
*/
|
||||
uint32_t esp_core_dump_checksum_size(void);
|
||||
|
||||
/**
|
||||
* @brief Print a message followed by the checksum given as a parameter.
|
||||
*
|
||||
* @note The checksum will be printed in hex format and followed by \r\n.
|
||||
*
|
||||
* @param msg Message to print before the checksum. Can be NULL.
|
||||
* @param checksum Checksum to print. Must not be NULL.
|
||||
*/
|
||||
void esp_core_dump_print_checksum(const char* msg, core_dump_checksum_bytes checksum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,8 +14,17 @@
|
||||
#ifndef ESP_CORE_DUMP_ELF_H_
|
||||
#define ESP_CORE_DUMP_ELF_H_
|
||||
|
||||
#include "esp_core_dump_priv.h"
|
||||
#include "esp_core_dump_types.h"
|
||||
|
||||
/**
|
||||
* @brief Initiate the ELF core dump generation.
|
||||
*
|
||||
* @param info Exception frame info generated when the panic occured.
|
||||
* @param write_cfg Structre containing the callbacks that will be called to
|
||||
* write the generated core dump data.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise \see esp_err_t.
|
||||
*/
|
||||
esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
// 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.
|
||||
#ifndef ESP_CORE_DUMP_COMMON_H_
|
||||
#define ESP_CORE_DUMP_COMMON_H_
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "esp_debug_helpers.h"
|
||||
#include "esp_app_format.h"
|
||||
#include "esp_core_dump_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enumeration of the existing memory regions.
|
||||
* One can use these definitions to retrieve the start address and/or the size
|
||||
* of a specific region using the functions below.
|
||||
*/
|
||||
typedef enum {
|
||||
COREDUMP_MEMORY_DRAM,
|
||||
COREDUMP_MEMORY_IRAM,
|
||||
COREDUMP_MEMORY_RTC,
|
||||
COREDUMP_MEMORY_RTC_FAST,
|
||||
COREDUMP_MEMORY_MAX,
|
||||
COREDUMP_MEMORY_START = COREDUMP_MEMORY_DRAM
|
||||
} coredump_region_t;
|
||||
|
||||
/**
|
||||
* @brief Get the (FreeRTOS) task handle for the current task.
|
||||
*
|
||||
* @return Task handle of the current task.
|
||||
*/
|
||||
core_dump_task_handle_t esp_core_dump_get_current_task_handle(void);
|
||||
|
||||
/**
|
||||
* @brief Get next task handle of a given handle.
|
||||
*
|
||||
* @param handle Task handle to get the next handle from.
|
||||
*
|
||||
* @return Next task handle.
|
||||
*/
|
||||
core_dump_task_handle_t esp_core_dump_get_next_task(core_dump_task_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Get a task snapshot from a given handle.
|
||||
*
|
||||
* @param handle Task handle to get the snapshot from.
|
||||
* @param task Returned task header.
|
||||
* @param interrupted_stack Backup of the task stack if the handle passed is the task
|
||||
* that crashed and if it crashed within an ISR context.
|
||||
*
|
||||
* @return false is the task is broken, true else.
|
||||
*/
|
||||
bool esp_core_dump_get_task_snapshot(core_dump_task_handle_t handle,
|
||||
core_dump_task_header_t *task,
|
||||
core_dump_mem_seg_header_t *interrupted_stack);
|
||||
|
||||
/**
|
||||
* @brief Reset tasks snapshot iterator.
|
||||
*/
|
||||
void esp_core_dump_reset_tasks_snapshots_iter(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if the TCB passed as a parameter is sane.
|
||||
*
|
||||
* @param address Address of the TCB to check.
|
||||
*
|
||||
* @return true if the TCB is sane, false else.
|
||||
*/
|
||||
bool esp_core_dump_tcb_addr_is_sane(uint32_t addr);
|
||||
|
||||
/**
|
||||
* @brief Get the number of RAM segments.
|
||||
*
|
||||
* @return Number of RAM segments.
|
||||
*/
|
||||
uint32_t esp_core_dump_get_user_ram_segments(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get start address and size of a memory region.
|
||||
*
|
||||
* @param region Memory region to get information about.
|
||||
* @param start Pointer that will be filled with the region start address.
|
||||
* Must **not** be NULL.
|
||||
*
|
||||
* @return Size, in bytes, of the memory region.
|
||||
*/
|
||||
int esp_core_dump_get_user_ram_info(coredump_region_t region, uint32_t *start);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if the current task is in an ISR.
|
||||
*
|
||||
* @return true if task in an ISR, false else.
|
||||
*/
|
||||
bool esp_core_dump_in_isr_context(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the size all the memory regions (DRAM, RTC, RTC_FAST, IRAM)
|
||||
*
|
||||
* @return Size, in bytes, of all the memory regions.
|
||||
*/
|
||||
uint32_t esp_core_dump_get_user_ram_size(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get TCB length, in bytes.
|
||||
*
|
||||
* @return Length of TCB, in bytes.
|
||||
*/
|
||||
static inline uint32_t esp_core_dump_get_tcb_len(void)
|
||||
{
|
||||
return (sizeof(StaticTask_t) % sizeof(uint32_t)) ?
|
||||
((sizeof(StaticTask_t) / sizeof(uint32_t) + 1) * sizeof(uint32_t)) :
|
||||
sizeof(StaticTask_t);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the length, in bytes, of a given memory location. Padding is
|
||||
* taken into account in this calculation.
|
||||
*
|
||||
* @param start Start address of the momery location.
|
||||
* @param end End address of the memory location.
|
||||
*
|
||||
* @return Size of the memory location, multiple of sizeof(uint32_t).
|
||||
*/
|
||||
static inline uint32_t esp_core_dump_get_memory_len(uint32_t start, uint32_t end)
|
||||
{
|
||||
const uint32_t len = end - start;
|
||||
// Take stack padding into account
|
||||
return (len + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,142 +14,155 @@
|
||||
#ifndef ESP_CORE_DUMP_PORT_H_
|
||||
#define ESP_CORE_DUMP_PORT_H_
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Core dump port interface.
|
||||
*
|
||||
* This file contains all the functions required by the core dump component to
|
||||
* get the information related to the board or the SoC itself. Currently, the
|
||||
* implementations of this interface, located in `src/port/[arch]`, support
|
||||
* both Xtensa and RISC-V architecture.
|
||||
*/
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
|
||||
#include "esp_rom_crc.h"
|
||||
#elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||
#include "mbedtls/sha256.h"
|
||||
#endif
|
||||
#include "esp_core_dump_priv.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "esp_debug_helpers.h"
|
||||
#include "esp_app_format.h"
|
||||
#include "esp_core_dump_types.h"
|
||||
#include "esp_core_dump_port_impl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define COREDUMP_VERSION_CHIP ESP_CHIP_ID_ESP32
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define COREDUMP_VERSION_CHIP ESP_CHIP_ID_ESP32S2
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
COREDUMP_MEMORY_DRAM,
|
||||
COREDUMP_MEMORY_IRAM,
|
||||
COREDUMP_MEMORY_RTC,
|
||||
COREDUMP_MEMORY_RTC_FAST,
|
||||
COREDUMP_MEMORY_MAX,
|
||||
COREDUMP_MEMORY_START = COREDUMP_MEMORY_DRAM
|
||||
} coredump_region_t;
|
||||
|
||||
// RTOS tasks snapshots walk API
|
||||
void esp_core_dump_reset_tasks_snapshots_iter(void);
|
||||
void *esp_core_dump_get_next_task(void *handle);
|
||||
bool esp_core_dump_get_task_snapshot(void *handle, core_dump_task_header_t *task,
|
||||
core_dump_mem_seg_header_t *interrupted_stack);
|
||||
|
||||
bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz);
|
||||
void *esp_core_dump_get_current_task_handle(void);
|
||||
uint32_t esp_core_dump_get_stack(core_dump_task_header_t* task_snapshot, uint32_t* stk_base, uint32_t* stk_len);
|
||||
|
||||
static inline uint32_t esp_core_dump_get_tcb_len(void)
|
||||
{
|
||||
if (sizeof(StaticTask_t) % sizeof(uint32_t)) {
|
||||
return ((sizeof(StaticTask_t) / sizeof(uint32_t) + 1) * sizeof(uint32_t));
|
||||
}
|
||||
return sizeof(StaticTask_t);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_core_dump_get_memory_len(uint32_t start, uint32_t end)
|
||||
{
|
||||
uint32_t len = end - start;
|
||||
// Take stack padding into account
|
||||
return (len + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the architecture ID.
|
||||
*
|
||||
* @return Architecture ID, as described by ELF format.
|
||||
*/
|
||||
uint16_t esp_core_dump_get_arch_id(void);
|
||||
uint32_t esp_core_dump_get_task_regs_dump(core_dump_task_header_t *task, void **reg_dump);
|
||||
void esp_core_dump_init_extra_info(void);
|
||||
uint32_t esp_core_dump_get_extra_info(void **info);
|
||||
|
||||
uint32_t esp_core_dump_get_user_ram_segments(void);
|
||||
uint32_t esp_core_dump_get_user_ram_size(void);
|
||||
int esp_core_dump_get_user_ram_info(coredump_region_t region, uint32_t *start);
|
||||
|
||||
// Data integrity check functions
|
||||
void esp_core_dump_checksum_init(core_dump_write_data_t* wr_data);
|
||||
void esp_core_dump_checksum_update(core_dump_write_data_t* wr_data, void* data, size_t data_len);
|
||||
size_t esp_core_dump_checksum_finish(core_dump_write_data_t* wr_data, void** chs_ptr);
|
||||
uint32_t esp_core_dump_checksum_size(void);
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||
void esp_core_dump_print_sha256(const char* msg, const uint8_t* sha_output);
|
||||
int esp_core_dump_sha(mbedtls_sha256_context *ctx,
|
||||
const unsigned char *input, size_t ilen, unsigned char output[32]);
|
||||
#endif
|
||||
void esp_core_dump_print_checksum(const char* msg, const void* checksum);
|
||||
|
||||
/**
|
||||
* @brief Initialize the port module. This function is also in charge of
|
||||
* initializing the extra information, if any.
|
||||
*
|
||||
* @param info Pointer to the panic information. It contains the execution
|
||||
* frame.
|
||||
*/
|
||||
void esp_core_dump_port_init(panic_info_t *info);
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_STACK_SIZE > 0
|
||||
#if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG
|
||||
// increase stack size in verbose mode
|
||||
#define ESP_COREDUMP_STACK_SIZE (CONFIG_ESP_COREDUMP_STACK_SIZE+100)
|
||||
#else
|
||||
#define ESP_COREDUMP_STACK_SIZE CONFIG_ESP_COREDUMP_STACK_SIZE
|
||||
#endif
|
||||
#endif
|
||||
/**
|
||||
* @brief Reset fake stacks allocator, if any.
|
||||
*
|
||||
* @note This function is called if we want to free all the previously
|
||||
* allocated "fake" stacks, used in broken tasks.
|
||||
*/
|
||||
void esp_core_dump_reset_fake_stacks(void);
|
||||
|
||||
void esp_core_dump_report_stack_usage(void);
|
||||
/**
|
||||
* @brief Get ISR stack end address.
|
||||
*
|
||||
* @return End address of the ISR stack.
|
||||
*/
|
||||
uint32_t esp_core_dump_get_isr_stack_end(void);
|
||||
|
||||
#if ESP_COREDUMP_STACK_SIZE > 0
|
||||
#define COREDUMP_STACK_FILL_BYTE (0xa5U)
|
||||
extern uint8_t s_coredump_stack[];
|
||||
extern uint8_t *s_core_dump_sp;
|
||||
|
||||
#if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG
|
||||
#define esp_core_dump_fill_stack() \
|
||||
memset(s_coredump_stack, COREDUMP_STACK_FILL_BYTE, ESP_COREDUMP_STACK_SIZE)
|
||||
#else
|
||||
#define esp_core_dump_fill_stack()
|
||||
#endif
|
||||
/**
|
||||
* @brief Get the top of the ISR stack.
|
||||
*
|
||||
* @return Pointer to the top of the ISR stack.
|
||||
*/
|
||||
uint8_t* esp_core_dump_get_isr_stack_top(void);
|
||||
|
||||
#define esp_core_dump_setup_stack() \
|
||||
{ \
|
||||
s_core_dump_sp = (uint8_t *)((uint32_t)(s_coredump_stack + ESP_COREDUMP_STACK_SIZE - 1) & ~0xf); \
|
||||
esp_core_dump_fill_stack(); \
|
||||
/* 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); \
|
||||
asm volatile ("mov sp, %0" :: "r"(s_core_dump_sp)); \
|
||||
ESP_COREDUMP_LOGD("Use core dump stack @ 0x%x", get_sp()); \
|
||||
}
|
||||
#else
|
||||
#define esp_core_dump_setup_stack() \
|
||||
{ \
|
||||
/* if we are in ISR set watchpoint to the end of ISR stack */ \
|
||||
if (xPortInterruptedFromISRContext()) { \
|
||||
extern uint8_t port_IntStack; \
|
||||
esp_clear_watchpoint(1); \
|
||||
esp_set_watchpoint(1, &port_IntStack+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 */ \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
// coredump memory regions defined during compile timing
|
||||
extern int _coredump_dram_start;
|
||||
extern int _coredump_dram_end;
|
||||
extern int _coredump_iram_start;
|
||||
extern int _coredump_iram_end;
|
||||
extern int _coredump_rtc_start;
|
||||
extern int _coredump_rtc_end;
|
||||
extern int _coredump_rtc_fast_start;
|
||||
extern int _coredump_rtc_fast_end;
|
||||
/**
|
||||
* @brief Check the stack defined by address given.
|
||||
*
|
||||
* @param task Task to check the stack of.
|
||||
*
|
||||
* @return true is the stack is sane, false else.
|
||||
*/
|
||||
bool esp_core_dump_check_stack(core_dump_task_header_t *task);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if the memory segment is sane.
|
||||
*
|
||||
* @param addr Address of the memory segment to check.
|
||||
* @param sz Size of the memory segment to check.
|
||||
*
|
||||
* @return true if the memory segment is sane, false else.
|
||||
*/
|
||||
bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the stack of a task.
|
||||
*
|
||||
* @param task_snapshot Pointer to the task snapshot.
|
||||
* @param stk_vaddr Pointer which will be set to the stack's virtual address.
|
||||
* Must **not** be NULL.
|
||||
* @param stk_paddr Pointer which will be set to the stack's physical
|
||||
* address. Must **not** be NULL.
|
||||
*
|
||||
* @return Size, in bytes, of the stack.
|
||||
*/
|
||||
uint32_t esp_core_dump_get_stack(core_dump_task_header_t* task_snapshot,
|
||||
uint32_t* stk_vaddr, uint32_t* stk_paddr);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check the task passed as a parameter.
|
||||
*
|
||||
* @note The goal of this function is to check whether the task passed is the
|
||||
* task that crashed or not. If this is the case and if it didn't crash
|
||||
* within an ISR, its stack pointer will be set to the panic frame,
|
||||
* containing all the registers values when the error occured. This
|
||||
* function also checks if the TCB address is sane or not.
|
||||
*
|
||||
* @param task Pointer to the frame exception generated when the panic occured.
|
||||
*
|
||||
* @return True if the TCB is sane, false else.
|
||||
*/
|
||||
bool esp_core_dump_check_task(core_dump_task_header_t *task);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a dump of the task's registers.
|
||||
*
|
||||
* @note In practice, this function is used to fill the ELF file with the
|
||||
* PR_STATUS sections for all the existing tasks. This structure
|
||||
* contains the CPU registers value when the exception occured.
|
||||
*
|
||||
* @param task Task to dump the registers from.
|
||||
* @param reg_dump Pointer that will be filled with the registers dump.
|
||||
* Must **not** be NULL.
|
||||
*
|
||||
* @return Size, in bytes, of the returned registers duump.
|
||||
*/
|
||||
uint32_t esp_core_dump_get_task_regs_dump(core_dump_task_header_t *task,
|
||||
void **reg_dump);
|
||||
|
||||
/**
|
||||
* @brief Transmit the crashed task handle.
|
||||
*
|
||||
* @param handle Crashed task handle.
|
||||
*
|
||||
* @note This function is used to give information about the crashed task to
|
||||
* the port module. It can be ignored if not needed.
|
||||
*/
|
||||
void esp_core_dump_port_set_crashed_tcb(uint32_t handle);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the extra information.
|
||||
*
|
||||
* @param info Pointer that will be filled with the extra information.
|
||||
* Can be NULL, in that case, this function is used to get the
|
||||
* extra information size.
|
||||
*
|
||||
* @return Size, in bytes, of the extra information.
|
||||
*/
|
||||
uint32_t esp_core_dump_get_extra_info(void **info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,157 +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.
|
||||
#ifndef ESP_CORE_DUMP_PRIV_H_
|
||||
#define ESP_CORE_DUMP_PRIV_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
#if CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||
// TODO: move this to portable part of the code
|
||||
#include "mbedtls/sha256.h"
|
||||
#endif
|
||||
|
||||
#define ESP_COREDUMP_LOG( level, format, ... ) if (LOG_LOCAL_LEVEL >= level) { esp_rom_printf(DRAM_STR(format), esp_log_early_timestamp(), (const char *)TAG, ##__VA_ARGS__); }
|
||||
#define ESP_COREDUMP_LOGE( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_ERROR, LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGW( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_WARN, LOG_FORMAT(W, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGI( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_INFO, LOG_FORMAT(I, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGD( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_DEBUG, LOG_FORMAT(D, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGV( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_VERBOSE, LOG_FORMAT(V, format), ##__VA_ARGS__)
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
#define ESP_COREDUMP_LOG_PROCESS( format, ... ) ESP_COREDUMP_LOGD(format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define ESP_COREDUMP_LOG_PROCESS( format, ... ) do{/*(__VA_ARGS__);*/}while(0)
|
||||
#endif
|
||||
|
||||
#define COREDUMP_MAX_TASK_STACK_SIZE (64*1024)
|
||||
// COREDUMP_VERSION_CHIP is defined in ports
|
||||
#define COREDUMP_VERSION_MAKE(_maj_, _min_) ((((COREDUMP_VERSION_CHIP)&0xFFFF) << 16) | (((_maj_)&0xFF) << 8) | (((_min_)&0xFF) << 0))
|
||||
#define COREDUMP_VERSION_BIN 0
|
||||
#define COREDUMP_VERSION_ELF 1
|
||||
// legacy bin coredumps (before IDF v4.1) has version set to 1
|
||||
#define COREDUMP_VERSION_BIN_LEGACY COREDUMP_VERSION_MAKE(COREDUMP_VERSION_BIN, 1) // -> 0x0001
|
||||
#define COREDUMP_VERSION_BIN_CURRENT COREDUMP_VERSION_MAKE(COREDUMP_VERSION_BIN, 2) // -> 0x0002
|
||||
#define COREDUMP_VERSION_ELF_CRC32 COREDUMP_VERSION_MAKE(COREDUMP_VERSION_ELF, 0) // -> 0x0100
|
||||
#define COREDUMP_VERSION_ELF_SHA256 COREDUMP_VERSION_MAKE(COREDUMP_VERSION_ELF, 1) // -> 0x0101
|
||||
#define COREDUMP_CURR_TASK_MARKER 0xDEADBEEF
|
||||
#define COREDUMP_CURR_TASK_NOT_FOUND -1
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
#if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
|
||||
#define COREDUMP_VERSION COREDUMP_VERSION_ELF_CRC32
|
||||
#elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||
#define COREDUMP_VERSION COREDUMP_VERSION_ELF_SHA256
|
||||
#define COREDUMP_SHA256_LEN 32
|
||||
#endif
|
||||
#else
|
||||
#define COREDUMP_VERSION COREDUMP_VERSION_BIN_CURRENT
|
||||
#endif
|
||||
|
||||
#define COREDUMP_CHECKSUM_MAX_LEN 32
|
||||
|
||||
typedef esp_err_t (*esp_core_dump_write_prepare_t)(void *priv, uint32_t *data_len);
|
||||
typedef esp_err_t (*esp_core_dump_write_start_t)(void *priv);
|
||||
typedef esp_err_t (*esp_core_dump_write_end_t)(void *priv);
|
||||
typedef esp_err_t (*esp_core_dump_flash_write_data_t)(void *priv, void * data, uint32_t data_len);
|
||||
|
||||
typedef uint32_t core_dump_crc_t;
|
||||
|
||||
/**
|
||||
* The following macro defines the size of the cache used to write the coredump
|
||||
* to the flash. When the flash is encrypted, the smallest data block we can
|
||||
* write to it is 16 bytes long. Thus, this macro MUST be a multiple of 16.
|
||||
*/
|
||||
#define COREDUMP_CACHE_SIZE 32
|
||||
|
||||
#if (COREDUMP_CACHE_SIZE % 16) != 0
|
||||
#error "Coredump cache size must be a multiple of 16"
|
||||
#endif
|
||||
|
||||
typedef struct _core_dump_write_data_t
|
||||
{
|
||||
// TODO: move flash related data to flash-specific code
|
||||
uint32_t off; // current offset in partition
|
||||
uint8_t cached_data[COREDUMP_CACHE_SIZE];
|
||||
uint8_t cached_bytes;
|
||||
#if CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||
// TODO: move this to portable part of the code
|
||||
mbedtls_sha256_context ctx;
|
||||
char sha_output[COREDUMP_SHA256_LEN];
|
||||
#elif CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
|
||||
core_dump_crc_t crc; // CRC of dumped data
|
||||
#endif
|
||||
} core_dump_write_data_t;
|
||||
|
||||
// core dump emitter control structure
|
||||
typedef struct _core_dump_write_config_t
|
||||
{
|
||||
// this function is called before core dump data writing
|
||||
// used for sanity checks
|
||||
esp_core_dump_write_prepare_t prepare;
|
||||
// this function is called at the beginning of data writing
|
||||
esp_core_dump_write_start_t start;
|
||||
// this function is called when all dump data are written
|
||||
esp_core_dump_write_end_t end;
|
||||
// this function is called to write data chunk
|
||||
esp_core_dump_flash_write_data_t write;
|
||||
// pointer to data which are specific for particular core dump emitter
|
||||
void * priv;
|
||||
} core_dump_write_config_t;
|
||||
|
||||
/** core dump data header */
|
||||
typedef struct _core_dump_header_t
|
||||
{
|
||||
uint32_t data_len; // data length
|
||||
uint32_t version; // core dump struct version
|
||||
uint32_t tasks_num; // number of tasks
|
||||
uint32_t tcb_sz; // size of TCB
|
||||
uint32_t mem_segs_num; // number of memory segments
|
||||
} core_dump_header_t;
|
||||
|
||||
/** core dump task data header */
|
||||
typedef struct _core_dump_task_header_t
|
||||
{
|
||||
void* tcb_addr; // TCB address
|
||||
uint32_t stack_start; // stack start address
|
||||
uint32_t stack_end; // stack end address
|
||||
} core_dump_task_header_t;
|
||||
|
||||
/** core dump memory segment header */
|
||||
typedef struct _core_dump_mem_seg_header_t
|
||||
{
|
||||
uint32_t start; // memory region start address
|
||||
uint32_t size; // memory region size
|
||||
} core_dump_mem_seg_header_t;
|
||||
|
||||
// Core dump flash init function
|
||||
void esp_core_dump_flash_init(void);
|
||||
|
||||
// Common core dump write function
|
||||
void esp_core_dump_write(panic_info_t *info, core_dump_write_config_t *write_cfg);
|
||||
|
||||
#include "esp_core_dump_port.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,188 @@
|
||||
// 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.
|
||||
#ifndef ESP_CORE_DUMP_PRIV_H_
|
||||
#define ESP_CORE_DUMP_PRIV_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
#include "core_dump_checksum.h"
|
||||
|
||||
#define ESP_COREDUMP_LOG( level, format, ... ) if (LOG_LOCAL_LEVEL >= level) { esp_rom_printf(DRAM_STR(format), esp_log_early_timestamp(), (const char *)TAG, ##__VA_ARGS__); }
|
||||
#define ESP_COREDUMP_LOGE( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_ERROR, LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGW( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_WARN, LOG_FORMAT(W, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGI( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_INFO, LOG_FORMAT(I, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGD( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_DEBUG, LOG_FORMAT(D, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGV( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_VERBOSE, LOG_FORMAT(V, format), ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Assertion to be verified in a release context. Cannot be muted.
|
||||
*/
|
||||
#define ESP_COREDUMP_ASSERT( condition ) if(!(condition)){ abort(); } else { }
|
||||
|
||||
/**
|
||||
* @brief Assertion to be verified in a debug context. Can be muted.
|
||||
*/
|
||||
#define ESP_COREDUMP_DEBUG_ASSERT( condition ) assert(condition)
|
||||
|
||||
/**
|
||||
* @brief Logging should only be enabled if the core dump is not written to
|
||||
* the UART.
|
||||
*/
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
#define ESP_COREDUMP_LOG_PROCESS( format, ... ) ESP_COREDUMP_LOGD(format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define ESP_COREDUMP_LOG_PROCESS( format, ... ) do{/*(__VA_ARGS__);*/}while(0)
|
||||
#endif
|
||||
|
||||
#define COREDUMP_MAX_TASK_STACK_SIZE (64*1024)
|
||||
|
||||
/**
|
||||
* @brief The following macros defined below are used to create a version
|
||||
* numbering. This number is then used in the core dump header.
|
||||
*
|
||||
* @note COREDUMP_VERSION_CHIP is defined in ports header.
|
||||
*/
|
||||
#define COREDUMP_VERSION_MAKE(_maj_, _min_) ( \
|
||||
(((COREDUMP_VERSION_CHIP)&0xFFFF) << 16) | \
|
||||
(((_maj_)&0xFF) << 8) | \
|
||||
(((_min_)&0xFF) << 0) \
|
||||
)
|
||||
#define COREDUMP_VERSION_BIN 0
|
||||
#define COREDUMP_VERSION_ELF 1
|
||||
|
||||
/* legacy bin coredumps (before IDF v4.1) has version set to 1 */
|
||||
#define COREDUMP_VERSION_BIN_LEGACY COREDUMP_VERSION_MAKE(COREDUMP_VERSION_BIN, 1) // -> 0x0001
|
||||
#define COREDUMP_VERSION_BIN_CURRENT COREDUMP_VERSION_MAKE(COREDUMP_VERSION_BIN, 2) // -> 0x0002
|
||||
#define COREDUMP_VERSION_ELF_CRC32 COREDUMP_VERSION_MAKE(COREDUMP_VERSION_ELF, 0) // -> 0x0100
|
||||
#define COREDUMP_VERSION_ELF_SHA256 COREDUMP_VERSION_MAKE(COREDUMP_VERSION_ELF, 1) // -> 0x0101
|
||||
#define COREDUMP_CURR_TASK_MARKER 0xDEADBEEF
|
||||
#define COREDUMP_CURR_TASK_NOT_FOUND -1
|
||||
|
||||
/**
|
||||
* @brief Macro defining the size of the cache used to write the core dump.
|
||||
*/
|
||||
#define COREDUMP_CACHE_SIZE 32
|
||||
|
||||
/**
|
||||
* @brief If the core dump has to be written to an encrypted flash, the
|
||||
* smallest data block we can write to it is 16 bytes long. Thus, this macro
|
||||
* MUST be a multiple of 16.
|
||||
*/
|
||||
#if (COREDUMP_CACHE_SIZE % 16) != 0
|
||||
#error "Coredump cache size must be a multiple of 16"
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _core_dump_write_data_t
|
||||
{
|
||||
uint32_t off; /*!< Current offset of data being written */
|
||||
uint8_t cached_data[COREDUMP_CACHE_SIZE]; /*!< Cache used to write to flash */
|
||||
uint8_t cached_bytes; /*!< Number of bytes filled in the cached */
|
||||
core_dump_checksum_ctx* checksum_ctx; /*!< Checksum context */
|
||||
} core_dump_write_data_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Types below define the signatures of the callbacks that are used
|
||||
* to output a core dump. The destination of the dump is implementation
|
||||
* dependant.
|
||||
*/
|
||||
typedef esp_err_t (*esp_core_dump_write_prepare_t)(core_dump_write_data_t* priv, uint32_t *data_len);
|
||||
typedef esp_err_t (*esp_core_dump_write_start_t)(core_dump_write_data_t* priv);
|
||||
typedef esp_err_t (*esp_core_dump_write_end_t)(core_dump_write_data_t* priv);
|
||||
typedef esp_err_t (*esp_core_dump_flash_write_data_t)(core_dump_write_data_t* priv,
|
||||
void * data,
|
||||
uint32_t data_len);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Core dump emitter control structure.
|
||||
* This structure contains the functions that are called in order to write
|
||||
* the core dump to the destination (UART or flash).
|
||||
* The function are called in this order:
|
||||
* - prepare
|
||||
* - start
|
||||
* - write (called once or more)
|
||||
* - end
|
||||
*/
|
||||
typedef struct _core_dump_write_config_t
|
||||
{
|
||||
esp_core_dump_write_prepare_t prepare; /*!< Function called for sanity checks */
|
||||
esp_core_dump_write_start_t start; /*!< Function called at the beginning of data writing */
|
||||
esp_core_dump_flash_write_data_t write; /*!< Function called to write data chunk */
|
||||
esp_core_dump_write_end_t end; /*!< Function called once all data have been written */
|
||||
core_dump_write_data_t* priv; /*!< Private context to pass to every function of this structure */
|
||||
} core_dump_write_config_t;
|
||||
|
||||
/**
|
||||
* @brief Core dump data header
|
||||
* This header predecesses the actual core dump data (ELF or binary). */
|
||||
typedef struct _core_dump_header_t
|
||||
{
|
||||
uint32_t data_len; /*!< Data length */
|
||||
uint32_t version; /*!< Core dump version */
|
||||
uint32_t tasks_num; /*!< Number of tasks */
|
||||
uint32_t tcb_sz; /*!< Size of a TCB, in bytes */
|
||||
uint32_t mem_segs_num; /*!< Number of memory segments */
|
||||
} core_dump_header_t;
|
||||
|
||||
/**
|
||||
* @brief Core dump task data header
|
||||
* The main goal of this definition is to add typing to the code.
|
||||
*/
|
||||
typedef void* core_dump_task_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Header for the tasks
|
||||
*/
|
||||
typedef struct _core_dump_task_header_t
|
||||
{
|
||||
core_dump_task_handle_t tcb_addr; /*!< TCB address */
|
||||
uint32_t stack_start; /*!< Start of the stack address */
|
||||
uint32_t stack_end; /*!< End of the stack address */
|
||||
} core_dump_task_header_t;
|
||||
|
||||
/**
|
||||
* @brief Core dump memory segment header
|
||||
*/
|
||||
typedef struct _core_dump_mem_seg_header_t
|
||||
{
|
||||
uint32_t start; /*!< Memory region start address */
|
||||
uint32_t size; /*!< Memory region size */
|
||||
} core_dump_mem_seg_header_t;
|
||||
|
||||
/**
|
||||
* @brief Core dump flash init function
|
||||
*/
|
||||
void esp_core_dump_flash_init(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Common core dump write function
|
||||
*/
|
||||
void esp_core_dump_write(panic_info_t *info, core_dump_write_config_t *write_cfg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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.
|
||||
#ifndef ESP_CORE_DUMP_PORT_IMPL_H_
|
||||
#define ESP_CORE_DUMP_PORT_IMPL_H_
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Core dump port interface implementation for RISC-V.
|
||||
*/
|
||||
|
||||
#include "esp_core_dump_types.h"
|
||||
#include "esp_app_format.h"
|
||||
|
||||
/**
|
||||
* @brief Chip ID associated to this implementation.
|
||||
*/
|
||||
#define COREDUMP_VERSION_CHIP ESP_CHIP_ID_ESP32C3
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the stack pointer to the address passed as a parameter.
|
||||
* @note This function must be inlined.
|
||||
*
|
||||
* @param new_sp New stack pointer to set in sp register.
|
||||
*
|
||||
* @return Former stack pointer address (sp register value).
|
||||
*/
|
||||
FORCE_INLINE_ATTR void* esp_core_dump_replace_sp(void* new_sp)
|
||||
{
|
||||
void* current_sp = NULL;
|
||||
asm volatile ("mv %0, sp \n\t\
|
||||
mv sp, %1 \n\t\
|
||||
"
|
||||
: "=&r"(current_sp)
|
||||
: "r"(new_sp));
|
||||
return current_sp;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
// 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.
|
||||
#ifndef ESP_CORE_DUMP_PORT_IMPL_H_
|
||||
#define ESP_CORE_DUMP_PORT_IMPL_H_
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Core dump port interface implementation for Xtensa boards.
|
||||
*/
|
||||
#include "esp_core_dump_types.h"
|
||||
#include "esp_app_format.h"
|
||||
/**
|
||||
* Included for SET_STACK macro
|
||||
*/
|
||||
#include <xtensa/xtruntime.h>
|
||||
#include <xt_instr_macros.h>
|
||||
|
||||
/**
|
||||
* @brief Chip ID associated to this implementation.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define COREDUMP_VERSION_CHIP ESP_CHIP_ID_ESP32
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define COREDUMP_VERSION_CHIP ESP_CHIP_ID_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define COREDUMP_VERSION_CHIP ESP_CHIP_ID_ESP32S3
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the stack pointer to the address passed as a parameter.
|
||||
* @note This function must be inlined.
|
||||
*
|
||||
* @param new_sp New stack pointer to set in sp register.
|
||||
*
|
||||
* @return Former stack pointer address (sp register value).
|
||||
*/
|
||||
FORCE_INLINE_ATTR void* esp_core_dump_replace_sp(void* new_sp)
|
||||
{
|
||||
void* current_sp = NULL;
|
||||
asm volatile ("mov %0, sp \n\t\
|
||||
"
|
||||
: "=&r"(current_sp)
|
||||
:);
|
||||
SET_STACK(new_sp);
|
||||
return current_sp;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user