Merge branch 'feature/apptrace_api_ext' into 'master'
esp32: Apptrace API enhancement See merge request !1021
This commit is contained in:
commit
d286d2f647
11 changed files with 376 additions and 196 deletions
|
@ -22,6 +22,12 @@ config ESP32_APPTRACE_ENABLE
|
|||
help
|
||||
Enables/disable application tracing module.
|
||||
|
||||
config ESP32_APPTRACE_LOCK_ENABLE
|
||||
bool
|
||||
default !SYSVIEW_ENABLE
|
||||
help
|
||||
Enables/disable application tracing module internal sync lock.
|
||||
|
||||
config ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
int "Timeout for flushing last trace data to host on panic"
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
|
|
|
@ -103,7 +103,8 @@
|
|||
// that task/ISR will fail to complete filling its data chunk before the whole trace block is exposed to the host. To handle such conditions tracing
|
||||
// module prepends all user data chunks with header which contains allocated buffer size and actual data length within it. OpenOCD command
|
||||
// which reads application traces reports error when it reads incompleted user data block.
|
||||
// Data which are transfered from host to target are also prepended with such header.
|
||||
// Data which are transfered from host to target are also prepended with a header. Down channel data header is simple and consists of one two bytes field
|
||||
// containing length of host data following the heder.
|
||||
|
||||
// 4.3 Data Buffering
|
||||
// ------------------
|
||||
|
@ -159,14 +160,10 @@
|
|||
#include "soc/dport_reg.h"
|
||||
#include "eri.h"
|
||||
#include "trax.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
|
||||
#if CONFIG_ESP32_APPTRACE_ENABLE
|
||||
#define ESP_APPTRACE_MAX_VPRINTF_ARGS 256
|
||||
|
@ -174,7 +171,7 @@
|
|||
|
||||
#define ESP_APPTRACE_PRINT_LOCK 0
|
||||
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_ERROR
|
||||
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "esp_apptrace";
|
||||
|
||||
|
@ -244,17 +241,13 @@ static volatile uint8_t *s_trax_blocks[] = {
|
|||
|
||||
#define ESP_APPTRACE_TRAX_BLOCKS_NUM (sizeof(s_trax_blocks)/sizeof(s_trax_blocks[0]))
|
||||
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_SIZE 0x4000UL
|
||||
|
||||
#define ESP_APPTRACE_TRAX_INBLOCK_START 0
|
||||
|
||||
#define ESP_APPTRACE_TRAX_INBLOCK_MARKER() (s_trace_buf.trax.state.markers[s_trace_buf.trax.state.in_block % 2])
|
||||
#define ESP_APPTRACE_TRAX_INBLOCK_MARKER_UPD(_v_) do {s_trace_buf.trax.state.markers[s_trace_buf.trax.state.in_block % 2] += (_v_);}while(0)
|
||||
#define ESP_APPTRACE_TRAX_INBLOCK_GET() (&s_trace_buf.trax.blocks[s_trace_buf.trax.state.in_block % 2])
|
||||
|
||||
//TODO: menuconfig
|
||||
#define ESP_APPTRACE_DOWN_BUF_SIZE 32UL
|
||||
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_SIZE (0x4000UL)
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
#define ESP_APPTRACE_USR_DATA_LEN_MAX 255UL
|
||||
#else
|
||||
|
@ -324,7 +317,6 @@ typedef struct {
|
|||
// ring buffer control struct for data from host (down buffer)
|
||||
esp_apptrace_rb_t rb_down;
|
||||
// storage for above ring buffer data
|
||||
uint8_t down_buf[ESP_APPTRACE_DOWN_BUF_SIZE + 1];
|
||||
esp_apptrace_trax_data_t trax; // TRAX HW transport data
|
||||
} esp_apptrace_buffer_t;
|
||||
|
||||
|
@ -334,13 +326,15 @@ static esp_apptrace_buffer_t s_trace_buf;
|
|||
static esp_apptrace_lock_t s_log_lock = {.irq_stat = 0, .portmux = portMUX_INITIALIZER_UNLOCKED};
|
||||
#endif
|
||||
|
||||
static uint16_t esp_apptrace_trax_write_down_buffer_nolock(uint8_t *data, uint16_t size);
|
||||
static esp_err_t esp_apptrace_trax_flush(uint32_t min_sz, uint32_t tmo);
|
||||
static uint32_t esp_apptrace_trax_down_buffer_write_nolock(uint8_t *data, uint32_t size);
|
||||
static esp_err_t esp_apptrace_trax_flush(uint32_t min_sz, esp_apptrace_tmo_t *tmo);
|
||||
|
||||
static inline int esp_apptrace_log_lock()
|
||||
{
|
||||
#if ESP_APPTRACE_PRINT_LOCK
|
||||
int ret = esp_apptrace_lock_take(&s_log_lock, ESP_APPTRACE_TMO_INFINITE);
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, ESP_APPTRACE_TMO_INFINITE);
|
||||
int ret = esp_apptrace_lock_take(&s_log_lock, &tmo);
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
|
@ -354,40 +348,26 @@ static inline void esp_apptrace_log_unlock()
|
|||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_lock_initialize()
|
||||
static inline esp_err_t esp_apptrace_lock_initialize()
|
||||
{
|
||||
#if CONFIG_SYSVIEW_ENABLE == 0
|
||||
#if CONFIG_ESP32_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(&s_trace_buf.lock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t inline esp_apptrace_lock_cleanup()
|
||||
static inline esp_err_t esp_apptrace_lock_cleanup()
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_lock(uint32_t *tmo)
|
||||
esp_err_t esp_apptrace_lock(esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
#if CONFIG_SYSVIEW_ENABLE == 0
|
||||
unsigned cur, elapsed, start = xthal_get_ccount();
|
||||
|
||||
esp_err_t ret = esp_apptrace_lock_take(&s_trace_buf.lock, *tmo);
|
||||
#if CONFIG_ESP32_APPTRACE_LOCK_ENABLE
|
||||
esp_err_t ret = esp_apptrace_lock_take(&s_trace_buf.lock, tmo);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
// decrease tmo by actual waiting time
|
||||
cur = xthal_get_ccount();
|
||||
if (start <= cur) {
|
||||
elapsed = cur - start;
|
||||
} else {
|
||||
elapsed = ULONG_MAX - start + cur;
|
||||
}
|
||||
if (ESP_APPTRACE_CPUTICKS2US(elapsed) > *tmo) {
|
||||
*tmo = 0;
|
||||
} else {
|
||||
*tmo -= ESP_APPTRACE_CPUTICKS2US(elapsed);
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -395,7 +375,7 @@ esp_err_t esp_apptrace_lock(uint32_t *tmo)
|
|||
esp_err_t esp_apptrace_unlock()
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
#if CONFIG_SYSVIEW_ENABLE == 0
|
||||
#if CONFIG_ESP32_APPTRACE_LOCK_ENABLE
|
||||
ret = esp_apptrace_lock_give(&s_trace_buf.lock);
|
||||
#endif
|
||||
return ret;
|
||||
|
@ -476,7 +456,8 @@ static esp_err_t esp_apptrace_trax_block_switch()
|
|||
uint32_t host_to_read = ESP_APPTRACE_TRAX_BLOCK_LEN_GET(ctrl_reg);
|
||||
if (host_to_read != 0 || acked_block != (s_trace_buf.trax.state.in_block & ESP_APPTRACE_TRAX_BLOCK_ID_MSK)) {
|
||||
ESP_APPTRACE_LOGD("HC[%d]: Can not switch %x %d %x %x/%lx, m %d", xPortGetCoreID(), ctrl_reg, host_to_read, acked_block,
|
||||
s_trace_buf.trax.state.in_block & ESP_APPTRACE_TRAX_BLOCK_ID_MSK, s_trace_buf.trax.state.in_block, s_trace_buf.trax.state.markers[prev_block_num]);
|
||||
s_trace_buf.trax.state.in_block & ESP_APPTRACE_TRAX_BLOCK_ID_MSK, s_trace_buf.trax.state.in_block,
|
||||
s_trace_buf.trax.state.markers[prev_block_num]);
|
||||
res = ESP_ERR_NO_MEM;
|
||||
goto _on_func_exit;
|
||||
}
|
||||
|
@ -491,12 +472,15 @@ static esp_err_t esp_apptrace_trax_block_switch()
|
|||
if (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA && hdr->block_sz > 0) {
|
||||
// TODO: add support for multiple blocks from host, currently there is no need for that
|
||||
uint8_t *p = s_trace_buf.trax.blocks[new_block_num].start + s_trace_buf.trax.blocks[new_block_num].sz;
|
||||
ESP_APPTRACE_LOGD("Recvd %d bytes from host [%x %x %x .. %x %x]", hdr->block_sz,
|
||||
ESP_APPTRACE_LOGD("Recvd %d bytes from host [%x %x %x %x %x %x %x %x .. %x %x %x %x %x %x %x %x]", hdr->block_sz,
|
||||
*(s_trace_buf.trax.blocks[new_block_num].start+0), *(s_trace_buf.trax.blocks[new_block_num].start+1),
|
||||
*(s_trace_buf.trax.blocks[new_block_num].start+2), *(p-2), *(p-1));
|
||||
uint32_t sz = esp_apptrace_trax_write_down_buffer_nolock((uint8_t *)(hdr+1), hdr->block_sz);
|
||||
*(s_trace_buf.trax.blocks[new_block_num].start+2), *(s_trace_buf.trax.blocks[new_block_num].start+3),
|
||||
*(s_trace_buf.trax.blocks[new_block_num].start+4), *(s_trace_buf.trax.blocks[new_block_num].start+5),
|
||||
*(s_trace_buf.trax.blocks[new_block_num].start+6), *(s_trace_buf.trax.blocks[new_block_num].start+7),
|
||||
*(p-8), *(p-7), *(p-6), *(p-5), *(p-4), *(p-3), *(p-2), *(p-1));
|
||||
uint32_t sz = esp_apptrace_trax_down_buffer_write_nolock((uint8_t *)(hdr+1), hdr->block_sz);
|
||||
if (sz != hdr->block_sz) {
|
||||
ESP_APPTRACE_LOGE("Failed to write %d bytes to down buffer!", hdr->block_sz - sz);
|
||||
ESP_APPTRACE_LOGE("Failed to write %d bytes to down buffer (%d %d)!", hdr->block_sz - sz, hdr->block_sz, sz);
|
||||
}
|
||||
hdr->block_sz = 0;
|
||||
}
|
||||
|
@ -548,15 +532,12 @@ _on_func_exit:
|
|||
return res;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_block_switch_waitus(uint32_t tmo)
|
||||
static esp_err_t esp_apptrace_trax_block_switch_waitus(esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
int res;
|
||||
esp_apptrace_tmo_t sleeping_tmo;
|
||||
|
||||
esp_apptrace_tmo_init(&sleeping_tmo, tmo);
|
||||
|
||||
while ((res = esp_apptrace_trax_block_switch()) != ESP_OK) {
|
||||
res = esp_apptrace_tmo_check(&sleeping_tmo);
|
||||
res = esp_apptrace_tmo_check(tmo);
|
||||
if (res != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
|
@ -564,58 +545,79 @@ static esp_err_t esp_apptrace_trax_block_switch_waitus(uint32_t tmo)
|
|||
return res;
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_trax_down_buf_init()
|
||||
static uint8_t *esp_apptrace_trax_down_buffer_get(uint32_t *size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_rb_init(&s_trace_buf.rb_down, s_trace_buf.down_buf, sizeof(s_trace_buf.down_buf));
|
||||
}
|
||||
uint8_t *ptr = NULL;
|
||||
|
||||
static inline uint8_t *esp_apptrace_trax_get_down_rdptr(uint32_t *size, uint32_t *tmo)
|
||||
{
|
||||
int res = esp_apptrace_lock(tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// may need to flush
|
||||
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
|
||||
if (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA) {
|
||||
ESP_APPTRACE_LOGD("force flush");
|
||||
res = esp_apptrace_trax_block_switch_waitus(*tmo);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to switch to another block to recv data from host!");
|
||||
while (1) {
|
||||
uint32_t sz = esp_apptrace_rb_read_size_get(&s_trace_buf.rb_down);
|
||||
if (sz != 0) {
|
||||
ptr = esp_apptrace_rb_consume(&s_trace_buf.rb_down, sz > *size ? *size : sz);
|
||||
if (!ptr) {
|
||||
assert(false && "Failed to consume bytes from down buffer!");
|
||||
}
|
||||
*size = sz;
|
||||
break;
|
||||
}
|
||||
// may need to flush
|
||||
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
|
||||
if (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA) {
|
||||
ESP_APPTRACE_LOGD("force flush");
|
||||
res = esp_apptrace_trax_block_switch_waitus(tmo);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to switch to another block to recv data from host!");
|
||||
/*do not return error because data can be in down buffer already*/
|
||||
}
|
||||
} else {
|
||||
// check tmo only if there is no data from host
|
||||
res = esp_apptrace_tmo_check(tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint8_t *ptr = NULL;
|
||||
uint32_t sz = esp_apptrace_rb_read_size_get(&s_trace_buf.rb_down);
|
||||
if (sz > 0) {
|
||||
ptr = esp_apptrace_rb_consume(&s_trace_buf.rb_down, sz > *size ? *size : sz);
|
||||
if (!ptr) {
|
||||
assert(false && "Failed to consume bytes from down buffer!");
|
||||
}
|
||||
}
|
||||
*size = sz;
|
||||
|
||||
if (esp_apptrace_unlock() != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline esp_err_t esp_apptrace_trax_put_down_rdptr(uint8_t *ptr, uint32_t size, uint32_t *tmo)
|
||||
static inline esp_err_t esp_apptrace_trax_down_buffer_put(uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
/* nothing todo */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static uint16_t esp_apptrace_trax_write_down_buffer_nolock(uint8_t *data, uint16_t size)
|
||||
static uint32_t esp_apptrace_trax_down_buffer_write_nolock(uint8_t *data, uint32_t size)
|
||||
{
|
||||
uint8_t *ptr = esp_apptrace_rb_produce(&s_trace_buf.rb_down, size);
|
||||
if (ptr) {
|
||||
memcpy(ptr, data, size);
|
||||
} else {
|
||||
return 0;
|
||||
uint32_t total_sz = 0;
|
||||
|
||||
while (total_sz < size) {
|
||||
// ESP_APPTRACE_LOGE("esp_apptrace_trax_down_buffer_write_nolock WRS %d-%d-%d %d", s_trace_buf.rb_down.wr, s_trace_buf.rb_down.rd,
|
||||
// s_trace_buf.rb_down.cur_size, size);
|
||||
uint32_t wr_sz = esp_apptrace_rb_write_size_get(&s_trace_buf.rb_down);
|
||||
if (wr_sz == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (wr_sz > size - total_sz) {
|
||||
wr_sz = size - total_sz;
|
||||
}
|
||||
// ESP_APPTRACE_LOGE("esp_apptrace_trax_down_buffer_write_nolock wr %d", wr_sz);
|
||||
uint8_t *ptr = esp_apptrace_rb_produce(&s_trace_buf.rb_down, wr_sz);
|
||||
if (!ptr) {
|
||||
assert(false && "Failed to produce bytes to down buffer!");
|
||||
}
|
||||
// ESP_APPTRACE_LOGE("esp_apptrace_trax_down_buffer_write_nolock wr %d to 0x%x from 0x%x", wr_sz, ptr, data + total_sz + wr_sz);
|
||||
memcpy(ptr, data + total_sz, wr_sz);
|
||||
total_sz += wr_sz;
|
||||
// ESP_APPTRACE_LOGE("esp_apptrace_trax_down_buffer_write_nolock wr %d/%d", wr_sz, total_sz);
|
||||
}
|
||||
return size;
|
||||
return total_sz;
|
||||
}
|
||||
|
||||
static inline uint8_t *esp_apptrace_data_header_init(uint8_t *ptr, uint16_t usr_size)
|
||||
|
@ -626,7 +628,7 @@ static inline uint8_t *esp_apptrace_data_header_init(uint8_t *ptr, uint16_t usr_
|
|||
return ptr + sizeof(esp_tracedata_hdr_t);
|
||||
}
|
||||
|
||||
static inline uint8_t *esp_apptrace_trax_wait4buf(uint16_t size, uint32_t tmo, int *pended)
|
||||
static inline uint8_t *esp_apptrace_trax_wait4buf(uint16_t size, esp_apptrace_tmo_t *tmo, int *pended)
|
||||
{
|
||||
uint8_t *ptr = NULL;
|
||||
|
||||
|
@ -665,7 +667,7 @@ static inline uint8_t *esp_apptrace_trax_wait4buf(uint16_t size, uint32_t tmo, i
|
|||
return ptr;
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_trax_get_buffer(size_t size, uint32_t *tmo)
|
||||
static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
uint8_t *buf_ptr = NULL;
|
||||
|
||||
|
@ -691,14 +693,14 @@ static uint8_t *esp_apptrace_trax_get_buffer(size_t size, uint32_t *tmo)
|
|||
buf_ptr = esp_apptrace_rb_produce(&s_trace_buf.trax.rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
if (buf_ptr == NULL) {
|
||||
int pended_buf;
|
||||
buf_ptr = esp_apptrace_trax_wait4buf(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), *tmo, &pended_buf);
|
||||
buf_ptr = esp_apptrace_trax_wait4buf(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
|
||||
if (buf_ptr) {
|
||||
if (pended_buf) {
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
esp_apptrace_trax_pend_chunk_sz_update(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
} else {
|
||||
ESP_APPTRACE_LOGD("Got %d bytes from TRAX buffer", size);
|
||||
ESP_APPTRACE_LOGD("Get %d bytes from TRAX buffer", size);
|
||||
// update cur block marker
|
||||
ESP_APPTRACE_TRAX_INBLOCK_MARKER_UPD(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
}
|
||||
|
@ -723,7 +725,7 @@ static uint8_t *esp_apptrace_trax_get_buffer(size_t size, uint32_t *tmo)
|
|||
if (buf_ptr == NULL) {
|
||||
int pended_buf;
|
||||
ESP_APPTRACE_LOGD("TRAX full. Get %d bytes from pend buffer", size);
|
||||
buf_ptr = esp_apptrace_trax_wait4buf(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), *tmo, &pended_buf);
|
||||
buf_ptr = esp_apptrace_trax_wait4buf(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
|
||||
if (buf_ptr) {
|
||||
if (pended_buf) {
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
|
@ -737,7 +739,7 @@ static uint8_t *esp_apptrace_trax_get_buffer(size_t size, uint32_t *tmo)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
ESP_APPTRACE_LOGD("Get %d bytes from TRAX buffer!", size);
|
||||
ESP_APPTRACE_LOGD("Get %d bytes from TRAX buffer", size);
|
||||
// fit to curr TRAX nlock
|
||||
buf_ptr = ESP_APPTRACE_TRAX_INBLOCK_GET()->start + ESP_APPTRACE_TRAX_INBLOCK_MARKER();
|
||||
// update cur block marker
|
||||
|
@ -755,7 +757,7 @@ static uint8_t *esp_apptrace_trax_get_buffer(size_t size, uint32_t *tmo)
|
|||
return buf_ptr;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_put_buffer(uint8_t *ptr, uint32_t *tmo)
|
||||
static esp_err_t esp_apptrace_trax_put_buffer(uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
int res = ESP_OK;
|
||||
esp_tracedata_hdr_t *hdr = (esp_tracedata_hdr_t *)(ptr - sizeof(esp_tracedata_hdr_t));
|
||||
|
@ -772,7 +774,7 @@ static esp_err_t esp_apptrace_trax_put_buffer(uint8_t *ptr, uint32_t *tmo)
|
|||
return res;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_flush(uint32_t min_sz, uint32_t tmo)
|
||||
static esp_err_t esp_apptrace_trax_flush(uint32_t min_sz, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
int res = ESP_OK;
|
||||
|
||||
|
@ -782,7 +784,7 @@ static esp_err_t esp_apptrace_trax_flush(uint32_t min_sz, uint32_t tmo)
|
|||
}
|
||||
// switch TRAX block while size of data is more than min size
|
||||
while (ESP_APPTRACE_TRAX_INBLOCK_MARKER() > 0) {
|
||||
ESP_APPTRACE_LOGD("Try to flush %d bytes. Wait until block switch for %u us", ESP_APPTRACE_TRAX_INBLOCK_MARKER(), tmo);
|
||||
ESP_APPTRACE_LOGD("Try to flush %d bytes. Wait until block switch for %u us", ESP_APPTRACE_TRAX_INBLOCK_MARKER(), tmo->tmo);
|
||||
res = esp_apptrace_trax_block_switch_waitus(tmo);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to switch to another block!");
|
||||
|
@ -810,7 +812,6 @@ static esp_err_t esp_apptrace_trax_dest_init()
|
|||
sizeof(s_trace_buf.trax.pending_chunk_sz));
|
||||
#endif
|
||||
#endif
|
||||
esp_apptrace_trax_down_buf_init();
|
||||
|
||||
DPORT_WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, DPORT_PRO_TRACEMEM_ENA_M);
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
|
@ -849,25 +850,31 @@ esp_err_t esp_apptrace_init()
|
|||
esp_apptrace_trax_init();
|
||||
#endif
|
||||
|
||||
// disabled by default
|
||||
esp_apptrace_rb_init(&s_trace_buf.rb_down, NULL, 0);
|
||||
|
||||
s_trace_buf.inited |= 1 << xPortGetCoreID(); // global and this CPU-specific data are inited
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, size_t *size, uint32_t user_tmo)
|
||||
void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size)
|
||||
{
|
||||
esp_apptrace_rb_init(&s_trace_buf.rb_down, buf, size);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, uint32_t *size, uint32_t user_tmo)
|
||||
{
|
||||
uint8_t *ptr = NULL;
|
||||
uint32_t tmo = user_tmo;
|
||||
int res = ESP_OK;
|
||||
esp_apptrace_tmo_t sleeping_tmo;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
//TODO: use ptr to HW transport iface struct
|
||||
uint8_t *(*apptrace_get_down_buffer)(uint32_t *, uint32_t *);
|
||||
esp_err_t (*apptrace_put_down_buffer)(uint8_t *, uint32_t , uint32_t *);
|
||||
uint8_t *(*apptrace_get_down_buffer)(uint32_t *, esp_apptrace_tmo_t *);
|
||||
esp_err_t (*apptrace_put_down_buffer)(uint8_t *, esp_apptrace_tmo_t *);
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
apptrace_get_down_buffer = esp_apptrace_trax_get_down_rdptr;
|
||||
apptrace_put_down_buffer = esp_apptrace_trax_put_down_rdptr;
|
||||
apptrace_get_down_buffer = esp_apptrace_trax_down_buffer_get;
|
||||
apptrace_put_down_buffer = esp_apptrace_trax_down_buffer_put;
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
|
@ -878,31 +885,72 @@ esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, size_t *size, u
|
|||
}
|
||||
|
||||
//TODO: callback system
|
||||
esp_apptrace_tmo_init(&sleeping_tmo, tmo);
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
uint32_t act_sz = *size;
|
||||
while ((ptr = apptrace_get_down_buffer(&act_sz, &tmo)) == NULL ) {
|
||||
res = esp_apptrace_tmo_check(&sleeping_tmo);
|
||||
if (res != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*size = 0;
|
||||
uint8_t * ptr = apptrace_get_down_buffer(&act_sz, &tmo);
|
||||
if (ptr && act_sz > 0) {
|
||||
ESP_APPTRACE_LOGD("Read %d bytes from host", act_sz);
|
||||
memcpy(buf, ptr, act_sz);
|
||||
res = apptrace_put_down_buffer(ptr, act_sz, &tmo);
|
||||
res = apptrace_put_down_buffer(ptr, &tmo);
|
||||
*size = act_sz;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, size_t size, uint32_t user_tmo)
|
||||
uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t user_tmo)
|
||||
{
|
||||
esp_apptrace_tmo_t tmo;
|
||||
//TODO: use ptr to HW transport iface struct
|
||||
uint8_t *(*apptrace_get_down_buffer)(uint32_t *, esp_apptrace_tmo_t *);
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
apptrace_get_down_buffer = esp_apptrace_trax_down_buffer_get;
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
return NULL;
|
||||
#endif
|
||||
} else {
|
||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ESP_APPTRACE_LOGE("esp_apptrace_down_buffer_get %d", *size);
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
return apptrace_get_down_buffer(size, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
|
||||
{
|
||||
esp_apptrace_tmo_t tmo;
|
||||
//TODO: use ptr to HW transport iface struct
|
||||
esp_err_t (*apptrace_put_down_buffer)(uint8_t *, esp_apptrace_tmo_t *);
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
apptrace_put_down_buffer = esp_apptrace_trax_down_buffer_put;
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
} else {
|
||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
return apptrace_put_down_buffer(ptr, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_t size, uint32_t user_tmo)
|
||||
{
|
||||
uint8_t *ptr = NULL;
|
||||
uint32_t tmo = user_tmo;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
//TODO: use ptr to HW transport iface struct
|
||||
uint8_t *(*apptrace_get_buffer)(size_t, uint32_t *);
|
||||
esp_err_t (*apptrace_put_buffer)(uint8_t *, uint32_t *);
|
||||
uint8_t *(*apptrace_get_buffer)(uint32_t, esp_apptrace_tmo_t *);
|
||||
esp_err_t (*apptrace_put_buffer)(uint8_t *, esp_apptrace_tmo_t *);
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
|
@ -917,6 +965,7 @@ esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, size_t
|
|||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
ptr = apptrace_get_buffer(size, &tmo);
|
||||
if (ptr == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
|
@ -934,10 +983,10 @@ int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const c
|
|||
{
|
||||
uint16_t nargs = 0;
|
||||
uint8_t *pout, *p = (uint8_t *)fmt;
|
||||
uint32_t tmo = user_tmo;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
//TODO: use ptr to HW transport iface struct
|
||||
uint8_t *(*apptrace_get_buffer)(size_t, uint32_t *);
|
||||
esp_err_t (*apptrace_put_buffer)(uint8_t *, uint32_t *);
|
||||
uint8_t *(*apptrace_get_buffer)(uint32_t, esp_apptrace_tmo_t *);
|
||||
esp_err_t (*apptrace_put_buffer)(uint8_t *, esp_apptrace_tmo_t *);
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
|
@ -952,6 +1001,7 @@ int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const c
|
|||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
ESP_APPTRACE_LOGD("fmt %x", fmt);
|
||||
while ((p = (uint8_t *)strchr((char *)p, '%')) && nargs < ESP_APPTRACE_MAX_VPRINTF_ARGS) {
|
||||
p++;
|
||||
|
@ -995,11 +1045,11 @@ int esp_apptrace_vprintf(const char *fmt, va_list ap)
|
|||
return esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_TRAX, /*ESP_APPTRACE_TMO_INFINITE*/0, fmt, ap);
|
||||
}
|
||||
|
||||
uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, size_t size, uint32_t user_tmo)
|
||||
uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32_t user_tmo)
|
||||
{
|
||||
uint32_t tmo = user_tmo;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
//TODO: use ptr to HW transport iface struct
|
||||
uint8_t *(*apptrace_get_buffer)(size_t, uint32_t *);
|
||||
uint8_t *(*apptrace_get_buffer)(uint32_t, esp_apptrace_tmo_t *);
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
|
@ -1013,14 +1063,15 @@ uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, size_t size, uint32_t
|
|||
return NULL;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
return apptrace_get_buffer(size, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
|
||||
{
|
||||
uint32_t tmo = user_tmo;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
//TODO: use ptr to HW transport iface struct
|
||||
esp_err_t (*apptrace_put_buffer)(uint8_t *, uint32_t *);
|
||||
esp_err_t (*apptrace_put_buffer)(uint8_t *, esp_apptrace_tmo_t *);
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
|
@ -1034,13 +1085,15 @@ esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32
|
|||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
return apptrace_put_buffer(ptr, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t tmo)
|
||||
esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t usr_tmo)
|
||||
{
|
||||
esp_apptrace_tmo_t tmo;
|
||||
//TODO: use ptr to HW transport iface struct
|
||||
esp_err_t (*apptrace_flush)(uint32_t, uint32_t);
|
||||
esp_err_t (*apptrace_flush)(uint32_t, esp_apptrace_tmo_t *);
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
|
@ -1054,20 +1107,23 @@ esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, u
|
|||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return apptrace_flush(min_sz, tmo);
|
||||
esp_apptrace_tmo_init(&tmo, usr_tmo);
|
||||
return apptrace_flush(min_sz, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t tmo)
|
||||
esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t usr_tmo)
|
||||
{
|
||||
int res;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, usr_tmo);
|
||||
res = esp_apptrace_lock(&tmo);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to lock apptrace data (%d)!", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = esp_apptrace_flush_nolock(dest, 0, tmo);
|
||||
res = esp_apptrace_flush_nolock(dest, 0, esp_apptrace_tmo_remaining_us(&tmo));
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to flush apptrace data (%d)!", res);
|
||||
}
|
||||
|
|
|
@ -17,38 +17,39 @@
|
|||
#include "esp_app_trace_util.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// LOCK ////////////////////////////////////////
|
||||
///////////////////////////////// TIMEOUT /////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define ESP_TEST_CPUTICKS2US(_t_) ((_t_)/(XT_CLOCK_FREQ/1000000))
|
||||
// TODO: get actual clock from PLL config
|
||||
#define ESP_APPTRACE_CPUTICKS2US(_t_) ((_t_)/(XT_CLOCK_FREQ/1000000))
|
||||
|
||||
esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
unsigned cur, elapsed;
|
||||
|
||||
if (tmo->tmo != 0xFFFFFFFF) {
|
||||
cur = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
if (tmo->tmo != ESP_APPTRACE_TMO_INFINITE) {
|
||||
unsigned cur = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
if (tmo->start <= cur) {
|
||||
elapsed = cur - tmo->start;
|
||||
tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(cur - tmo->start);
|
||||
} else {
|
||||
elapsed = 0xFFFFFFFF - tmo->start + cur;
|
||||
tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(0xFFFFFFFF - tmo->start + cur);
|
||||
}
|
||||
if (ESP_TEST_CPUTICKS2US(elapsed) >= tmo->tmo) {
|
||||
if (tmo->elapsed >= tmo->tmo) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, uint32_t tmo)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// LOCK ////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
uint32_t res;
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
uint32_t recCnt;
|
||||
#endif
|
||||
esp_apptrace_tmo_t sleeping_tmo;
|
||||
|
||||
esp_apptrace_tmo_init(&sleeping_tmo, tmo);
|
||||
while (1) {
|
||||
res = (xPortGetCoreID() << portMUX_VAL_SHIFT) | portMUX_MAGIC_VAL;
|
||||
// first disable IRQs on this CPU, this will prevent current task from been
|
||||
|
@ -77,7 +78,7 @@ esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, uint32_t tmo)
|
|||
// if mux is locked by other task/ISR enable IRQs and let other guys work
|
||||
portEXIT_CRITICAL_NESTED(irq_stat);
|
||||
|
||||
int err = esp_apptrace_tmo_check(&sleeping_tmo);
|
||||
int err = esp_apptrace_tmo_check(tmo);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
@ -205,3 +206,19 @@ uint32_t esp_apptrace_rb_read_size_get(esp_apptrace_rb_t *rb)
|
|||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t esp_apptrace_rb_write_size_get(esp_apptrace_rb_t *rb)
|
||||
{
|
||||
uint32_t size = 0;
|
||||
if (rb->rd <= rb->wr) {
|
||||
// |?R......W??|
|
||||
size = rb->size - rb->wr;
|
||||
if (size && rb->rd == 0) {
|
||||
size--;
|
||||
}
|
||||
} else {
|
||||
// |?W......R??|
|
||||
size = rb->rd - rb->wr - 1;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -16,10 +16,7 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
#include "esp_err.h"
|
||||
#include "freertos/portmacro.h"
|
||||
|
||||
/** Infinite waiting timeout */
|
||||
#define ESP_APPTRACE_TMO_INFINITE ((uint32_t)-1)
|
||||
#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
|
||||
|
||||
/**
|
||||
* Application trace data destinations bits.
|
||||
|
@ -38,6 +35,16 @@ typedef enum {
|
|||
*/
|
||||
esp_err_t esp_apptrace_init();
|
||||
|
||||
/**
|
||||
* @brief Configures down buffer.
|
||||
* @note Needs to be called before initiating any data transfer using esp_apptrace_buffer_get and esp_apptrace_write.
|
||||
* This function does not protect internal data by lock.
|
||||
*
|
||||
* @param buf Address of buffer to use for down channel (host to target) data.
|
||||
* @param size Size of the buffer.
|
||||
*/
|
||||
void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Allocates buffer for trace data.
|
||||
* After data in buffer are ready to be sent off esp_apptrace_buffer_put must be called to indicate it.
|
||||
|
@ -48,11 +55,11 @@ esp_err_t esp_apptrace_init();
|
|||
*
|
||||
* @return non-NULL on success, otherwise NULL.
|
||||
*/
|
||||
uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, size_t size, uint32_t tmo);
|
||||
uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Indicates that the data in buffer are ready to be sent off.
|
||||
* This function is a counterpart of must be preceeded by esp_apptrace_buffer_get.
|
||||
* This function is a counterpart of and must be preceeded by esp_apptrace_buffer_get.
|
||||
*
|
||||
* @param dest Indicates HW interface to send data. Should be identical to the same parameter in call to esp_apptrace_buffer_get.
|
||||
* @param ptr Address of trace buffer to release. Should be the value returned by call to esp_apptrace_buffer_get.
|
||||
|
@ -72,7 +79,7 @@ esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32
|
|||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, size_t size, uint32_t tmo);
|
||||
esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_t size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief vprintf-like function to sent log messages to host via specified HW interface.
|
||||
|
@ -128,7 +135,30 @@ esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, u
|
|||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *data, size_t *size, uint32_t tmo);
|
||||
esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *data, uint32_t *size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Rertrieves incoming data buffer if any.
|
||||
* After data in buffer are processed esp_apptrace_down_buffer_put must be called to indicate it.
|
||||
*
|
||||
* @param dest Indicates HW interface to receive data.
|
||||
* @param size Address to store size of available data in down buffer. Must be initializaed with requested value.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return non-NULL on success, otherwise NULL.
|
||||
*/
|
||||
uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Indicates that the data in down buffer are processesd.
|
||||
* This function is a counterpart of and must be preceeded by esp_apptrace_down_buffer_get.
|
||||
*
|
||||
* @param dest Indicates HW interface to receive data. Should be identical to the same parameter in call to esp_apptrace_down_buffer_get.
|
||||
* @param ptr Address of trace buffer to release. Should be the value returned by call to esp_apptrace_down_buffer_get.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t tmo);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,9 +14,49 @@
|
|||
#ifndef ESP_APP_TRACE_UTIL_H_
|
||||
#define ESP_APP_TRACE_UTIL_H_
|
||||
|
||||
#include "freertos/portmacro.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
/** Infinite waiting timeout */
|
||||
#define ESP_APPTRACE_TMO_INFINITE ((uint32_t)-1)
|
||||
|
||||
/** Structure which holds data necessary for measuring time intervals.
|
||||
*
|
||||
* After initialization via esp_apptrace_tmo_init() user needs to call esp_apptrace_tmo_check()
|
||||
* periodically to check timeout for expiration.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t start; ///< time interval start (in CPU ticks)
|
||||
uint32_t tmo; ///< timeout value (in us)
|
||||
uint32_t elapsed; ///< elapsed time (in us)
|
||||
} esp_apptrace_tmo_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes timeout structure.
|
||||
*
|
||||
* @param tmo Pointer to timeout structure to be initialized.
|
||||
* @param user_tmo Timeout value (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*/
|
||||
static inline void esp_apptrace_tmo_init(esp_apptrace_tmo_t *tmo, uint32_t user_tmo)
|
||||
{
|
||||
tmo->start = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
tmo->tmo = user_tmo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks timeout for expiration.
|
||||
*
|
||||
* @param tmo Pointer to timeout structure to be initialized.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise \see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo);
|
||||
|
||||
static inline uint32_t esp_apptrace_tmo_remaining_us(esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
return tmo->tmo != ESP_APPTRACE_TMO_INFINITE ? (tmo->elapsed - tmo->tmo) : ESP_APPTRACE_TMO_INFINITE;
|
||||
}
|
||||
|
||||
/** Tracing module synchronization lock */
|
||||
typedef struct {
|
||||
volatile unsigned int irq_stat; ///< local (on 1 CPU) IRQ state
|
||||
|
@ -38,11 +78,11 @@ static inline void esp_apptrace_lock_init(esp_apptrace_lock_t *lock)
|
|||
* @brief Tries to acquire lock in specified time period.
|
||||
*
|
||||
* @param lock Pointer to lock structure.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
* @param tmo Pointer to timeout struct.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise \see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, uint32_t tmo);
|
||||
esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *tmo);
|
||||
|
||||
/**
|
||||
* @brief Releases lock.
|
||||
|
@ -53,39 +93,6 @@ esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, uint32_t tmo);
|
|||
*/
|
||||
esp_err_t esp_apptrace_lock_give(esp_apptrace_lock_t *lock);
|
||||
|
||||
|
||||
/** Structure which holds data necessary for measuring time intervals.
|
||||
*
|
||||
* After initialization via esp_apptrace_tmo_init() user needs to call esp_apptrace_tmo_check()
|
||||
* periodically to check timeout for expiration.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t start; ///< time interval start (in ticks)
|
||||
uint32_t tmo; ///< timeout value (in us)
|
||||
} esp_apptrace_tmo_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes timeout structure.
|
||||
*
|
||||
* @param tmo Pointer to timeout structure to be initialized.
|
||||
* @param user_tmo Timeout value (in us).
|
||||
*/
|
||||
static inline void esp_apptrace_tmo_init(esp_apptrace_tmo_t *tmo, uint32_t user_tmo)
|
||||
{
|
||||
tmo->start = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
tmo->tmo = user_tmo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks timeout for expiration.
|
||||
*
|
||||
* @param tmo Pointer to timeout structure to be initialized.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise \see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo);
|
||||
|
||||
|
||||
/** Ring buffer control structure.
|
||||
*
|
||||
* @note For purposes of application tracing module if there is no enough space for user data and write pointer can be wrapped
|
||||
|
@ -93,10 +100,10 @@ esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo);
|
|||
*/
|
||||
typedef struct {
|
||||
uint8_t *data; ///< pointer to data storage
|
||||
uint32_t size; ///< size of data storage
|
||||
uint32_t cur_size; ///< current size of data storage
|
||||
uint32_t rd; ///< read pointer
|
||||
uint32_t wr; ///< write pointer
|
||||
volatile uint32_t size; ///< size of data storage
|
||||
volatile uint32_t cur_size; ///< current size of data storage
|
||||
volatile uint32_t rd; ///< read pointer
|
||||
volatile uint32_t wr; ///< write pointer
|
||||
} esp_apptrace_rb_t;
|
||||
|
||||
/**
|
||||
|
@ -145,4 +152,15 @@ uint8_t *esp_apptrace_rb_consume(esp_apptrace_rb_t *rb, uint32_t size);
|
|||
*/
|
||||
uint32_t esp_apptrace_rb_read_size_get(esp_apptrace_rb_t *rb);
|
||||
|
||||
/**
|
||||
* @brief Gets size of memory which can produced with single call to esp_apptrace_rb_produce().
|
||||
*
|
||||
* @param rb Pointer to ring buffer structure.
|
||||
*
|
||||
* @return Size of memory which can produced.
|
||||
*
|
||||
* @note Due to write pointer wrapping returned size can be less then the total size of available data.
|
||||
*/
|
||||
uint32_t esp_apptrace_rb_write_size_get(esp_apptrace_rb_t *rb);
|
||||
|
||||
#endif //ESP_APP_TRACE_UTIL_H_
|
|
@ -322,7 +322,9 @@ void SEGGER_SYSVIEW_X_RTT_Unlock()
|
|||
|
||||
void SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
{
|
||||
esp_apptrace_lock_take(&s_sys_view_lock, SEGGER_LOCK_WAIT_TMO);
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, SEGGER_LOCK_WAIT_TMO);
|
||||
esp_apptrace_lock_take(&s_sys_view_lock, &tmo);
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_X_SysView_Unlock()
|
||||
|
|
|
@ -36,11 +36,14 @@ const static char *TAG = "segger_rtt";
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define SEGGER_HOST_WAIT_TMO 500 //us
|
||||
#define SEGGER_STOP_WAIT_TMO 1000000 //us
|
||||
// size of down channel data buf
|
||||
#define SYSVIEW_DOWN_BUF_SIZE 32
|
||||
#define SEGGER_HOST_WAIT_TMO 500 //us
|
||||
#define SEGGER_STOP_WAIT_TMO 1000000 //us
|
||||
|
||||
static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ];
|
||||
static uint16_t s_events_buf_filled;
|
||||
static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
|
@ -216,6 +219,7 @@ int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBu
|
|||
* Buffer name and flags can be reconfigured using the appropriate functions.
|
||||
*/
|
||||
int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
|
||||
esp_apptrace_down_buffer_config(s_down_buf, sizeof(s_down_buf));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ To use logging via JTAG user needs to perform the following steps:
|
|||
2. Build the program image and download it to target as described in :idf:`Developing With the ESP-IDF` section.
|
||||
3. Run OpenOCD (see :idf:`OpenOCD setup for ESP32` section).
|
||||
4. Connect to OpenOCD telnet server. On Linux it can be done using the following command in terminal ``telnet <oocd_host> 4444``. If telnet session is opened on the same machine which runs OpenOCD you can use `localhost` as `<oocd_host>` in the command.
|
||||
5. Run the following command in OpenOCD telnet session: ``esp108 apptrace start /path/to/trace/file -1 -1 0 0 1``. This command will wait for board reset and transfer tracing data at the highest possible rate.
|
||||
5. Run the following command in OpenOCD telnet session: ``esp108 apptrace start /path/to/trace/file 0 -1 -1 1``. This command will wait for board reset and transfer tracing data at the highest possible rate.
|
||||
6. Reset the board. Logging to host will start automatically.
|
||||
7. ``esp108 apptrace`` command with given arguments will never return (see other command options below), so you must stop it manually by resetting the board or pressing CTRL+C in OpenOCD window (not one with the telnet session).
|
||||
8. Reset board or press CTRL+C in OpenOCD window (not one with the telnet session) when tracing is completed (for the example code above after the message `"Tracing is finished."` appears on UART).
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
uint32_t eri_read(int addr) {
|
||||
uint32_t ret;
|
||||
asm(
|
||||
asm volatile (
|
||||
"RER %0,%1"
|
||||
:"=r"(ret):"r"(addr)
|
||||
);
|
||||
|
|
|
@ -13,7 +13,7 @@ Developers can use this library to send application specific state of execution
|
|||
|
||||
Tracing components when working over JTAG interface are shown in the figure below.
|
||||
|
||||
.. figure:: ../_static/app_trace/overview.png
|
||||
.. figure:: ../_static/app_trace/overview.jpg
|
||||
:align: center
|
||||
:alt: Tracing Components when Working Over JTAG
|
||||
:figclass: align-center
|
||||
|
@ -80,13 +80,13 @@ In general user should decide what type of data should be transferred in every d
|
|||
#include "esp_app_trace.h"
|
||||
...
|
||||
int number = 10;
|
||||
char *ptr = (char *)esp_apptrace_buffer_get(32, 100/*tmo in us*/);
|
||||
char *ptr = (char *)esp_apptrace_buffer_get(ESP_APPTRACE_DEST_TRAX, 32, 100/*tmo in us*/);
|
||||
if (ptr == NULL) {
|
||||
ESP_LOGE("Failed to get buffer!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
sprintf(ptr, "Here is the number %d", number);
|
||||
esp_err_t res = esp_apptrace_buffer_put(ptr, 100/*tmo in us*/);
|
||||
esp_err_t res = esp_apptrace_buffer_put(ESP_APPTRACE_DEST_TRAX, ptr, 100/*tmo in us*/);
|
||||
if (res != ESP_OK) {
|
||||
/* in case of error host tracing tool (e.g. OpenOCD) will report incomplete user buffer */
|
||||
ESP_LOGE("Failed to put buffer!");
|
||||
|
@ -100,7 +100,11 @@ Also according to his needs user may want to receive data from the host. Piece o
|
|||
#include "esp_app_trace.h"
|
||||
...
|
||||
char buf[32];
|
||||
char down_buf[32];
|
||||
size_t sz = sizeof(buf);
|
||||
|
||||
/* config down buffer */
|
||||
esp_apptrace_down_buffer_config(down_buf, sizeof(down_buf));
|
||||
/* check for incoming data and read them if any */
|
||||
esp_err_t res = esp_apptrace_read(ESP_APPTRACE_DEST_TRAX, buf, &sz, 0/*do not wait*/);
|
||||
if (res != ESP_OK) {
|
||||
|
@ -112,6 +116,37 @@ Also according to his needs user may want to receive data from the host. Piece o
|
|||
...
|
||||
}
|
||||
|
||||
``esp_apptrace_read()`` function uses memcpy to copy host data to user buffer. In some cases it can be more optimal to use ``esp_apptrace_down_buffer_get()`` and ``esp_apptrace_down_buffer_put()`` functions.
|
||||
They allow developers to ocupy chunk of read buffer and process it in-place. The following piece of code shows how to do this.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "esp_app_trace.h"
|
||||
...
|
||||
char down_buf[32];
|
||||
uint32_t *number;
|
||||
size_t sz = 32;
|
||||
|
||||
/* config down buffer */
|
||||
esp_apptrace_down_buffer_config(down_buf, sizeof(down_buf));
|
||||
char *ptr = (char *)esp_apptrace_down_buffer_get(ESP_APPTRACE_DEST_TRAX, &sz, 100/*tmo in us*/);
|
||||
if (ptr == NULL) {
|
||||
ESP_LOGE("Failed to get buffer!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (sz > 4) {
|
||||
number = (uint32_t *)ptr;
|
||||
printf("Here is the number %d", *number);
|
||||
} else {
|
||||
printf("No data");
|
||||
}
|
||||
esp_err_t res = esp_apptrace_down_buffer_put(ESP_APPTRACE_DEST_TRAX, ptr, 100/*tmo in us*/);
|
||||
if (res != ESP_OK) {
|
||||
/* in case of error host tracing tool (e.g. OpenOCD) will report incomplete user buffer */
|
||||
ESP_LOGE("Failed to put buffer!");
|
||||
return res;
|
||||
}
|
||||
|
||||
2. The next step is to build the program image and download it to the target as described in :doc:`Build and Flash <../get-started/make-project>`.
|
||||
3. Run OpenOCD (see :doc:`JTAG Debugging <../api-guides/jtag-debugging/index>`).
|
||||
4. Connect to OpenOCD telnet server. On Linux it can be done using the following command in terminal ``telnet <oocd_host> 4444``. If telnet session is opened on the same machine which runs OpenOCD you can use ``localhost`` as ``<oocd_host>`` in the command above.
|
||||
|
@ -151,7 +186,7 @@ Sub-commands:
|
|||
|
||||
Start command syntax:
|
||||
|
||||
``start <outfile1> [outfile2] [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]``
|
||||
``start <outfile> [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]``
|
||||
|
||||
.. list-table::
|
||||
:widths: 20 80
|
||||
|
@ -159,10 +194,8 @@ Start command syntax:
|
|||
|
||||
* - Argument
|
||||
- Description
|
||||
* - outfile1
|
||||
- Path to file to save data from PRO CPU. This argument should have the following format: ``file://path/to/file``.
|
||||
* - outfile2
|
||||
- Path to file to save data from APP CPU. This argument should have the following format: ``file://path/to/file``.
|
||||
* - outfile
|
||||
- Path to file to save data from both CPUs. This argument should have the following format: ``file://path/to/file``.
|
||||
* - poll_period
|
||||
- Data polling period (in ms). If greater then 0 then command runs in non-blocking mode. By default 1 ms.
|
||||
* - trace_size
|
||||
|
|
|
@ -88,7 +88,9 @@ CONFIG_APP_OFFSET=0x10000
|
|||
#
|
||||
CONFIG_OPTIMIZATION_LEVEL_DEBUG=y
|
||||
# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set
|
||||
CONFIG_OPTIMIZATION_ASSERTIONS=y
|
||||
CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
|
||||
# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set
|
||||
# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set
|
||||
|
||||
#
|
||||
# Component config
|
||||
|
@ -100,6 +102,7 @@ CONFIG_OPTIMIZATION_ASSERTIONS=y
|
|||
# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set
|
||||
CONFIG_ESP32_APPTRACE_DEST_NONE=y
|
||||
# CONFIG_ESP32_APPTRACE_ENABLE is not set
|
||||
CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
|
||||
|
||||
#
|
||||
# FreeRTOS SystemView Tracing
|
||||
|
@ -149,6 +152,16 @@ CONFIG_INT_WDT=y
|
|||
CONFIG_INT_WDT_TIMEOUT_MS=300
|
||||
CONFIG_INT_WDT_CHECK_CPU1=y
|
||||
# CONFIG_TASK_WDT is not set
|
||||
CONFIG_BROWNOUT_DET=y
|
||||
CONFIG_BROWNOUT_DET_LVL_SEL_0=y
|
||||
# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set
|
||||
# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set
|
||||
# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set
|
||||
# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set
|
||||
# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set
|
||||
# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set
|
||||
# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set
|
||||
CONFIG_BROWNOUT_DET_LVL=0
|
||||
# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set
|
||||
CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y
|
||||
# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set
|
||||
|
@ -227,6 +240,7 @@ CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y
|
|||
# CONFIG_FREERTOS_ASSERT_DISABLE is not set
|
||||
CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG=y
|
||||
# CONFIG_ENABLE_MEMORY_DEBUG is not set
|
||||
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024
|
||||
CONFIG_FREERTOS_ISR_STACKSIZE=1536
|
||||
# CONFIG_FREERTOS_LEGACY_HOOKS is not set
|
||||
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
|
||||
|
|
Loading…
Reference in a new issue