I want the function USB_Jump_Table() to start at a page boundary. Therefore, I defined the following assembler code:
.area JTAB (PAG, CODE)
ljmp _ISR_Sudav ;(00) Setup Data Available
ljmp _ISR_Sof ;(04) Start of Frame
ljmp _ISR_Sutok ;(08) Setup Data Loading
I hoped that in this way the linker would automatically place the code at a page boundary, but I only get
?ASlink-Warning-Paged Area JTAB Boundary Error
Is there a simple way of doing this?
I assume that you are trying to port the EZ-USB framework to be used with SDCC. I did the same job these days :-)
I ran into the same problem. The "paged" attribute seems to be ignored in conjunction with the "code" attribute. I wrote:
.area JTAB (XDATA,PAG)
to solve the problem. This of course puts the jump table into the xdata segment, but that does not make a difference... at least with the EZ-USB project, because code and xdata share the same address space.
Sorry, I did not pay attention to the fact that the SDCC runtime startup will clear the xdata area. So for now I would suggest that you put the jump table into the same segment where you have put the interrupt vector jumps (that would have to be a non relocateable segment) and put a ".org 0x0100" just in front of the jump table code. This actually works for me. Look at the resulting map file to see what's happening!
PAG only makes sure the whole segment fits inside a 256 bytes page and doesn't cross a border.
Why does it need to be at a page boundary?
Using a JTAB (ABS, CODE) area with a .org will do fine too. Don't try to offset with the ".org 0x0100" from another segment. It ends up at 0x100 absolute.
the 8051 based Cypress chips (CY7C64 family) have a special feature called "autovectoring". These chips supply 46 (!!!) USB related interrupt events, routed to the controller via interrupts 8 and 10. Within both interrupt service routines, the programmer would have to check more than 20 hardware sources to figure out the reason for the interrupt.
By turning on the autovectoring feature, the hardware assumes that the vectoring addresses for those two interrupts contain ljmp instructions. When the interrupt occurs and the controller fetches this instruction, it replaces the 3rd byte of the instruction with an interrupt source number, multiplied by 4. So the ljmp can point to another, big jump table, which contains 46 ljmps.
Of course this feature will work only if the the big 46 entries jump table starts at a 256 byte boundary. The autovectoring feature is a simple replacement of the 3rd byte of the first three bytes fetched from the irq vector location.
The KEIL C compiler, however is capeable of handling code segments with attributes like "is relocateable", but must start at a 256 byte boundary.
By now, my solution is to use a JUMPTAB (CODE, ABS) area and nail it down to 0x0100 using an .org directive.