Hello cathychang,
I have not had any problems getting my interrupt handler working. In my system the interrupt vectors are all hard coded in the protected bootloader section, and all of them (except reset) point to a jump table at a fixed location in my exec. (My boot loaders use vectors in RAM, but my exec is fixed in FLASH).
I have come ot the realization that most of the poeple who use this forum are not "copecetic" with assembly language, but I'm "old school" and I prefer assembly whenever I can get away with it. I have been translating my attempt at Virtual COM Port from Assembly to C, but I have not yet gotten down to the USB_INIT subroutine. So I'm posting it here in assembly. I have not had any problem with the interrupt. My problems all come after enumeration when I just don't know what else to do.
So Here's my USB_INIT in assembly, I hope this helps:
////////////////////////////////////////////////////////////////////////////////////////////////////
// INIT USB
//is called from power up reset.
////////////////////////////////////////////////////////////////////////////////////////////////////
.align 2
USB_INIT:
LEA.L (EP0Rx).L,%A0 //EP zero Receive is the start of the BDT
CLEAR_BDT_LOOP:
CLR.L (%A0)+
CMPA.L #BTD_END,%A0
BLT.B CLEAR_BDT_LOOP //Clear the BDT
LEA.L (USB_BUFFERS_START).L,%A0
CLEAR_USB_BUFFERS_LOOP:
CLR.L (%A0)+
CMPA.L #USB_BUFFERS_END,%A0
BLT.B CLEAR_USB_BUFFERS_LOOP //Clear the Buffers used by USB
//
//Setup the BDT for Endpoint 0. I think that EP0 will always be the same.
//
//EP0 Rx even (0)
MOVE.L #0x88004000,%D0 //0x00400088 converted to little endian is 0x88004000. These are all hard coded constants so why waste code.
MOVE.L %D0,(EP0Rx).L //set the control long in End Point zero receive 0
MOVE.L #SETUP_PACKET,%D0 //get the address of the buffer to be used to receive the Setup Packet.
.word 0x02C0 //BYTEREV %D0 because the BDT is little Endian
MOVE.L %D0,(EP0Rx_ADDR).L //save the buffer address in the BDT.
//EP0 Rx odd (1)
MOVE.L #0xC8004000,%D0
MOVE.L %D0,(EP0Rx1).L //set the control long in End Point zero receive 0
MOVE.L #EP0_OUT_Data,%D0 //get the address of the buffer to be used,
.word 0x02C0 //BYTEREV %D0 because the BDT is little Endian
MOVE.L %D0,(EP0Rx1_ADDR).L //save the buffer address in the BDT.
//EP0 Tx even (0)
MOVE.L #0x88004000,%D0
MOVE.L %D0,(EP0Tx).L //set the control long in End Point zero receive 0
MOVE.L #EP0_TX_DATA_BUFFER,%D0 //get the address of the buffer to be used,
.word 0x02C0 //BYTEREV %D0 because the BDT is little Endian
MOVE.L %D0,(EP0Tx_ADDR).L //save the buffer address in the BDT.
//EP0 Tx odd (1)
MOVE.L #0xC8004000,%D0
MOVE.L %D0,(EP0Tx1).L //set the control long in End Point zero receive 0
MOVE.L #EP0_TX_DATA_BUFFER,%D0 //get the address of the buffer to be used,
.word 0x02C0 //BYTEREV %D0 because the BDT is little Endian
MOVE.L %D0,(EP0Tx1_ADDR).L //save the buffer address in the BDT.
//Setup the address of the BDT in three separate bytes for the USB silicon.
MOVE.L #EP0Rx,%D0
ASR.L #8,%D0
MOVE.B %D0,(BDT_PAGE_01).L
ASR.L #8,%D0
MOVE.B %D0,(BDT_PAGE_02).L
ASR.L #8,%D0
MOVE.B %D0,(BDT_PAGE_03).L
CLR.L %D0
MOVE.W %D0,(CCE).L //In the beginning there was a bit (14) that allowed the BDT to be Bigendian.
//It has since been removed from the manual, and possibly the silicon.
//The response from Freescale support to my question about it was basically that
//all the existing "stacks" use little endian (and obviously software engineers are too
//stupid to write their own), so they took it out.
//The bit might still be there who knows?
//There is no mention anywhere in their manual that the BDT is all LITTLE ENDIAN.
//The description of CCE bit 14 that they removed was the only reference to it.
//select the USB clock
MOVE.B #1,%D0
MOVE.B %D0,(USB_CTRL).L //1 selects the external oscillator clock to run the USB silicon.
//Enable Endpoint zero
MOVE.B #0x0D,%D0
MOVE.B %D0,(ENDPT0).L
//Disable all USB interrupts
CLR.L %D0
MOVE.B %D0,(INT_ENB).L //disable all USB interrupts
MOVE.B %D0,(OTG_INT_EN).L //disable all OTG interrupts
MOVE.B %D0,(ERR_ENB).L //disable all USB error interrupts
MOVE.B #0xFF,%D0
MOVE.B %D0,INT_STAT //reset any pending USB interrupts
MOVE.B %D0,(OTG_INT_STAT).L //clear any pending OTG interrupts
MOVE.B %D0,(ERR_STAT).L //clear any pending USB error interrupt
//Enable USB interrupts: //////////////////////////////////////
//ICR053 set the interrupt "level" and "Priority" for USB's interrupt
MOVE.B #0x12,%D0 //Level 2, Priority 2, what ever that is.
MOVE.B %D0,(ICR053).L
//Unmask Interrupts for USB source 53 on INTC0, this is vector 117 overall 64+53
MOVE.L (IMRH0).L,%D0
ANDI.L #0xFFDFFFFF,%D0 //the inverse of #0x00200000
MOVE.L %D0,(IMRH0).L //zero the bit for interrupt 53 on INTC0
MOVE.L (IMRL0).L,%D0 //Zero the MASK ALL bit.
ANDI.L #0xFFFFFFFE,%D0 //This only needs to be done once.
MOVE.L %D0,(IMRL0).L //clear the mask all bit
//MOVE.B #0x9B,%D0 //enable Stall, sleep, Token DNE, error, USB reset interrupts but not enable attach, resume or sof_toK.
//MOVE.B #0xFF,%D0 //enable all interrupts
MOVE.B #0xFB,%D0 //enable all interrupts except SOF
//MOVE.B #0xEB,%D0 //enable all interupts except sleep and SOF
MOVE.B %D0,(INT_ENB).L
//End of interrupt enabling. //////////////////////////////////////
CLR.L %D0
MOVE.B %D0,(ADDR).L
//enable the USB silicon
MOVE.B #1,%D0
MOVE.B %D0,(CTL).L
//enable the USB DP pullup resistor. This lets the PC know soemthing is plugged in.
MOVE.B #0x84,%D0
MOVE.B %D0,(OTG_CTRL).L
RTS
When I previewed this the forum messed up the code something awful, I can assure you my code si properly formatted and there are absolutely no TAB characters in it. I guess I'll have to zip it up and attach it to make it readable: