• there are only a few KB left and as there are still improvements in Espruino

    True, and you could probably add a few extra bits and bobs (encryption, etc). With the byte read hack you could simply force all read-only arrays into flash, freeing a lot of RAM. I guess a 4MB build would probably be a good plan then.

    Is it possible to calculate how many space is needed by save() in worst case?

    You could argue it's JsVars * 16 bytes. But with E.setBootCode - assuming you had a way to actually write the code - you could upload a 1MB JS file if you wanted.

  • Hi @Gordon, my comments on RESIZABLE_JSVARS above, in my answer to @MaBe.

    Regarding the unaligned access code, here it is. I can't remember where I found it first on the internet, so I cannot credit the original idea author (even if current code does not seem too much to the original one...).

    By the way, it may need some adjustements to compile (this is just copied from another project of mine, and I have only done minor changes for it to compile in Espruino, but not really checked).

    Important: change everywhere ## by the a single "## hash" caracter (unless somebedy explains me how to write a single "## hash" without it being interpreted by the forum as some special character...)

    To activate the code, you need to call virtual_unaligned_memory_access() early in user_init()

     ##include "espmissingincludes.h"
     ##define RODATA __attribute__((section(".rodata")))
     ##define EXCCAUSE_LOAD_STORE_ERROR 3
     ##define EXCCAUSE_UNALIGNED 9
     ##define __stringify_1(x...) ##x
     ##define __stringify(x...) __stringify_1(x)
     ##define RSR(sr) ({ \
            uint32_t r; \
            __asm__ volatile("rsr %0," __stringify(sr) : "=a"(r)); \
            r; \
    })
    
    struct xtos_saved_regs {
            uint32_t pc;    /* instruction causing the trap */
            uint32_t ps;
            uint32_t sar;
            uint32_t vpri;  /* current xtos virtual priority */
            uint32_t a0;    /* when __XTENSA_CALL0_ABI__ is true */
            uint32_t a[16]; /* a2 - a15 */
    };
    
    typedef void (_xtos_handler_func)(struct xtos_saved_regs *);
    typedef _xtos_handler_func *_xtos_handler;
    _xtos_handler _xtos_set_exception_handler( int n, _xtos_handler f );
    
    const char _trap_unaligned_debug_msg[] RODATA = "Unaligned access @%p [%08x %08x]: %p\n";
    uintptr_t _trap_unaligned_last;
    uint32_t _trap_unaligned_read;
    
    static void CALLED_FROM_INTERRUPT unaligned_debug(uint8_t *pc, void *vaddr) {
            uint32_t *base = (uint32_t *)((uintptr_t) pc & ~0x3);
            ets_printf(_trap_unaligned_debug_msg, pc, base[0], base[1], vaddr);
    }
    
    uint8_t inline CALLED_FROM_INTERRUPT read_unaligned_byte(uint8_t *addr) {
            uintptr_t base = (uintptr_t) addr & ~0x3;
            if(base != _trap_unaligned_last) {
                    _trap_unaligned_read = * (uint32_t *) base;
                    _trap_unaligned_last = base;
            }
            return ((uint8_t *)&_trap_unaligned_read)[((uintptr_t) addr & 0x3)];
    }
    
    static void CALLED_FROM_INTERRUPT flash_emul_exception_handler(struct xtos_saved_regs *frame) {
            uint32_t vaddr = RSR(EXCVADDR);
            uint32_t instr = read_unaligned_byte((uint8_t *) frame->pc) | (read_unaligned_byte((uint8_t *) frame->pc + 1) << 8);
            uint8_t at = (instr >> 4) & 0xf;
            uint32_t val;
            uint32_t count;
            uint32_t u2s;
    
            if (vaddr < 0x40200000 /* 0x3ffe8000 */) {
                    unaligned_debug((void *)frame->pc, (void *)vaddr);
                    while(1);
            }
    
            if ((instr & 0xf00f) == 0x0002) {
                    // |     imm8       |   r   |   as  |   at  |0 0 1 0|
                    // l8ui at, as, imm    r:0
                    frame->pc += 3;
                    count = 1;
                    u2s = 0;
            } else if ((instr & 0x700f) == 0x1002) {
                    // |     imm8       |   r   |   as  |   at  |0 0 1 0|
                    // l16ui at, as, imm   r:1
                    // l16si at, as, imm   r:9
                    frame->pc += 3;
                    count = 2;
                    u2s = (instr & 0x8000);
            } else if ((instr & 0xf00f) == 0x2002) {
                    // |     imm8       |0 0 1 0|   as  |   at  |0 0 1 0|
                    // l32i at, as, 0..1020
                    frame->pc += 3;
                    count = 4;
                    u2s = 0;
            } else if ((instr & 0x000f) == 0x0008) {
                    // |  imm4 |   s   |   t   |1 0 0 0|
                    // l32i.n at, as, 0..60
                    frame->pc += 2;
                    count = 4;
                    u2s = 0;
            } else {
                    unaligned_debug((void *)frame->pc, (void *)vaddr);
                    while(1);
            }
    
            val = 0;
            do {
                    val |= read_unaligned_byte((uint8_t *) vaddr + --count);
                    if(count) val <<= 8;
            } while(count);
    
            /* a0 and a1 are never used as scratch registers */
            frame->a[at - 2] = (u2s) ? (int16_t) val : val;
    }
    
    void virtual_unaligned_memory_access(void) {
            _xtos_set_exception_handler(EXCCAUSE_LOA­D_STORE_ERROR, flash_emul_exception_handler);
            _xtos_set_exception_handler(EXCCAUSE_UNA­LIGNED, flash_emul_exception_handler);
    }
    
About

Avatar for Pedro @Pedro started