/* In theory, we can also make this work by prepending a struct that looks similar to the block link struct used by the heap allocator itself, which will allow inspection tools relying on any block returned from any sort of malloc to have such a block in front of it, work. We may do this later, if/when there is demand for it. For now, a simple pointer is used.  */
static IRAM_ATTR void* dram_alloc_to_iram_addr(void *addr, size_t len)
/* In theory, we can also make this work by prepending a struct that looks similar to the block link struct used by the heap allocator itself, which will allow inspection tools relying on any block returned from any sort of malloc to have such a block in front of it, work. We may do this later, if/when there is demand for it. For now, a simple pointer is used.  */
static IRAM_ATTR void* dram_alloc_to_iram_addr(void *addr, size_t len)
{
    uint32_t dstart = (int)addr;
    uint32_t dend = ((int)addr) + len - 4;
    assert(dstart >= SOC_DIRAM_DRAM_LOW);
    assert(dend <= SOC_DIRAM_DRAM_HIGH);
    assert((dstart & 3) == 0);
    assert((dend & 3) == 0);
    uint32_t istart = SOC_DIRAM_IRAM_LOW + (SOC_DIRAM_DRAM_HIGH - dend);
    uint32_t *iptr = (uint32_t *)istart;
    *iptr = dstart;
    return (void *)(iptr + 1);
}