From: Ernst B. <e.b...@xe...> - 2005-10-24 20:49:40
|
On Monday 24 October 2005 21:25, Paul Stoffregen wrote: > >Now, anyone interrested in some code snippets to make the USB Autovector > >feature of the EzUSB chips work with sdcc? > > Several months ago, I played with one of these chips. I never did > figure out a nice way to get SDCC (mainly the linker) to build the > autovector table and endpoint descriptor tables at absolute addresses. > So instead I did some very ugly hacks with perl scripts to read a couple > simple text files, and the symbol table from the linker. The scripts > output absolute addressed assembly, which is then run through an > assembler, and the intel hex is post processed and merged with the > linker's hex by more ugly perl scripts. > > An ugly hack, but it worked. I'd be really curious to see if anyone has > found a "nice" was to do this using SDCC. Sure sounds like an ugly hack. Here's how I do it now: A header file where I declare what USB Interrupts I'll be using: -----[ usb_config.h ] ----- #define SUDAV_ISR _sudav_isr #define USBRESET_ISR _usb_reset_isr #define EP0IN_ISR _ep0in_isr #define EP1IN_ISR _ep1in_isr #define EP0OUT_ISR _ep0out_isr #define EP2OUT_ISR _ep2out_isr #define EP4OUT_ISR _ep4out_isr ... --------------------------- an File to contain the actual interrupt table: that usb_table function has to be all alone in that file, so the offset is still right, and contains an ljump for every enabled ISR, reti otherwise. I'm using .db 0,0,0 instead of .d s3 so the resulting hex file in the end won't have thousands of small blocks, but only one for this function (less block header space wasted when installed on i2c eeprom) -----[ usb.c ]------------- #include <ezusb.h> #include "usb_config.h" #pragma codeseg USBSEG void usb_table() interrupt USB_VECT _naked { _asm; #ifdef SUDAV_ISR ljmp SUDAV_ISR .db 0x00 #else reti .db 0x00,0x00,0x00 #endif #ifdef SOF_ISR ljmp SOF_ISR .db 0x00 #else reti .db 0x00,0x00,0x00 #endif #ifdef SUTOK_ISR ljmp SUTOK_ISR .db 0x00 #else reti .db 0x00,0x00,0x00 #endif #ifdef SUSPEND_ISR ljmp SUSPEND_ISR .db 0x00 #else reti .db 0x00,0x00,0x00 #endif .... ------------------- in the main program, be sure to have a line like extern void usb_table() interrupt USB_VECT _naked; So the usb_table will be referenced all right from the main ISR table ----[ main.c ] ----- void setup_usb() { ... /* set autovector enable */ USBBAV = bmAVEN; /* enable ISRs based on what's defined in usb_config.h */ USBIEN = #ifdef SUDAV_ISR bmSUDAV | #endif #ifdef USBRESET_ISR bmURES | #endif ... } extern void usb_table() interrupt USB_VECT _naked; void sudav_isr() interrupt { EZUSB_IRQ_CLEAR(); USBIRQ = bmSUDAV; switch (SETUPDAT.bRequest) { case SC_GET_STATUS: .... } void ep0in_isr() interrupt { EZUSB_IRQ_CLEAR(); IN07IRQ = bmEP0; ... } ------------- The actual usb-isrs are just declared as "interrupt", without vector, we need sdcc to generate a reti at their end, but don't need an IRQ Table entry done by sdcc. Now, for compiling, I compile the single .c files normally with "sdcc -c usb.c" ... But then I link everything with: sdcc -Wl-bUSBSEG=0x1A00 --xram-loc 0x1A58 --code-size 0x1A58 --xram-size 0x00E8 main.rel i2c.rel usb.rel usb_setup.rel strings.rel ; So my final memory layout is about this: 0000 .. 1A00 free for CODE 1A00 .. 1A58 the USB Autovector table 1A58 .. 1B40 space for xdata variables (0xE8 bytes) 1B40 .. xxxx usb buffers. if you need more xdata space, just move the USBSEG down a bit or declare xdata to be before USBSEG and maybe put some more code behind it. HTH /Ernst |