Complete USB XMEGA interrupt control subsystem code in the core USB driver.
authorDean Camera <dean@fourwalledcubicle.com>
Fri, 15 Jul 2011 08:10:51 +0000 (08:10 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Fri, 15 Jul 2011 08:10:51 +0000 (08:10 +0000)
Automatically load in the USB calibration bytes from the User Signature Row on start-up.

Create internal SRAM variable for the endpoint control and status register table, used by the XMEGA USB controller hardware.

LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c
LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h
LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h
LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c
LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h
LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c
LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h

index 7a9c148..93d23c3 100644 (file)
 \r
 void USB_INT_DisableAllInterrupts(void)\r
 {\r
-       AVR32_USBB.USBCON.vbuste = false;\r
-       AVR32_USBB.USBCON.idte   = false;\r
+       AVR32_USBB.USBCON.vbuste     = false;\r
+       AVR32_USBB.USBCON.idte       = false;\r
 \r
-       AVR32_USBB.uhinteclr     = -1;\r
-       AVR32_USBB.udinteclr     = -1;\r
+       AVR32_USBB.uhinteclr         = -1;\r
+       AVR32_USBB.udinteclr         = -1;\r
 }\r
 \r
 void USB_INT_ClearAllInterrupts(void)\r
@@ -45,8 +45,8 @@ void USB_INT_ClearAllInterrupts(void)
        AVR32_USBB.USBSTACLR.vbustic = true;\r
        AVR32_USBB.USBSTACLR.idtic   = true;\r
 \r
-       AVR32_USBB.uhintclr      = -1;\r
-       AVR32_USBB.udintclr      = -1;\r
+       AVR32_USBB.uhintclr          = -1;\r
+       AVR32_USBB.udintclr          = -1;\r
 }\r
 \r
 ISR(USB_GEN_vect)\r
index f0a472e..4b43891 100644 (file)
@@ -50,6 +50,7 @@
 \r
        /* Includes: */\r
                #include "../../../../Common/Common.h"\r
+               #include "../USBController.h"\r
                #include "../StdDescriptors.h"\r
                #include "../USBInterrupt.h"\r
                #include "../Endpoint.h"\r
                        /** Length of the device's unique internal serial number, in bits, if present on the selected microcontroller\r
                         *  model.\r
                         */\r
-                       #define INTERNAL_SERIAL_LENGTH_BITS    112\r
+                       #define INTERNAL_SERIAL_LENGTH_BITS    (8 * (1 + (offsetof(NVM_PROD_SIGNATURES_t, COORDY1) - offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0))))\r
                        \r
                        /** Start address of the internal serial number, in the appropriate address space, if present on the selected microcontroller\r
                         *  model.\r
                         */\r
-                       #define INTERNAL_SERIAL_START_ADDRESS  0x08\r
+                       #define INTERNAL_SERIAL_START_ADDRESS  offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0)\r
                        \r
                /* Function Prototypes: */\r
                        /** Sends a Remote Wakeup request to the host. This signals to the host that the device should\r
                        static inline uint16_t USB_Device_GetFrameNumber(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;\r
                        static inline uint16_t USB_Device_GetFrameNumber(void)\r
                        {\r
-                               return 0; // TODO\r
+                               return (((uint16_t)USB_EndpointTable.FRAMENUMH << 8) | USB_EndpointTable.FRAMENUML);\r
                        }\r
 \r
                        #if !defined(NO_SOF_EVENTS)\r
                        static inline void USB_Device_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Device_EnableSOFEvents(void)\r
                        {\r
-                               // TODO\r
+                               USB.INTCTRLA |=  USB_SOFIE_bm;\r
                        }\r
 \r
                        /** Disables the device mode Start Of Frame events. When disabled, this stops the firing of the\r
                        static inline void USB_Device_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_Device_DisableSOFEvents(void)\r
                        {\r
-                               // TODO\r
+                               USB.INTCTRLA &= ~USB_SOFIE_bm;\r
                        }\r
                        #endif\r
 \r
                                }\r
                                \r
                                SetGlobalInterruptMask(CurrentGlobalInt);\r
-\r
-\r
                        }\r
 \r
        #endif\r
index fd5addd..2a2d4f2 100644 (file)
                                        CheckBytes <<= 1;\r
                                }\r
 \r
-                               return (MaskVal << USB_EP_SIZE_gp);\r
+                               return (MaskVal << USB_EP_BUFSIZE_gp);\r
                        }\r
 \r
                /* Function Prototypes: */\r
index c8839c9..c67575b 100644 (file)
@@ -40,6 +40,8 @@ volatile uint8_t USB_CurrentMode = USB_MODE_None;
 volatile uint8_t USB_Options;\r
 #endif\r
 \r
+USB_EP_TABLE_t USB_EndpointTable ATTR_ALIGNED(2);\r
+\r
 void USB_Init(\r
                #if defined(USB_CAN_BE_BOTH)\r
                const uint8_t Mode\r
@@ -61,6 +63,16 @@ void USB_Init(
        #endif\r
        \r
        USB_IsInitialized = true;\r
+       \r
+       uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+       GlobalInterruptDisable();\r
+\r
+       NVM.CMD  = NVM_CMD_READ_CALIB_ROW_gc;\r
+       USB.CAL0 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL0));\r
+       NVM.CMD  = NVM_CMD_READ_CALIB_ROW_gc;\r
+       USB.CAL1 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL1));\r
+       \r
+       SetGlobalInterruptMask(CurrentGlobalInt);\r
 \r
        USB_ResetInterface();   \r
 }\r
@@ -79,13 +91,17 @@ void USB_Disable(void)
 void USB_ResetInterface(void)\r
 {\r
        if (USB_Options & USB_DEVICE_OPT_LOWSPEED)\r
-         CLK.USBCTRL = ((((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp) | CLK_USBSRC_PLL_gc | CLK_USBEN_bm);\r
+         CLK.USBCTRL = ((((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp) | CLK_USBSRC_PLL_gc | CLK_USBSEN_bm);\r
        else\r
-         CLK.USBCTRL = ((((F_USB / 48000000) - 1) << CLK_USBPSDIV_gp) | CLK_USBSRC_PLL_gc | CLK_USBEN_bm);\r
+         CLK.USBCTRL = ((((F_USB / 48000000) - 1) << CLK_USBPSDIV_gp) | CLK_USBSRC_PLL_gc | CLK_USBSEN_bm);\r
        \r
        USB_INT_DisableAllInterrupts();\r
        USB_INT_ClearAllInterrupts();\r
 \r
+       // TODO: Config define for priority\r
+       USB.INTCTRLA = (2 << USB_INTLVL_gp);\r
+       PMIC.CTRL   |= (1 << PMIC_MEDLVLEX_bp);\r
+\r
        USB_Controller_Reset();\r
        USB_Init_Device();\r
 }\r
@@ -143,6 +159,8 @@ static void USB_Init_Device(void)
                                                           ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,\r
                                                           ENDPOINT_BANK_SINGLE);\r
 \r
+       USB_INT_Enable(USB_INT_BUSEVENTI);\r
+\r
        USB_Attach();\r
 }\r
 #endif\r
index f5adc12..45cfe59 100644 (file)
                #include "../USBTask.h"\r
                #include "../USBInterrupt.h"\r
 \r
+       /* Private Interface - For use in library only: */\r
+       #if !defined(__DOXYGEN__)\r
+               /* External Variables: */\r
+                       extern USB_EP_TABLE_t USB_EndpointTable;\r
+       #endif\r
+       \r
+       /* Includes: */\r
                #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)\r
                        #include "../Device.h"\r
                        #include "../Endpoint.h"\r
index cb80622..b52a716 100644 (file)
 \r
 void USB_INT_DisableAllInterrupts(void)\r
 {\r
-       // TODO\r
+       USB.INTCTRLA     = 0;\r
+       USB.INTCTRLB     = 0;\r
 }\r
 \r
 void USB_INT_ClearAllInterrupts(void)\r
 {\r
-       // TODO\r
+       USB.INTFLAGSACLR = 0xFF;\r
+       USB.INTFLAGSBCLR = 0xFF;\r
 }\r
 \r
-// TODO: USB ISR\r
+ISR(USB_BUSEVENT_vect)\r
+{\r
+       #if !defined(NO_SOF_EVENTS)\r
+       if (USB_INT_HasOccurred(USB_INT_SOFI) && USB_INT_IsEnabled(USB_INT_SOFI))\r
+       {\r
+               USB_INT_Clear(USB_INT_SOFI);\r
+\r
+               EVENT_USB_Device_StartOfFrame();\r
+       }\r
+       #endif\r
+\r
+       if (USB_INT_HasOccurred(USB_INT_BUSEVENTI_Suspend))\r
+       {\r
+               USB_INT_Clear(USB_INT_BUSEVENTI_Suspend);\r
+\r
+               #if !defined(NO_LIMITED_CONTROLLER_CONNECT)\r
+               USB_DeviceState = DEVICE_STATE_Unattached;\r
+               EVENT_USB_Device_Disconnect();\r
+               #else\r
+               USB_DeviceState = DEVICE_STATE_Suspended;\r
+               EVENT_USB_Device_Suspend();\r
+               #endif\r
+       }\r
+\r
+       if (USB_INT_HasOccurred(USB_INT_BUSEVENTI_Resume))\r
+       {\r
+               USB_INT_Clear(USB_INT_BUSEVENTI_Resume);\r
+               \r
+               if (USB_Device_ConfigurationNumber)\r
+                 USB_DeviceState = DEVICE_STATE_Configured;\r
+               else\r
+                 USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Configured : DEVICE_STATE_Powered;\r
+\r
+               #if !defined(NO_LIMITED_CONTROLLER_CONNECT)\r
+               EVENT_USB_Device_Connect();\r
+               #else\r
+               EVENT_USB_Device_WakeUp();\r
+               #endif\r
+       }\r
+\r
+       if (USB_INT_HasOccurred(USB_INT_BUSEVENTI_Reset))\r
+       {\r
+               USB_INT_Clear(USB_INT_BUSEVENTI_Reset);\r
+               \r
+               USB_DeviceState                = DEVICE_STATE_Default;\r
+               USB_Device_ConfigurationNumber = 0;\r
+\r
+               Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,\r
+                                          ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,\r
+                                          ENDPOINT_BANK_SINGLE);\r
+\r
+               EVENT_USB_Device_Reset();\r
+       }\r
+}\r
 \r
index 6dcb0e6..b6acec4 100644 (file)
                /* Enums: */\r
                        enum USB_Interrupts_t\r
                        {\r
-                               USB_INT_NONE  = 0, // TODO\r
+                               USB_INT_BUSEVENTI         = 1,\r
+                               USB_INT_BUSEVENTI_Suspend = 2,\r
+                               USB_INT_BUSEVENTI_Resume  = 3,\r
+                               USB_INT_BUSEVENTI_Reset   = 4,\r
+                               USB_INT_SOFI              = 5,\r
                        };\r
 \r
                /* Inline Functions: */\r
                        static inline void USB_INT_Enable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_INT_Enable(const uint8_t Interrupt)\r
                        {\r
-                               // TODO\r
+                               switch (Interrupt)\r
+                               {\r
+                                       case USB_INT_BUSEVENTI:\r
+                                               USB.INTCTRLA |=  USB_BUSEVIE_bm;\r
+                                               return;\r
+                                       case USB_INT_SOFI:\r
+                                               USB.INTCTRLA |=  USB_SOFIE_bm;                                          \r
+                                               return;                         \r
+                               }\r
                        }\r
 \r
                        static inline void USB_INT_Disable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_INT_Disable(const uint8_t Interrupt)\r
                        {\r
-                               // TODO\r
+                               switch (Interrupt)\r
+                               {\r
+                                       case USB_INT_BUSEVENTI:\r
+                                               USB.INTCTRLA &= ~USB_BUSEVIE_bm;\r
+                                               return;\r
+                                       case USB_INT_SOFI:\r
+                                               USB.INTCTRLA &= ~USB_SOFIE_bm;                                          \r
+                                               return;                         \r
+                               }\r
                        }\r
                        \r
                        static inline void USB_INT_Clear(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;\r
                        static inline void USB_INT_Clear(const uint8_t Interrupt)\r
                        {\r
-                               // TODO\r
+                               switch (Interrupt)\r
+                               {\r
+                                       case USB_INT_BUSEVENTI_Suspend:\r
+                                               USB.INTFLAGSACLR = USB_SUSPENDIF_bm;\r
+                                               return;\r
+                                       case USB_INT_BUSEVENTI_Resume:\r
+                                               USB.INTFLAGSACLR = USB_RESUMEIF_bm;\r
+                                               return;\r
+                                       case USB_INT_BUSEVENTI_Reset:\r
+                                               USB.INTFLAGSACLR = USB_RSTIF_bm;\r
+                                               return;\r
+                                       case USB_INT_SOFI:\r
+                                               USB.INTFLAGSACLR = USB_SOFIF_bm;                                                \r
+                                               return;                         \r
+                               }\r
                        }\r
                        \r
                        static inline bool USB_INT_IsEnabled(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;\r
                        static inline bool USB_INT_IsEnabled(const uint8_t Interrupt)\r
                        {\r
-                               return false; // TODO\r
+                               switch (Interrupt)\r
+                               {\r
+                                       case USB_INT_BUSEVENTI:\r
+                                               return (USB.INTCTRLA & USB_BUSEVIE_bm);\r
+                                       case USB_INT_SOFI:\r
+                                               return (USB.INTCTRLA & USB_SOFIE_bm);\r
+                               }\r
+                               \r
+                               return false;\r
                        }\r
                \r
                        static inline bool USB_INT_HasOccurred(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;\r
                        static inline bool USB_INT_HasOccurred(const uint8_t Interrupt)\r
                        {\r
-                               return false; // TODO\r
+                               switch (Interrupt)\r
+                               {\r
+                                       case USB_INT_BUSEVENTI_Suspend:\r
+                                               return (USB.INTFLAGSACLR & USB_SUSPENDIF_bm);\r
+                                       case USB_INT_BUSEVENTI_Resume:\r
+                                               return (USB.INTFLAGSACLR & USB_RESUMEIF_bm);\r
+                                       case USB_INT_BUSEVENTI_Reset:\r
+                                               return (USB.INTFLAGSACLR & USB_RSTIF_bm);\r
+                                       case USB_INT_SOFI:\r
+                                               return (USB.INTFLAGSACLR & USB_SOFIF_bm);\r
+                               }\r
+                               \r
+                               return false;\r
                        }\r
 \r
                /* Includes: */\r