From c6a7a028bd1f6a41195ed95e3c6b4291105ef448 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Wed, 29 Jun 2011 05:57:29 +0000 Subject: [PATCH] Merge over core library changes from the MultiArchDemos branch. --- LUFA/CodeTemplates/makefile_template.uc3 | 2 +- LUFA/Drivers/USB/Class/Device/HID.c | 2 +- LUFA/Drivers/USB/Core/ConfigDescriptor.c | 2 +- LUFA/Drivers/USB/Core/StdDescriptors.h | 5 +- LUFA/Platform/UC3/ClockManagement.h | 181 +++++++++++++++++++++++ LUFA/Platform/UC3/Exception.S | 125 ++++++++++++++++ LUFA/Platform/UC3/InterruptManagement.c | 62 ++++++++ LUFA/Platform/UC3/InterruptManagement.h | 83 +++++++++++ 8 files changed, 458 insertions(+), 4 deletions(-) create mode 100644 LUFA/Platform/UC3/ClockManagement.h create mode 100644 LUFA/Platform/UC3/Exception.S create mode 100644 LUFA/Platform/UC3/InterruptManagement.c create mode 100644 LUFA/Platform/UC3/InterruptManagement.h diff --git a/LUFA/CodeTemplates/makefile_template.uc3 b/LUFA/CodeTemplates/makefile_template.uc3 index e29e3a438c..2077ca1878 100644 --- a/LUFA/CodeTemplates/makefile_template.uc3 +++ b/LUFA/CodeTemplates/makefile_template.uc3 @@ -68,7 +68,7 @@ BOARD = ### INSERT NAME OF BOARD HERE, OR NONE IF NO BOARD DRIVERS USED ### F_CPU = ### INSERT PRESCALED SYSTEM CLOCK SPEED HERE, IN HZ ### -# Input clock frequency. +# USB controller master clock frequency. # This will define a symbol, F_USB, in all source code files equal to the # input clock frequency (before any prescaling is performed) in Hz. This value may # differ from F_CPU, as the USB clock is often sourced from the same oscillator as diff --git a/LUFA/Drivers/USB/Class/Device/HID.c b/LUFA/Drivers/USB/Class/Device/HID.c index 40351cc5d6..3b0f87a614 100644 --- a/LUFA/Drivers/USB/Class/Device/HID.c +++ b/LUFA/Drivers/USB/Class/Device/HID.c @@ -137,7 +137,7 @@ bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfac { memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State)); HIDInterfaceInfo->State.UsingReportProtocol = true; - HIDInterfaceInfo->State.IdleCount = 500; + HIDInterfaceInfo->State.IdleCount = 500; if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, HIDInterfaceInfo->Config.ReportINEndpointSize, diff --git a/LUFA/Drivers/USB/Core/ConfigDescriptor.c b/LUFA/Drivers/USB/Core/ConfigDescriptor.c index 35a01995d5..3e0cce5cc2 100644 --- a/LUFA/Drivers/USB/Core/ConfigDescriptor.c +++ b/LUFA/Drivers/USB/Core/ConfigDescriptor.c @@ -54,7 +54,7 @@ uint8_t USB_Host_GetDeviceConfigDescriptor(const uint8_t ConfigNumber, if ((ErrorCode = USB_Host_SendControlRequest(ConfigHeader)) != HOST_SENDCONTROL_Successful) return ErrorCode; - *ConfigSizePtr = DESCRIPTOR_PCAST(ConfigHeader, USB_Descriptor_Configuration_Header_t)->TotalConfigurationSize; + *ConfigSizePtr = le16_to_cpu(DESCRIPTOR_PCAST(ConfigHeader, USB_Descriptor_Configuration_Header_t)->TotalConfigurationSize); if (*ConfigSizePtr > BufferSize) return HOST_GETCONFIG_BuffOverflow; diff --git a/LUFA/Drivers/USB/Core/StdDescriptors.h b/LUFA/Drivers/USB/Core/StdDescriptors.h index 7840bcb8e3..864a1c4828 100644 --- a/LUFA/Drivers/USB/Core/StdDescriptors.h +++ b/LUFA/Drivers/USB/Core/StdDescriptors.h @@ -93,6 +93,9 @@ * Decimal format for descriptor fields requiring BCD encoding, such as the USB version number in the * standard device descriptor. * + * \note This value is automatically converted into Little Endian, suitable for direct use inside device + * descriptors on all architectures without endianness conversion macros. + * * \param[in] x Version number to encode as a 16-bit little-endian number, as a floating point number. */ #define VERSION_BCD(x) CPU_TO_LE16((((VERSION_TENS(x) << 4) | VERSION_ONES(x)) << 8) | \ @@ -101,7 +104,7 @@ /** String language ID for the English language. Should be used in \ref USB_Descriptor_String_t descriptors * to indicate that the English language is supported by the device in its string descriptors. */ - #define LANGUAGE_ID_ENG CPU_TO_LE16(0x0409) + #define LANGUAGE_ID_ENG 0x0409 /** \name Endpoint Address Direction Masks */ //@{ diff --git a/LUFA/Platform/UC3/ClockManagement.h b/LUFA/Platform/UC3/ClockManagement.h new file mode 100644 index 0000000000..2b7325ba88 --- /dev/null +++ b/LUFA/Platform/UC3/ClockManagement.h @@ -0,0 +1,181 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#ifndef _CLOCK_MANAGEMENT_H_ +#define _CLOCK_MANAGEMENT_H_ + + /* Includes: */ + #include + #include + #include + + #include + + /* Macros: */ + enum Extern_OSC_ClockStartup_t + { + EXOSC_START_0CLK = 0, + EXOSC_START_64CLK = 1, + EXOSC_START_128CLK = 2, + EXOSC_START_2048CLK = 3, + EXOSC_START_4096CLK = 4, + EXOSC_START_8192CLK = 5, + EXOSC_START_16384CLK = 6, + }; + + enum Extern_OSC_ClockMode_t + { + EXOSC_MODE_CLOCK = 0, + EXOSC_MODE_900KHZ_MAX = 1, + EXOSC_MODE_3MHZ_MAX = 2, + EXOSC_MODE_8MHZ_MAX = 3, + EXOSC_MODE_8MHZ_OR_MORE = 4, + }; + + enum + { + CLOCK_SRC_SLOW_CLK = 0, + CLOCK_SRC_OSC0 = 1, + CLOCK_SRC_OSC1 = 2, + CLOCK_SRC_PLL0 = 3, + CLOCK_SRC_PLL1 = 4, + }; + + /* Inline Functions: */ + static inline bool AVR32CLK_StartExternalOscillator(const uint8_t Channel, + const uint8_t Type, + const uint8_t Startup) + { + AVR32_PM.OSCCTRL0.startup = Startup; + AVR32_PM.OSCCTRL0.mode = Type; + AVR32_PM.mcctrl |= (1 << (AVR32_PM_MCCTRL_OSC0EN_OFFSET + Channel)); + + while (!(AVR32_PM.poscsr & (1 << (AVR32_PM_POSCSR_OSC0RDY_OFFSET + Channel)))); + return true; + } + + static inline void AVR32CLK_StopExternalOscillator(const uint8_t Channel) + { + AVR32_PM.mcctrl &= ~(1 << (AVR32_PM_MCCTRL_OSC0EN_OFFSET + Channel)); + } + + static inline bool AVR32CLK_StartPLL(const uint8_t Channel, + const uint8_t Source, + const uint32_t SourceFreq, + const uint32_t Frequency) + { + switch (Source) + { + case CLOCK_SRC_OSC0: + AVR32_PM.PLL[Channel].pllosc = 0; + break; + case CLOCK_SRC_OSC1: + AVR32_PM.PLL[Channel].pllosc = 1; + break; + default: + return false; + } + + AVR32_PM.PLL[Channel].pllmul = (Frequency / SourceFreq) ? (((Frequency / SourceFreq) - 1) / 2) : 0; + AVR32_PM.PLL[Channel].plldiv = 0; + AVR32_PM.PLL[Channel].pllen = true; + + while (!(AVR32_PM.poscsr & (1 << (AVR32_PM_POSCSR_LOCK0_OFFSET + Channel)))); + return true; + } + + static inline void AVR32CLK_StopPLL(const uint8_t Channel) + { + AVR32_PM.PLL[Channel].pllen = false; + } + + static inline bool AVR32CLK_StartGenericClock(const uint8_t Channel, + const uint8_t Source, + const uint32_t SourceFreq, + const uint32_t Frequency) + { + switch (Source) + { + case CLOCK_SRC_OSC0: + AVR32_PM.GCCTRL[Channel].pllsel = 0; + AVR32_PM.GCCTRL[Channel].oscsel = 0; + break; + case CLOCK_SRC_OSC1: + AVR32_PM.GCCTRL[Channel].pllsel = 0; + AVR32_PM.GCCTRL[Channel].oscsel = 1; + break; + case CLOCK_SRC_PLL0: + AVR32_PM.GCCTRL[Channel].pllsel = 1; + AVR32_PM.GCCTRL[Channel].oscsel = 0; + break; + case CLOCK_SRC_PLL1: + AVR32_PM.GCCTRL[Channel].pllsel = 1; + AVR32_PM.GCCTRL[Channel].oscsel = 1; + break; + default: + return false; + } + + AVR32_PM.GCCTRL[Channel].diven = (SourceFreq > Frequency) ? true : false; + AVR32_PM.GCCTRL[Channel].div = (((SourceFreq / Frequency) - 1) / 2); + AVR32_PM.GCCTRL[Channel].cen = true; + + return true; + } + + static inline void AVR32CLK_StopGenericClock(const uint8_t Channel) + { + AVR32_PM.GCCTRL[Channel].cen = false; + } + + static inline bool AVR32CLK_SetCPUClockSource(const uint8_t Source, + const uint32_t SourceFreq) + { + AVR32_FLASHC.FCR.fws = (SourceFreq > 30000000) ? true : false; + + switch (Source) + { + case CLOCK_SRC_SLOW_CLK: + AVR32_PM.MCCTRL.mcsel = 0; + break; + case CLOCK_SRC_OSC0: + AVR32_PM.MCCTRL.mcsel = 1; + break; + case CLOCK_SRC_PLL0: + AVR32_PM.MCCTRL.mcsel = 2; + break; + default: + return false; + } + + return true; + } + +#endif diff --git a/LUFA/Platform/UC3/Exception.S b/LUFA/Platform/UC3/Exception.S new file mode 100644 index 0000000000..9509fd7f22 --- /dev/null +++ b/LUFA/Platform/UC3/Exception.S @@ -0,0 +1,125 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#include + +.section .exception_handlers, "ax", @progbits + +// ================= EXCEPTION TABLE ================ +.balign 0x200 +.global EVBA_Table +EVBA_Table: + +.org 0x000 +Exception_Unrecoverable_Exception: + rjmp $ +.org 0x004 +Exception_TLB_Multiple_Hit: + rjmp $ +.org 0x008 +Exception_Bus_Error_Data_Fetch: + rjmp $ +.org 0x00C +Exception_Bus_Error_Instruction_Fetch: + rjmp $ +.org 0x010 +Exception_NMI: + rjmp $ +.org 0x014 +Exception_Instruction_Address: + rjmp $ +.org 0x018 +Exception_ITLB_Protection: + rjmp $ +.org 0x01C +Exception_OCD_Breakpoint: + rjmp $ +.org 0x020 +Exception_Illegal_Opcode: + rjmp $ +.org 0x024 +Exception_Unimplemented_Instruction: + rjmp $ +.org 0x028 +Exception_Privilege_Violation: + rjmp $ +.org 0x02C +Exception_Floating_Point: + rjmp $ +.org 0x030 +Exception_Coprocessor_Absent: + rjmp $ +.org 0x034 +Exception_Data_Address_Read: + rjmp $ +.org 0x038 +Exception_Data_Address_Write: + rjmp $ +.org 0x03C +Exception_DTLB_Protection_Read: + rjmp $ +.org 0x040 +Exception_DTLB_Protection_Write: + rjmp $ +.org 0x044 +Exception_DTLB_Modified: + rjmp $ +.org 0x050 +Exception_ITLB_Miss: + rjmp $ +.org 0x060 +Exception_DTLB_Miss_Read: + rjmp $ +.org 0x070 +Exception_DTLB_Miss_Write: + rjmp $ +.org 0x100 +Exception_Supervisor_Call: + rjmp $ +// ============== END OF EXCEPTION TABLE ============= + +// ============= GENERAL INTERRUPT HANDLER =========== +.balign 4 +.irp Level, 0, 1, 2, 3 +Exception_INT\Level: + mov r12, \Level + call INTC_GetInterruptHandler + mov pc, r12 +.endr +// ========= END OF GENERAL INTERRUPT HANDLER ======== + +// ====== GENERAL INTERRUPT HANDLER OFFSET TABLE ====== +.balign 4 +.global Autovector_Table +Autovector_Table: +.irp Level, 0, 1, 2, 3 + .word ((AVR32_INTC_INT0 + \Level) << AVR32_INTC_IPR_INTLEVEL_OFFSET) | (Exception_INT\Level - EVBA_Table) +.endr +// === END OF GENERAL INTERRUPT HANDLER OFFSET TABLE === diff --git a/LUFA/Platform/UC3/InterruptManagement.c b/LUFA/Platform/UC3/InterruptManagement.c new file mode 100644 index 0000000000..b1dda745cb --- /dev/null +++ b/LUFA/Platform/UC3/InterruptManagement.c @@ -0,0 +1,62 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#include "InterruptManagement.h" + +/** Interrupt vector table, containing the ISR to call for each interrupt group */ +InterruptHandlerPtr_t InterruptHandlers[AVR32_INTC_NUM_INT_GRPS]; + +/** ISR for unhandled interrupt groups */ +ISR(Unhandled_Interrupt) +{ + while (true); +} + +/** Retrieves the associated interrupt handler for the interrupt currently being fired. This is + * called directly from the exception handler routine before dispatching to the ISR. + */ +InterruptHandlerPtr_t INTC_GetInterruptHandler(const uint_reg_t InterruptLevel) +{ + return InterruptHandlers[AVR32_INTC.icr[AVR32_INTC_INT3 - InterruptLevel]]; +} + +/** Initializes the interrupt controller ready to handle interrupts. This must be called at the + * start of the user program before any interrupts are registered or enabled. + */ +void INTC_Init(void) +{ + for (uint8_t InterruptGroup = 0; InterruptGroup < AVR32_INTC_NUM_INT_GRPS; InterruptGroup++) + { + InterruptHandlers[InterruptGroup] = Unhandled_Interrupt; + AVR32_INTC.ipr[InterruptGroup] = Autovector_Table[AVR32_INTC_INT0]; + } + + __builtin_mtsr(AVR32_EVBA, (uintptr_t)&EVBA_Table); +} diff --git a/LUFA/Platform/UC3/InterruptManagement.h b/LUFA/Platform/UC3/InterruptManagement.h new file mode 100644 index 0000000000..fec099dba4 --- /dev/null +++ b/LUFA/Platform/UC3/InterruptManagement.h @@ -0,0 +1,83 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#ifndef _INTERRUPT_MANAGEMENT_H_ +#define _INTERRUPT_MANAGEMENT_H_ + + /* Includes: */ + #include + #include + #include + + #include + + /* Macros: */ + #if !defined(ISR) + #define ISR(Name) void Name (void) __attribute__((__interrupt__)); void Name (void) + #endif + + #define INTC_EnableInterrupts() do { GCC_MEMORY_BARRIER(); __builtin_csrf(AVR32_SR_GM_OFFSET); } while (0) + #define INTC_DisableInterrupts() do { __builtin_ssrf(AVR32_SR_GM_OFFSET); GCC_MEMORY_BARRIER(); } while (0) + + /* Type Defines: */ + typedef void (*InterruptHandlerPtr_t)(void); + + /* External Variables: */ + extern const void EVBA_Table; + extern const uint32_t Autovector_Table[]; + extern InterruptHandlerPtr_t InterruptHandlers[AVR32_INTC_NUM_INT_GRPS]; + + /* Function Prototypes: */ + void INTC_Init(void); + + /* Inline Functions: */ + /** Registers a handler for a given interrupt group. On the AVR32 UC3 devices, interrupts are grouped by + * peripheral. To save on SRAM used, a single ISR handles all interrupt lines within a single group - to + * determine the exact line that has interrupted within the group ISR handler, examine the module's interrupt + * flag register bits. + * + * If multiple interrupts with the same group are registered, the last registered handler will become the + * handler called for interrupts raised within that group. + * + * \param[in] InterruptRequest Interrupt request index for the given interrupt, a AVR32_*_IRQ mask. + * \param[in] InterruptLevel Priority level for the specified interrupt, a AVR32_INTC_INT* mask. + * \param[in] Handler Address of the ISR handler for the interrupt group. + */ + static inline void INTC_RegisterGroupHandler(const uint16_t InterruptRequest, + const uint8_t InterruptLevel, + const InterruptHandlerPtr_t Handler) + { + uint8_t InterruptGroup = (InterruptRequest >> 5); + + InterruptHandlers[InterruptGroup] = Handler; + AVR32_INTC.ipr[InterruptGroup] = Autovector_Table[InterruptLevel]; + } + +#endif