Hello Ian,

[email protected] schreef op 2026-06-29 12:44:

extern void USBINT_AUTOVECTORS(void) __interrupt(8) __naked;

This is a good idea.

int main(void)

Since main() has nothing to return any value to, make it return void.

{
__asm
  .area HOME (CODE)
  .bndry 256
_USBINT_AUTOVECTORS::
  ljmp _USBINT_SUDAV
  .ds 1
  ljmp _USBINT_SOF
  .ds 1
  ljmp _USBINT_SUTOK
  .ds 1
  ljmp _USBINT_SUSPEND
  .ds 1

  // And so on...

  .area CSEG (CODE)
__endasm;

  while (1)
  {
  }
}

Since .bndry is not working in the linker I would be careful with this.
Also, don't place this inside main(). Put it in a separate dummy function,
preferably at the end of the file containing main().

static void dummy(void) __naked
{
__asm
    ...
__endasm;
}

Using ljmp instead of the magic number 0x02 is better IMO.

static volatile uint8_t i = 0;

void USBINT_SUDAV(void) __interrupt
{
  i = 0;
}

This is exactly right: __interrupt with no number.

void USBINT_SOF(void) __interrupt
{
  i = 1;
}

void USBINT_SUTOK(void) __interrupt
{
  i = 2;
}

void USBINT_SUSPEND(void) __interrupt
{
  i = 3;
}

As compiled and linked with SDCC 4.6.0, this seems to give the desired
layout in code space.

 Eric





________________________________________
From: Ian Molton via Sdcc-user <[email protected]>
Sent: Monday, June 29, 2026 03:21
To: [email protected] <[email protected]>
Cc: Ian Molton <[email protected]>
Subject: Re: [Sdcc-user] Cypress FX2 USB vector "table"


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] =

How about making this table const so it can be placed in CODE?
Or do you plan to change it at runtime making it self-modifying code?
At least change 02 (octal, really?) to a macro LJMP.
#define LJMP    (0x02)

{
         {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.

This is because of the __at(0x0d000) which places the array outside of XISEG.

And on an FX2 even a copy from XINIT to XISEG is inefficient as it only has ram.
SDCC assumes XINIT to be in unmodifiable ROM.

Fun and games...

-Ian

Kind regards,
Maarten


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

Reply via email to