So, I may be either answering my own question, or looking dumb by missing the obvious "correct" way, but...

This appears to generate correct assembly for the jumptable, at the desired address. The idea is to construct the LJMP instructions that should exist for each entry point, as 0x02 is the correct opcode (each entry is 4 bytes, so the remaining one is left as a 0. Using the __at() directive an array of structs can be created at a specific (aligned) location.

I haven't yet tried to generate an interrupt handler - I expect the compiler to refuse to generate an interrupt function for the USB vector to occupy the same address as the array - but it should be trivial to generate the correct LJMP 0x0d00 instruction and copy it to 0x0043.

The documentation for the EZUSB is contradictory on this point - it is unclear if only the byte at 0x0045 is replaced by the low byte of the USB autovector function pointer, or if instead the entire 4 bytes of the autovector are used.


I'll try this out soon - in the meantime, this is my code:


struct usb_vectable_entry
{
        uint8_t jmp_insn;
        void (*fn_ptr)(void);
        uint8_t zero;
};

void func_1(void)
{
}

void func_2(void)
{
}

#define NULL (0)

static struct usb_vectable_entry __at(0x0d00) usb_vectable[32] =
{
        {02, func_1, 00},
        {02, func_2, 00},
        {NULL},

       ...

};


The assembler output by sdcc as part of the .globals setup generates a table that looks valid at 0xd00 -

        mov     dptr,#_usb_vectable
        mov     a,#0x02
        movx    @dptr,a
        mov     dptr,#(_usb_vectable + 0x0001)
        mov     a,#_func_1
        movx    @dptr,a
        mov     a,#(_func_1 >> 8)
        inc     dptr
        movx    @dptr,a
        mov     dptr,#(_usb_vectable + 0x0003)
        clr     a
        movx    @dptr,a
        mov     dptr,#(_usb_vectable + 0x0004)
        mov     a,#0x02
        movx    @dptr,a
        mov     dptr,#(_usb_vectable + 0x0005)
        mov     a,#_func_2
        movx    @dptr,a
        mov     a,#(_func_2 >> 8)
        inc     dptr
        movx    @dptr,a
        mov     dptr,#(_usb_vectable + 0x0007)
        clr     a
        movx    @dptr,a
        mov     dptr,#(_usb_vectable + 0x0008)
        movx    @dptr,a
    ...


I'm unsure why the compiler has emitted this rather than copying .data from somewhere else - I assume I'm missing an option on the sdcc commandline, as this looks quite space inefficient.

Fun and games...

-Ian


On 28/06/2026 19:29, Ian Molton via Sdcc-user wrote:
Hi all,


I've looked through the docs and searched online, but I can't find an answer to this.


Normal ISRs work just fine for the FX2, but I want to use the USB autovector functionality. I can't just use a bunch of function pointers, as the table uses actual jump instructions which the CPU "reinterprets" to get the destination of the jump.


I've seen several people produce solutions to this that each have their own problems. The SDCC documentation hints that there is a solution, but gives no information.


Is there actually a solution, like using __interrupt(), or some nice way to generate a compatible jump table that can be located in a fixed position in memory by the linker? I don't like the idea of using an assembler stub that inherently has to define pretty much every ISR, if only as a dummy function.

If not, would patches to sdcc be welcome?

-Ian



_______________________________________________
Sdcc-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sdcc-user


_______________________________________________
Sdcc-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sdcc-user

Reply via email to