Example #1
0
int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence)
{
    esp_apptrace_fseek_args_t cmd_args;

    ESP_EARLY_LOGV(TAG, "esp_apptrace_fseek f %p o 0x%lx w %d", stream, offset, whence);

    cmd_args.file = stream;
    cmd_args.offset = offset;
    cmd_args.whence = whence;
    esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
                        &cmd_args, sizeof(cmd_args));
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
        return -1;
    }

    // now read the answer
    int resp;
    ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
        return -1;
    }

    return resp;
}
/**
 * @brief Initialize regions of memory to the collection of heaps at runtime.
 */
void esp_heap_caps_init_region(heap_region_t *region, size_t max_num)
{
    uint8_t num;
    mem_blk_t *mem_start, *mem_end;

    for (num = 0; num < max_num; num++) {
        mem_start = (mem_blk_t *)HEAP_ALIGN(region[num].start_addr);
        mem_end = (mem_blk_t *)(HEAP_ALIGN(region[num].start_addr + region[num].total_size));
        if ((uint8_t *)mem_end != region[num].start_addr + region[num].total_size)
            mem_end = (mem_blk_t *)((uint8_t *)mem_end - sizeof(void *));
        mem_end = (mem_blk_t *)((uint8_t *)mem_end - MEM_HEAD_SIZE);

        ESP_EARLY_LOGV(TAG, "heap %d start from %p to %p total %d bytes, mem_blk from %p to %p total",
                            num, region[num].start_addr, region[num].start_addr + region[num].total_size,
                            region[num].total_size, mem_start, mem_end);

        mem_start->prev = NULL;
        mem_start->next = mem_end;

        mem_end->prev = mem_start;
        mem_end->next = NULL;

        g_heap_region[num].free_blk = mem_start;
        g_heap_region[num].min_free_bytes = g_heap_region[num].free_bytes = blk_link_size(mem_start);
    }
}
Example #3
0
static esp_err_t esp_apptrace_file_cmd_send(esp_apptrace_dest_t dest, uint8_t cmd, void (*prep_args)(uint8_t *, void *), void *args, uint32_t args_len)
{
    esp_err_t ret;
    esp_apptrace_fcmd_hdr_t *hdr;

    ESP_EARLY_LOGV(TAG, "%s %d", __func__, cmd);
    uint8_t *ptr = esp_apptrace_buffer_get(dest, sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
    if (ptr == NULL) {
        return ESP_ERR_NO_MEM;
    }

    hdr = (esp_apptrace_fcmd_hdr_t *)ptr;
    hdr->cmd = cmd;
    if (prep_args) {
        prep_args(ptr + sizeof(hdr->cmd), args);
    }

    // now indicate that this buffer is ready to be sent off to host
    ret = esp_apptrace_buffer_put(dest, ptr, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to put apptrace buffer (%d)!", ret);
        return ret;
    }

    ret = esp_apptrace_flush(dest, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to flush apptrace buffer (%d)!", ret);
        return ret;
    }

    return ESP_OK;
}
Example #4
0
size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream)
{
    esp_apptrace_fread_args_t cmd_args;

    ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size*nmemb);

    cmd_args.size = size * nmemb;
    cmd_args.file = stream;
    esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
                        &cmd_args, sizeof(cmd_args));
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
        return 0;
    }

    // now read the answer
    size_t resp;
    ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
        return 0;
    }
    if (resp > 0) {
        ret = esp_apptrace_file_rsp_recv(dest, ptr, resp);
        if (ret != ESP_OK) {
            ESP_EARLY_LOGE(TAG, "Failed to read file data (%d)!", ret);
            return 0;
        }
    }
    return resp;
}
Example #5
0
size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream)
{
    esp_apptrace_fwrite_args_t cmd_args;

    ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size*nmemb);

    cmd_args.buf = (void *)ptr;
    cmd_args.size = size * nmemb;
    cmd_args.file = stream;
    esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
                        &cmd_args, sizeof(cmd_args.file)+cmd_args.size);
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
        return 0;
    }

    // now read the answer
    size_t resp;
    ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
        return 0;
    }

    return resp;
}
Example #6
0
void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode)
{
    esp_apptrace_fopen_args_t cmd_args;

    ESP_EARLY_LOGV(TAG, "esp_apptrace_fopen '%s' '%s'", path, mode);

    cmd_args.path = path;
    cmd_args.path_len = strlen(path) + 1;
    cmd_args.mode = mode;
    cmd_args.mode_len = strlen(mode) + 1;

    esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
                        &cmd_args, cmd_args.path_len+cmd_args.mode_len);
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
        return NULL;
    }

    // now read the answer
    void *resp;
    ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
        return NULL;
    }

    return resp;
}
Example #7
0
int esp_apptrace_fstop(esp_apptrace_dest_t dest)
{
    ESP_EARLY_LOGV(TAG, "%s", __func__);
    esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0);
    if (ret != ESP_OK) {
        ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret);
    }
    return ret;
}
Example #8
0
static esp_err_t esp_apptrace_file_rsp_recv(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t buf_len)
{
    uint32_t tot_rd = 0;
    while (tot_rd < buf_len) {
        uint32_t rd_size = buf_len - tot_rd;
        esp_err_t ret = esp_apptrace_read(dest, buf + tot_rd, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
        if (ret != ESP_OK) {
            ESP_EARLY_LOGE(TAG, "Failed to read (%d)!", ret);
            return ret;
        }
        ESP_EARLY_LOGV(TAG, "%s read %d bytes", __FUNCTION__, rd_size);
        tot_rd += rd_size;
    }

    return ESP_OK;
}
/**
 * @brief Allocate a chunk of memory which has the given capabilities
 */
void IRAM_ATTR *_heap_caps_malloc(size_t size, uint32_t caps, const char *file, size_t line)
{
    mem_blk_t *mem_blk, *next_mem_blk;
    void *ret_mem = NULL;
    uint32_t num;
    uint32_t mem_blk_size;

    if (line == 0) {
        ESP_EARLY_LOGV(TAG, "caller func %p", file);
    } else {
        ESP_EARLY_LOGV(TAG, "caller file %s line %d", file, line);
    }

    for (num = 0; num < HEAP_REGIONS_MAX; num++) {
        bool trace;
        size_t head_size;

        if ((g_heap_region[num].caps & caps) != caps)
            continue;

        _heap_caps_lock(num);

        trace = __g_heap_trace_mode == HEAP_TRACE_LEAKS;

        mem_blk_size = ptr2memblk_size(size, trace);

        ESP_EARLY_LOGV(TAG, "malloc size is %d(%x) blk size is %d(%x) region is %d", size, size,
                            mem_blk_size, mem_blk_size, num);

        if (mem_blk_size > g_heap_region[num].free_bytes)
            goto next_region;

        mem_blk = (mem_blk_t *)g_heap_region[num].free_blk;

        ESP_EARLY_LOGV(TAG, "malloc start %p", mem_blk);

        while (mem_blk && !mem_blk_is_end(mem_blk) && (mem_blk_is_used(mem_blk) || blk_link_size(mem_blk) < mem_blk_size)) {
            ESP_EARLY_LOGV(TAG, "malloc mem_blk %p next %p used %x traced %x, size %d", mem_blk, mem_blk_next(mem_blk),
                                mem_blk_is_used(mem_blk), mem_blk_is_traced(mem_blk), blk_link_size(mem_blk));
            mem_blk = mem_blk_next(mem_blk);
        }

        ESP_EARLY_LOGV(TAG, "malloc end %p, end %d", mem_blk, mem_blk_is_end(mem_blk));

        if (!mem_blk || mem_blk_is_end(mem_blk))
            goto next_region;

        ret_mem = blk2ptr(mem_blk, trace);
        ESP_EARLY_LOGV(TAG, "ret_mem is %p", ret_mem);

        head_size = mem_blk_head_size(trace);

        if (blk_link_size(mem_blk) >= mem_blk_size + head_size + MEM_BLK_MIN)
            next_mem_blk = (mem_blk_t *)((uint8_t *)mem_blk + mem_blk_size);
        else 
            next_mem_blk = mem_blk_next(mem_blk);

        ESP_EARLY_LOGV(TAG, "next_mem_blk is %p", next_mem_blk);

        if (mem_blk_next(mem_blk) != next_mem_blk) {
            next_mem_blk->prev = next_mem_blk->next = NULL;

            mem_blk_set_prev(next_mem_blk, mem_blk);
            mem_blk_set_next(next_mem_blk, mem_blk_next(mem_blk));

            ESP_EARLY_LOGV(TAG, "mem_blk1 %p, mem_blk->prev %p(%p), mem_blk->next %p(%p)", mem_blk, mem_blk_prev(mem_blk),
                                mem_blk->prev, mem_blk_next(mem_blk), mem_blk->next);

            mem_blk_set_prev(mem_blk_next(mem_blk), next_mem_blk);
            mem_blk_set_next(mem_blk, next_mem_blk);
        }

        mem_blk_set_used(mem_blk);
        if (trace) {
            mem_blk_set_traced((mem2_blk_t *)mem_blk, file, line);
            ESP_EARLY_LOGV(TAG, "mem_blk1 %p set trace", mem_blk);
        }

        if (g_heap_region[num].free_blk == mem_blk) {
            mem_blk_t *free_blk = mem_blk;

            while (free_blk && !mem_blk_is_end(free_blk) && mem_blk_is_used(free_blk)) {
                free_blk = mem_blk_next(free_blk);
            }

            ESP_EARLY_LOGV(TAG, "reset free_blk from %p to %p", g_heap_region[num].free_blk, free_blk);
            g_heap_region[num].free_blk = free_blk;
        } else {
            ESP_EARLY_LOGV(TAG, "free_blk is %p", g_heap_region[num].free_blk);
        }

        mem_blk_size = blk_link_size(mem_blk);
        g_heap_region[num].free_bytes -= mem_blk_size;

        if (g_heap_region[num].min_free_bytes > g_heap_region[num].free_bytes)
            g_heap_region[num].min_free_bytes = g_heap_region[num].free_bytes;

        ESP_EARLY_LOGV(TAG, "mem_blk2 %p, mem_blk->prev %p(%p), mem_blk->next %p(%p)", mem_blk, mem_blk_prev(mem_blk),
                            mem_blk->prev, mem_blk_next(mem_blk), mem_blk->next);
        ESP_EARLY_LOGV(TAG, "next_mem_blk %p, next_mem_blk->prev %p(%p), next_mem_blk->next %p(%p)", next_mem_blk,
                            mem_blk_prev(next_mem_blk), next_mem_blk->prev, mem_blk_next(next_mem_blk), next_mem_blk->next);
        ESP_EARLY_LOGV(TAG, "last_mem_blk %p, last_mem_blk->prev %p(%p), last_mem_blk->next %p(%p)", mem_blk_next(next_mem_blk),
                            mem_blk_prev(mem_blk_next(next_mem_blk)), mem_blk_next(next_mem_blk)->prev, mem_blk_next(mem_blk_next(next_mem_blk)), mem_blk_next(next_mem_blk)->next);

next_region:
        _heap_caps_unlock(num);

        if (ret_mem)
            break;
    }

    ESP_EARLY_LOGV(TAG, "malloc return mem %p", ret_mem);

    return ret_mem;
}
/**
 * @brief Free memory previously allocated via heap_caps_(m/c/r/z)alloc().
 */
void IRAM_ATTR _heap_caps_free(void *ptr, const char *file, size_t line)
{
    int num;
    mem_blk_t *mem_blk;
    mem_blk_t *tmp, *next, *prev, *last;

    if ((int)line == 0) {
        ESP_EARLY_LOGV(TAG, "caller func %p", file);
    } else {
        ESP_EARLY_LOGV(TAG, "caller file %s line %d", file, line);
    }

    if (!ptr) {
        ESP_EARLY_LOGE(TAG, "free(ptr=NULL)");
        if ((int)line == 0) {
            ESP_EARLY_LOGE(TAG, "caller func %p", file);
        } else {
            ESP_EARLY_LOGE(TAG, "caller file %s line %d", file, line);
        }
        return;
    }

    num = get_blk_region(ptr);

    if (num >= HEAP_REGIONS_MAX) {
        ESP_EARLY_LOGE(TAG, "free(ptr_region=NULL)");
        return;
    }

    mem_blk = ptr2blk(ptr, ptr_is_traced(ptr));
    if (!mem_blk_is_used(mem_blk)) {
        ESP_EARLY_LOGE(TAG, "%p already freed\n", ptr);
        return;
    }

    ESP_EARLY_LOGV(TAG, "Free(ptr=%p, mem_blk=%p, region=%d)", ptr, mem_blk, num);

    _heap_caps_lock(num);

    g_heap_region[num].free_bytes += blk_link_size(mem_blk);

    ESP_EARLY_LOGV(TAG, "ptr prev=%p next=%p", mem_blk_prev(mem_blk), mem_blk_next(mem_blk));
    ESP_EARLY_LOGV(TAG, "ptr1 prev->next=%p next->prev=%p", mem_blk_prev(mem_blk) ? mem_blk_next(mem_blk_prev(mem_blk)) : NULL,
                        mem_blk_prev(mem_blk_next(mem_blk)));

    mem_blk_set_unused(mem_blk);
    mem_blk_set_untraced((mem2_blk_t *)mem_blk);

    prev = mem_blk_prev(mem_blk);
    next = mem_blk_next(mem_blk);
    last = mem_blk_next(next);

    if (prev && !mem_blk_is_used(prev)) {
        mem_blk_set_next(prev, next);
        mem_blk_set_prev(next, prev);
        tmp = prev;
    } else
        tmp = mem_blk;

    if (last && !mem_blk_is_used(next)) {
        mem_blk_set_next(tmp, last);
        mem_blk_set_prev(last, tmp);
    }

    ESP_EARLY_LOGV(TAG, "ptr2 prev->next=%p next->prev=%p", mem_blk_prev(mem_blk) ? mem_blk_next(mem_blk_prev(mem_blk)) : NULL,
                        mem_blk_prev(mem_blk_next(mem_blk)));

    if ((uint8_t *)mem_blk < (uint8_t *)g_heap_region[num].free_blk) {
        ESP_EARLY_LOGV(TAG, "Free update free block from %p to %p", g_heap_region[num].free_blk, mem_blk);
        g_heap_region[num].free_blk = mem_blk;
    }

    _heap_caps_unlock(num);
}