From c0a5eb38e2a2d5dd8e8cb1371502669b7544ea0b Mon Sep 17 00:00:00 2001 From: Thibaut VIARD Date: Sat, 28 Apr 2012 11:49:28 +0200 Subject: [PATCH] [sam] adding USB updates --- hardware/arduino/sam/cores/sam/UARTClass.cpp | 6 +- hardware/arduino/sam/cores/sam/USARTClass.cpp | 6 +- hardware/arduino/sam/cores/sam/USB/HID.cpp | 127 +- hardware/arduino/sam/cores/sam/USB/USBAPI.h | 7 +- hardware/arduino/sam/cores/sam/USB/USBCore.h | 46 +- .../sam/build_gcc/libarduino_arduino_due_x.mk | 12 +- hardware/arduino/sam/cores/sam/main.cpp | 14 +- .../arduino/sam/cores/sam/syscalls_sam3.c | 10 +- .../build_gcc/test_usb_device.mk | 11 +- .../validation_usb_device/test_usb_device.cpp | 140 ++- hardware/arduino/sam/cores/sam/wiring.c | 2 +- .../arduino/sam/cores/sam/wiring_digital.c | 6 +- hardware/arduino/sam/platform.txt | 3 +- .../sam/system/libsam/build_gcc/sam3.mk | 2 +- hardware/arduino/sam/system/libsam/chip.h | 4 +- .../arduino/sam/system/libsam/include/pmc.h | 401 +++++- .../arduino/sam/system/libsam/source/pmc.c | 1118 +++++++++++++++-- .../arduino/sam/system/libsam/source/spi.c | 4 +- .../sam/system/libsam/source/timetick.c | 2 +- .../arduino/sam/system/libsam/source/udp.c | 4 +- .../arduino/sam/system/libsam/source/udphs.c | 16 +- .../sam/variants/arduino_due_x/variant.cpp | 20 +- .../sam/variants/arduino_due_x/variant.h | 7 +- 23 files changed, 1623 insertions(+), 345 deletions(-) diff --git a/hardware/arduino/sam/cores/sam/UARTClass.cpp b/hardware/arduino/sam/cores/sam/UARTClass.cpp index 2ef23a7e1..106a79cc5 100644 --- a/hardware/arduino/sam/cores/sam/UARTClass.cpp +++ b/hardware/arduino/sam/cores/sam/UARTClass.cpp @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -37,7 +37,7 @@ UARTClass::UARTClass( Uart* pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* p void UARTClass::begin( const uint32_t dwBaudRate ) { // Configure PMC - PMC_EnablePeripheral( _dwId ) ; + pmc_enable_periph_clk( _dwId ) ; // Disable PDC channel _pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS ; @@ -73,7 +73,7 @@ void UARTClass::end( void ) // Wait for any outstanding data to be sent flush(); - PMC_DisablePeripheral( _dwId ) ; + pmc_disable_periph_clk( _dwId ) ; } int UARTClass::available( void ) diff --git a/hardware/arduino/sam/cores/sam/USARTClass.cpp b/hardware/arduino/sam/cores/sam/USARTClass.cpp index a1b511a72..c00f3df57 100644 --- a/hardware/arduino/sam/cores/sam/USARTClass.cpp +++ b/hardware/arduino/sam/cores/sam/USARTClass.cpp @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -37,7 +37,7 @@ USARTClass::USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffe void USARTClass::begin( const uint32_t dwBaudRate ) { // Configure PMC - PMC_EnablePeripheral( _dwId ) ; + pmc_enable_periph_clk( _dwId ) ; // Disable PDC channel _pUsart->US_PTCR = US_PTCR_RXTDIS | US_PTCR_TXTDIS ; @@ -74,7 +74,7 @@ void USARTClass::end( void ) // Wait for any outstanding data to be sent flush(); - PMC_DisablePeripheral( _dwId ) ; + pmc_disable_periph_clk( _dwId ) ; } int USARTClass::available( void ) diff --git a/hardware/arduino/sam/cores/sam/USB/HID.cpp b/hardware/arduino/sam/cores/sam/USB/HID.cpp index 0bdf444af..ae2c04290 100644 --- a/hardware/arduino/sam/cores/sam/USB/HID.cpp +++ b/hardware/arduino/sam/cores/sam/USB/HID.cpp @@ -1,26 +1,28 @@ -/* Copyright (c) 2011, Peter Barrett -** -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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. +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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. */ -#if defined(USBCON) +#define USBCON + #include "Platform.h" #include "USBAPI.h" #include "USBDesc.h" +#if defined(USBCON) #ifdef HID_ENABLED //#define RAWHID_ENABLED @@ -43,9 +45,7 @@ Keyboard_ Keyboard; #define RAWHID_TX_SIZE 64 #define RAWHID_RX_SIZE 64 -extern const u8 _hidReportDescriptor[] PROGMEM; -const u8 _hidReportDescriptor[] = { - +extern const u8 _hidReportDescriptor[] = { // Mouse 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54 0x09, 0x02, // USAGE (Mouse) @@ -82,31 +82,31 @@ const u8 _hidReportDescriptor[] = { 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x02, // REPORT_ID (2) 0x05, 0x07, // USAGE_PAGE (Keyboard) - + 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) - + 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) - + 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) - + 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION -#if RAWHID_ENABLED +#ifdef RAWHID_ENABLED // RAW HID 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), @@ -128,8 +128,7 @@ const u8 _hidReportDescriptor[] = { #endif }; -extern const HIDDescriptor _hidInterface PROGMEM; -const HIDDescriptor _hidInterface = +extern const HIDDescriptor _hidInterface = { D_INTERFACE(HID_INTERFACE,1,3,0,0), D_HIDREPORT(sizeof(_hidReportDescriptor)), @@ -179,7 +178,7 @@ bool WEAK HID_Setup(Setup& setup) return true; } } - + if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (HID_SET_PROTOCOL == r) @@ -205,11 +204,11 @@ Mouse_::Mouse_(void) : _buttons(0) { } -void Mouse_::begin(void) +void Mouse_::begin(void) { } -void Mouse_::end(void) +void Mouse_::end(void) { } @@ -240,7 +239,7 @@ void Mouse_::buttons(uint8_t b) } } -void Mouse_::press(uint8_t b) +void Mouse_::press(uint8_t b) { buttons(_buttons | b); } @@ -252,7 +251,7 @@ void Mouse_::release(uint8_t b) bool Mouse_::isPressed(uint8_t b) { - if ((b & _buttons) > 0) + if ((b & _buttons) > 0) return true; return false; } @@ -261,15 +260,15 @@ bool Mouse_::isPressed(uint8_t b) //================================================================================ // Keyboard -Keyboard_::Keyboard_(void) +Keyboard_::Keyboard_(void) { } -void Keyboard_::begin(void) +void Keyboard_::begin(void) { } -void Keyboard_::end(void) +void Keyboard_::end(void) { } @@ -278,11 +277,8 @@ void Keyboard_::sendReport(KeyReport* keys) HID_SendReport(2,keys,sizeof(KeyReport)); } -extern -const uint8_t _asciimap[128] PROGMEM; - #define SHIFT 0x80 -const uint8_t _asciimap[128] = +extern const uint8_t _asciimap[128] = { 0x00, // NUL 0x00, // SOH @@ -290,16 +286,16 @@ const uint8_t _asciimap[128] = 0x00, // ETX 0x00, // EOT 0x00, // ENQ - 0x00, // ACK + 0x00, // ACK 0x00, // BEL 0x2a, // BS Backspace 0x2b, // TAB Tab 0x28, // LF Enter - 0x00, // VT - 0x00, // FF - 0x00, // CR - 0x00, // SO - 0x00, // SI + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI 0x00, // DEL 0x00, // DC1 0x00, // DC2 @@ -309,13 +305,13 @@ const uint8_t _asciimap[128] = 0x00, // SYN 0x00, // ETB 0x00, // CAN - 0x00, // EM + 0x00, // EM 0x00, // SUB 0x00, // ESC - 0x00, // FS - 0x00, // GS - 0x00, // RS - 0x00, // US + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US 0x2c, // ' ' 0x1e|SHIFT, // ! @@ -408,7 +404,7 @@ const uint8_t _asciimap[128] = 0x1b, // x 0x1c, // y 0x1d, // z - 0x2f|SHIFT, // + 0x2f|SHIFT, // 0x31|SHIFT, // | 0x30|SHIFT, // } 0x35|SHIFT, // ~ @@ -418,10 +414,10 @@ const uint8_t _asciimap[128] = uint8_t USBPutChar(uint8_t c); // press() adds the specified key (printing, non-printing, or modifier) -// to the persistent key report and sends the report. Because of the way -// USB HID works, the host acts like the key remains pressed until we +// to the persistent key report and sends the report. Because of the way +// USB HID works, the host acts like the key remains pressed until we // call release(), releaseAll(), or otherwise clear the report and resend. -size_t Keyboard_::press(uint8_t k) +size_t Keyboard_::press(uint8_t k) { uint8_t i; if (k >= 136) { // it's a non-printing key (not a modifier) @@ -430,7 +426,7 @@ size_t Keyboard_::press(uint8_t k) _keyReport.modifiers |= (1<<(k-128)); k = 0; } else { // it's a printing key - k = pgm_read_byte(_asciimap + k); + k = _asciimap[k]; if (!k) { setWriteError(); return 0; @@ -440,13 +436,13 @@ size_t Keyboard_::press(uint8_t k) k &= 0x7F; } } - + // Add k to the key report only if it's not already present // and if there is an empty slot. - if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && + if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && _keyReport.keys[2] != k && _keyReport.keys[3] != k && _keyReport.keys[4] != k && _keyReport.keys[5] != k) { - + for (i=0; i<6; i++) { if (_keyReport.keys[i] == 0x00) { _keyReport.keys[i] = k; @@ -456,7 +452,7 @@ size_t Keyboard_::press(uint8_t k) if (i == 6) { setWriteError(); return 0; - } + } } sendReport(&_keyReport); return 1; @@ -465,7 +461,7 @@ size_t Keyboard_::press(uint8_t k) // release() takes the specified key out of the persistent key report and // sends the report. This tells the OS the key is no longer pressed and that // it shouldn't be repeated any more. -size_t Keyboard_::release(uint8_t k) +size_t Keyboard_::release(uint8_t k) { uint8_t i; if (k >= 136) { // it's a non-printing key (not a modifier) @@ -474,7 +470,7 @@ size_t Keyboard_::release(uint8_t k) _keyReport.modifiers &= ~(1<<(k-128)); k = 0; } else { // it's a printing key - k = pgm_read_byte(_asciimap + k); + k = _asciimap[k]; if (!k) { return 0; } @@ -483,7 +479,7 @@ size_t Keyboard_::release(uint8_t k) k &= 0x7F; } } - + // Test the key report to see if k is present. Clear it if it exists. // Check all positions in case the key is present more than once (which it shouldn't be) for (i=0; i<6; i++) { @@ -499,20 +495,23 @@ size_t Keyboard_::release(uint8_t k) void Keyboard_::releaseAll(void) { _keyReport.keys[0] = 0; - _keyReport.keys[1] = 0; + _keyReport.keys[1] = 0; _keyReport.keys[2] = 0; - _keyReport.keys[3] = 0; + _keyReport.keys[3] = 0; _keyReport.keys[4] = 0; - _keyReport.keys[5] = 0; + _keyReport.keys[5] = 0; _keyReport.modifiers = 0; sendReport(&_keyReport); } size_t Keyboard_::write(uint8_t c) -{ +{ +/* TODO uint8_t p = press(c); // Keydown uint8_t r = release(c); // Keyup return (p); // just return the result of press() since release() almost always returns 1 + */ + return 1 ; } #endif diff --git a/hardware/arduino/sam/cores/sam/USB/USBAPI.h b/hardware/arduino/sam/cores/sam/USB/USBAPI.h index f66cb16d2..8fcf0f2c1 100644 --- a/hardware/arduino/sam/cores/sam/USB/USBAPI.h +++ b/hardware/arduino/sam/cores/sam/USB/USBAPI.h @@ -28,7 +28,7 @@ extern USB_ USB; class Serial_ : public Stream { private: - ring_buffer *_cdc_rx_buffer; + RingBuffer *_cdc_rx_buffer; public: void begin(uint16_t baud_count); void end(void); @@ -39,6 +39,7 @@ public: virtual int read(void); virtual void flush(void); virtual size_t write(uint8_t); + virtual void write(uint8_t); operator bool(); }; extern Serial_ Serial; @@ -62,7 +63,7 @@ public: void begin(void); void end(void); void click(uint8_t b = MOUSE_LEFT); - void move(signed char x, signed char y, signed char wheel = 0); + void move(signed char x, signed char y, signed char wheel = 0); void press(uint8_t b = MOUSE_LEFT); // press LEFT by default void release(uint8_t b = MOUSE_LEFT); // release LEFT by default bool isPressed(uint8_t b = MOUSE_ALL); // check all buttons by default @@ -192,4 +193,4 @@ void USB_Flush(uint8_t ep); #endif -#endif /* if defined(USBCON) */ \ No newline at end of file +#endif /* if defined(USBCON) */ diff --git a/hardware/arduino/sam/cores/sam/USB/USBCore.h b/hardware/arduino/sam/cores/sam/USB/USBCore.h index 8d1380689..15ed54f37 100644 --- a/hardware/arduino/sam/cores/sam/USB/USBCore.h +++ b/hardware/arduino/sam/cores/sam/USB/USBCore.h @@ -1,18 +1,18 @@ -// Copyright (c) 2010, Peter Barrett +// Copyright (c) 2010, Peter Barrett /* -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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. +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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 __USBCORE_H__ @@ -117,8 +117,8 @@ #define CDC_CS_ENDPOINT 0x25 #define CDC_DATA_INTERFACE_CLASS 0x0A -#define MSC_SUBCLASS_SCSI 0x06 -#define MSC_PROTOCOL_BULK_ONLY 0x50 +#define MSC_SUBCLASS_SCSI 0x06 +#define MSC_PROTOCOL_BULK_ONLY 0x50 #define HID_HID_DESCRIPTOR_TYPE 0x21 #define HID_REPORT_DESCRIPTOR_TYPE 0x22 @@ -214,7 +214,7 @@ typedef struct u8 d0; } CDCCSInterfaceDescriptor4; -typedef struct +typedef struct { u8 len; u8 dtype; // 0x24 @@ -222,8 +222,8 @@ typedef struct u8 bmCapabilities; u8 bDataInterface; } CMFunctionalDescriptor; - -typedef struct + +typedef struct { u8 len; u8 dtype; // 0x24 @@ -231,13 +231,13 @@ typedef struct u8 bmCapabilities; } ACMFunctionalDescriptor; -typedef struct +typedef struct { // IAD IADDescriptor iad; // Only needed on compound device // Control - InterfaceDescriptor cif; // + InterfaceDescriptor cif; // CDCCSInterfaceDescriptor header; CMFunctionalDescriptor callManagement; // Call Management ACMFunctionalDescriptor controlManagement; // ACM @@ -250,7 +250,7 @@ typedef struct EndpointDescriptor out; } CDCDescriptor; -typedef struct +typedef struct { InterfaceDescriptor msc; EndpointDescriptor in; @@ -270,7 +270,7 @@ typedef struct u8 descLenH; } HIDDescDescriptor; -typedef struct +typedef struct { InterfaceDescriptor hid; HIDDescDescriptor desc; @@ -300,4 +300,4 @@ typedef struct #define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } -#endif \ No newline at end of file +#endif diff --git a/hardware/arduino/sam/cores/sam/build_gcc/libarduino_arduino_due_x.mk b/hardware/arduino/sam/cores/sam/build_gcc/libarduino_arduino_due_x.mk index 90228a53e..0283daddd 100644 --- a/hardware/arduino/sam/cores/sam/build_gcc/libarduino_arduino_due_x.mk +++ b/hardware/arduino/sam/cores/sam/build_gcc/libarduino_arduino_due_x.mk @@ -34,6 +34,7 @@ OUTPUT_BIN = .. # Libraries PROJECT_BASE_PATH = .. +PROJECT_BASE_PATH_USB = ../USB SYSTEM_PATH = ../../../system CMSIS_ROOT_PATH = $(SYSTEM_PATH)/CMSIS CMSIS_ARM_PATH=$(CMSIS_ROOT_PATH)/CMSIS/Include @@ -45,14 +46,15 @@ VARIANT_PATH = ../../../variants/$(VARIANT) # Files #------------------------------------------------------------------------------- -vpath %.h $(PROJECT_BASE_PATH) $(SYSTEM_PATH) $(VARIANT_PATH) -vpath %.c $(PROJECT_BASE_PATH) $(VARIANT_PATH) -vpath %.cpp $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH) +vpath %.h $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH_USB) $(SYSTEM_PATH) $(VARIANT_PATH) +vpath %.c $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH_USB) $(VARIANT_PATH) +vpath %.cpp $(PROJECT_BASE_PATH) $(PROJECT_BASE_PATH_USB) $(PROJECT_BASE_PATH) VPATH+=$(PROJECT_BASE_PATH) INCLUDES = INCLUDES += -I$(PROJECT_BASE_PATH) +INCLUDES += -I$(PROJECT_BASE_PATH_USB) INCLUDES += -I$(VARIANT_PATH) INCLUDES += -I$(CMSIS_ARM_PATH) INCLUDES += -I$(CMSIS_ATMEL_PATH) @@ -86,7 +88,7 @@ OUTPUT_PATH=$(OUTPUT_OBJ)_$(VARIANT) #------------------------------------------------------------------------------- # C source files and objects #------------------------------------------------------------------------------- -C_SRC=$(wildcard $(PROJECT_BASE_PATH)/*.c) +C_SRC=$(wildcard $(PROJECT_BASE_PATH)/*.c $(PROJECT_BASE_PATH_USB)/*.c) C_OBJ_TEMP = $(patsubst %.c, %.o, $(notdir $(C_SRC))) @@ -98,7 +100,7 @@ C_OBJ=$(filter-out $(C_OBJ_FILTER), $(C_OBJ_TEMP)) #------------------------------------------------------------------------------- # CPP source files and objects #------------------------------------------------------------------------------- -CPP_SRC=$(wildcard $(PROJECT_BASE_PATH)/*.cpp) +CPP_SRC=$(wildcard $(PROJECT_BASE_PATH)/*.cpp $(PROJECT_BASE_PATH_USB)/*.cpp) CPP_OBJ_TEMP = $(patsubst %.cpp, %.o, $(notdir $(CPP_SRC))) diff --git a/hardware/arduino/sam/cores/sam/main.cpp b/hardware/arduino/sam/cores/sam/main.cpp index 325e6a807..7888c4cb9 100644 --- a/hardware/arduino/sam/cores/sam/main.cpp +++ b/hardware/arduino/sam/cores/sam/main.cpp @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -24,14 +24,14 @@ */ int main( void ) { - init() ; + init(); - setup() ; + setup(); - for ( ; ; ) - { - loop() ; - } + for (;;) + { + loop(); + } // return 0 ; } diff --git a/hardware/arduino/sam/cores/sam/syscalls_sam3.c b/hardware/arduino/sam/cores/sam/syscalls_sam3.c index e0f72dd46..23256db6d 100644 --- a/hardware/arduino/sam/cores/sam/syscalls_sam3.c +++ b/hardware/arduino/sam/cores/sam/syscalls_sam3.c @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -32,6 +32,7 @@ #include #include +#include "sam.h" #if defined ( __GNUC__ ) /* GCC CS3 */ #include #include @@ -109,6 +110,13 @@ extern int _write( int file, char *ptr, int len ) for ( iIndex=0 ; iIndex < len ; iIndex++, ptr++ ) { // UART_PutChar( *ptr ) ; + + // Check if the transmitter is ready + while ((UART->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY) + ; + + // Send character + UART->UART_THR = *ptr; } return iIndex ; diff --git a/hardware/arduino/sam/cores/sam/validation_usb_device/build_gcc/test_usb_device.mk b/hardware/arduino/sam/cores/sam/validation_usb_device/build_gcc/test_usb_device.mk index 283c19206..d6cb4fcde 100644 --- a/hardware/arduino/sam/cores/sam/validation_usb_device/build_gcc/test_usb_device.mk +++ b/hardware/arduino/sam/cores/sam/validation_usb_device/build_gcc/test_usb_device.mk @@ -8,7 +8,7 @@ # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public @@ -99,6 +99,7 @@ INCLUDES += -I$(SYSTEM_PATH)/libsam INCLUDES += -I$(CMSIS_ARM_PATH) INCLUDES += -I$(CMSIS_ATMEL_PATH) INCLUDES += -I$(CMSIS_CHIP_PATH) +INCLUDES += -I$(PROJECT_BASE_PATH)/../USB #------------------------------------------------------------------------------- ifdef DEBUG @@ -153,7 +154,7 @@ test: create_output libsam_$(CHIP_NAME)_$(TOOLCHAIN)_$(LIBS_POSTFIX).a libarduin .PHONY: create_output create_output: - @echo --- Preparing $(VARIANT) files in $(OUTPUT_PATH) $(OUTPUT_BIN) + @echo --- Preparing $(VARIANT) files in $(OUTPUT_PATH) $(OUTPUT_BIN) # @echo ------------------------- # @echo *$(INCLUDES) # @echo ------------------------- @@ -190,11 +191,11 @@ $(OUTPUT_BIN): $(addprefix $(OUTPUT_PATH)/, $(C_OBJ)) $(addprefix $(OUTPUT_PATH) clean: @echo --- Cleaning test files -@$(RM) $(OUTPUT_PATH) 1>NUL 2>&1 - + # -$(RM) $(OUTPUT_PATH)/test.o -# -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).elf +# -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).elf # -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).elf.txt -# -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).bin +# -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).bin # -$(RM) $(OUTPUT_PATH)/$(OUTPUT_BIN).map debug: test diff --git a/hardware/arduino/sam/cores/sam/validation_usb_device/test_usb_device.cpp b/hardware/arduino/sam/cores/sam/validation_usb_device/test_usb_device.cpp index 5e581f88a..c69bb60fe 100644 --- a/hardware/arduino/sam/cores/sam/validation_usb_device/test_usb_device.cpp +++ b/hardware/arduino/sam/cores/sam/validation_usb_device/test_usb_device.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2011 Arduino. All right reserved. + Copyright (c) 2012 Arduino. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -17,74 +17,86 @@ */ #include "variant.h" +#include -void setup( void ) -{ - // Initialize the digital pin as an output. - // Pin PIN_LED has a LED connected on most Arduino boards: - pinMode( PIN_LED, OUTPUT ) ; - digitalWrite( PIN_LED, LOW ) ; +// set pin numbers for the five buttons: +const int upButton = 2; +const int downButton = 3; +const int leftButton = 4; +const int rightButton = 5; +const int mouseButton = 6; - // Initialize the PIN_LED2 digital pin as an output. - pinMode( PIN_LED2, OUTPUT ) ; - digitalWrite( PIN_LED2, HIGH ) ; +int range = 5; // output range of X or Y movement; affects movement speed +int responseDelay = 10; // response delay of the mouse, in ms - Serial1.begin( 115200 ) ; +/* +void setup() { + // initialize the buttons' inputs: + pinMode(upButton, INPUT); + pinMode(downButton, INPUT); + pinMode(leftButton, INPUT); + pinMode(rightButton, INPUT); + pinMode(mouseButton, INPUT); + // initialize mouse control: + Mouse.begin(); } -static void led_step1( void ) -{ -#if defined sam3s_ek - digitalWrite( PIN_LED, HIGH ) ; // set the LED on - digitalWrite( PIN_LED2, LOW ) ; // set the red LED off -#endif /* sam3s_ek */ +void loop() { + // read the buttons: + int upState = digitalRead(upButton); + int downState = digitalRead(downButton); + int rightState = digitalRead(rightButton); + int leftState = digitalRead(leftButton); + int clickState = digitalRead(mouseButton); -#if defined sam3u_ek - digitalWrite( PIN_LED, HIGH ) ; // set the LED on - digitalWrite( PIN_LED2, LOW ) ; // set the red LED off -#endif /* sam3u_ek */ + // calculate the movement distance based on the button states: + int xDistance = (leftState - rightState)*range; + int yDistance = (upState - downState)*range; -#if defined arduino_due_x - digitalWrite( PIN_LED, LOW ) ; // set the LED on - digitalWrite( PIN_LED2, LOW ) ; // set the red LED off -#endif /* arduino_due_x */ -} - -static void led_step2( void ) -{ -#if defined sam3s_ek - digitalWrite( PIN_LED, LOW ) ; // set the LED off - digitalWrite( PIN_LED2, HIGH ) ; // set the red LED on -#endif /* sam3s_ek */ - -#if defined sam3u_ek - digitalWrite( PIN_LED, LOW ) ; // set the LED off - digitalWrite( PIN_LED2, HIGH ) ; // set the red LED on -#endif /* sam3u_ek */ - -#if defined arduino_due_x - digitalWrite( PIN_LED, HIGH ) ; // set the LED off - digitalWrite( PIN_LED2, HIGH ) ; // set the red LED on -#endif /* arduino_due_x */ -} - -void loop( void ) -{ - led_step1() ; - delay( 1000 ) ; // wait for a second - led_step2() ; - delay( 1000 ) ; // wait for a second - - Serial1.write( '-' ) ; // send a char -// Serial1.write( "test1\n" ) ; // send a string -// Serial1.write( "test2" ) ; // send another string - - Serial1.print("Analog ins: "); - for (int i=A0; iPIO_OSR == 0xffffffff ) { - PMC_DisablePeripheral( g_APinDescription[ulPin].ulPeripheralId ) ; + pmc_disable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ; } PIO_Configure( g_APinDescription[ulPin].pPort, PIO_OUTPUT_1, g_APinDescription[ulPin].ulPin, g_APinDescription[ulPin].ulPinConfiguration ) ; break ; diff --git a/hardware/arduino/sam/platform.txt b/hardware/arduino/sam/platform.txt index 12e67027d..d1f0f4c83 100644 --- a/hardware/arduino/sam/platform.txt +++ b/hardware/arduino/sam/platform.txt @@ -3,7 +3,8 @@ # --------------------- name=Atmel SAM3 -compiler.path={runtime.ide.path}/hardware/tools/g++_arm_none_eabi/bin/ +#compiler.path={runtime.ide.path}/hardware/tools/g++_arm_none_eabi/bin/ +compiler.path=C:/arm-none-eabi-gcc-4_6/bin/ compiler.c.cmd=arm-none-eabi-gcc compiler.c.flags=-c -g -Os -w -mlong-calls -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -Dprintf=iprintf compiler.c.elf.cmd=arm-none-eabi-gcc diff --git a/hardware/arduino/sam/system/libsam/build_gcc/sam3.mk b/hardware/arduino/sam/system/libsam/build_gcc/sam3.mk index c2d073b35..825ceb4b7 100644 --- a/hardware/arduino/sam/system/libsam/build_gcc/sam3.mk +++ b/hardware/arduino/sam/system/libsam/build_gcc/sam3.mk @@ -176,7 +176,7 @@ $(OUTPUT_LIB): $(addprefix $(OUTPUT_PATH)/, $(C_OBJ)) $(addprefix $(OUTPUT_PATH) .PHONY: clean clean: @echo --- Cleaning $(CHIP) files $(OUTPUT_PATH) $(subst /,$(SEP),$(OUTPUT_BIN)/$(OUTPUT_LIB)) - -@$(RM) $(OUTPUT_PATH) + -@$(RM) $(OUTPUT_PATH) 1>$(DEV_NUL) 2>&1 -@$(RM) $(subst /,$(SEP),$(OUTPUT_BIN)/$(OUTPUT_LIB)) 1>$(DEV_NUL) 2>&1 -@$(RM) $(subst /,$(SEP),$(OUTPUT_BIN)/$(OUTPUT_LIB)).txt 1>$(DEV_NUL) 2>&1 diff --git a/hardware/arduino/sam/system/libsam/chip.h b/hardware/arduino/sam/system/libsam/chip.h index d557371f5..0843d47be 100644 --- a/hardware/arduino/sam/system/libsam/chip.h +++ b/hardware/arduino/sam/system/libsam/chip.h @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -54,7 +54,7 @@ #include "include/wdt.h" #include "include/timetick.h" -#include "include/USB_driver.h" +#include "include/USB_device.h" #if SAM3XA_SERIES #include "include/uotghs.h" diff --git a/hardware/arduino/sam/system/libsam/include/pmc.h b/hardware/arduino/sam/system/libsam/include/pmc.h index 5b82a1f0b..ec784a609 100644 --- a/hardware/arduino/sam/system/libsam/include/pmc.h +++ b/hardware/arduino/sam/system/libsam/include/pmc.h @@ -1,5 +1,5 @@ /* ---------------------------------------------------------------------------- - * SAM Software Package License + * SAM Software Package License * ---------------------------------------------------------------------------- * Copyright (c) 2011, Atmel Corporation * @@ -27,30 +27,399 @@ * ---------------------------------------------------------------------------- */ -#ifndef _PMC_ -#define _PMC_ +#ifndef PMC_H_INCLUDED +#define PMC_H_INCLUDED -/*---------------------------------------------------------------------------- - * Headers - *----------------------------------------------------------------------------*/ -#include - -/*---------------------------------------------------------------------------- - * Exported functions - *----------------------------------------------------------------------------*/ +#include "../chip.h" +/// @cond 0 +/**INDENT-OFF**/ #ifdef __cplusplus - extern "C" { +extern "C" { +#endif +/**INDENT-ON**/ +/// @endcond + +/** Bit mask for peripheral clocks (PCER0) */ +#define PMC_MASK_STATUS0 (0xFFFFFFFC) + +/** Bit mask for peripheral clocks (PCER1) */ +#define PMC_MASK_STATUS1 (0xFFFFFFFF) + +/** Loop counter timeout value */ +#define PMC_TIMEOUT (2048) + +/** Key to unlock CKGR_MOR register */ +#define PMC_CKGR_MOR_KEY_VALUE CKGR_MOR_KEY(0x37) + +/** Key used to write SUPC registers */ +#define SUPC_KEY_VALUE ((uint32_t) 0xA5) + +/** PMC xtal statup time */ +#define PMC_XTAL_STARTUP_TIME (0x3F) + +/** Mask to access fast startup input */ +#define PMC_FAST_STARTUP_Msk (0xFFFFu) + +/** PMC_WPMR Write Protect KEY, unlock it */ +#define PMC_WPMR_WPKEY_VALUE PMC_WPMR_WPKEY((uint32_t) 0x504D43) + +/** Using external oscillator */ +#define PMC_OSC_XTAL 0 + +/** Oscillator in bypass mode */ +#define PMC_OSC_BYPASS 1 + +#define PMC_PCK_0 0 /* PCK0 ID */ +#define PMC_PCK_1 1 /* PCK1 ID */ +#define PMC_PCK_2 2 /* PCK2 ID */ + +/** + * \name Master clock (MCK) Source and Prescaler configuration + * + * The following functions may be used to select the clock source and + * prescaler for the master clock. + */ +//@{ + +void pmc_mck_set_prescaler(uint32_t ul_pres); +void pmc_mck_set_source(uint32_t ul_source); +uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres); +uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres); +uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres); +#if (SAM3S_SERIES || SAM4S_SERIES) +uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres); +#endif +#if (SAM3XA_SERIES || SAM3U_SERIES) +uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres); #endif -extern void PMC_EnablePeripheral( uint32_t dwId ) ; -extern void PMC_DisablePeripheral( uint32_t dwId ) ; +//@} -extern uint32_t PMC_IsPeripheralEnabled( uint32_t dwId ) ; +/** + * \name Slow clock (SLCK) oscillator and configuration + * + */ +//@{ +void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass); +uint32_t pmc_osc_is_ready_32kxtal(void); + +//@} + +/** + * \name Main Clock (MAINCK) oscillator and configuration + * + */ +//@{ + +void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf); +void pmc_osc_enable_fastrc(uint32_t ul_rc); +void pmc_osc_disable_fastrc(void); +void pmc_switch_mainck_to_xtal(uint32_t ul_bypass); +void pmc_osc_disable_xtal(uint32_t ul_bypass); +uint32_t pmc_osc_is_ready_mainck(void); + +//@} + +/** + * \name PLL oscillator and configuration + * + */ +//@{ + +void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva); +void pmc_disable_pllack(void); +uint32_t pmc_is_locked_pllack(void); + +#if (SAM3S_SERIES || SAM4S_SERIES) +void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb); +void pmc_disable_pllbck(void); +uint32_t pmc_is_locked_pllbck(void); +#endif + +#if (SAM3XA_SERIES || SAM3U_SERIES) +void pmc_enable_upll_clock(void); +void pmc_disable_upll_clock(void); +uint32_t pmc_is_locked_upll(void); +#endif + +//@} + +/** + * \name Peripherals clock configuration + * + */ +//@{ + +uint32_t pmc_enable_periph_clk(uint32_t ul_id); +uint32_t pmc_disable_periph_clk(uint32_t ul_id); +void pmc_enable_all_periph_clk(void); +void pmc_disable_all_periph_clk(void); +uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id); + +//@} + +/** + * \name Programmable clock Source and Prescaler configuration + * + * The following functions may be used to select the clock source and + * prescaler for the specified programmable clock. + */ +//@{ + +void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres); +void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source); +uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres); +uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres); +uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres); +#if (SAM3S_SERIES || SAM4S_SERIES) +uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres); +#endif +#if (SAM3XA_SERIES || SAM3U_SERIES) +uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres); +#endif +void pmc_enable_pck(uint32_t ul_id); +void pmc_disable_pck(uint32_t ul_id); +void pmc_enable_all_pck(void); +void pmc_disable_all_pck(void); +uint32_t pmc_is_pck_enabled(uint32_t ul_id); + +//@} + +/** + * \name USB clock configuration + * + */ +//@{ + +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) +void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv); +#endif +#if (SAM3S_SERIES || SAM4S_SERIES) +void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv); +#endif +#if (SAM3XA_SERIES) +void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv); +#endif +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) +void pmc_enable_udpck(void); +void pmc_disable_udpck(void); +#endif + +//@} + +/** + * \name Interrupt and status management + * + */ +//@{ + +void pmc_enable_interrupt(uint32_t ul_sources); +void pmc_disable_interrupt(uint32_t ul_sources); +uint32_t pmc_get_interrupt_mask(void); +uint32_t pmc_get_status(void); + +//@} + +/** + * \name Power management + * + * The following functions are used to configure sleep mode and additionnal + * wake up inputs. + */ +//@{ + +void pmc_set_fast_startup_input(uint32_t ul_inputs); +void pmc_clr_fast_startup_input(uint32_t ul_inputs); +void pmc_enable_sleepmode(uint8_t uc_type); +void pmc_enable_waitmode(void); +void pmc_enable_backupmode(void); + +//@} + +/** + * \name Write protection + * + */ +//@{ + +void pmc_set_writeprotect(uint32_t ul_enable); +uint32_t pmc_get_writeprotect_status(void); + +//@} + +/// @cond 0 +/**INDENT-OFF**/ #ifdef __cplusplus } #endif +/**INDENT-ON**/ +/// @endcond -#endif /* #ifndef _PMC_ */ +//! @} +/** + * \page sam_pmc_quickstart Quick start guide for the SAM PMC module + * + * This is the quick start guide for the \ref pmc_group "PMC module", with + * step-by-step instructions on how to configure and use the driver in a + * selection of use cases. + * + * The use cases contain several code fragments. The code fragments in the + * steps for setup can be copied into a custom initialization function, while + * the steps for usage can be copied into, e.g., the main application function. + * + * \section pmc_use_cases PMC use cases + * - \ref pmc_basic_use_case Basic use case - Switch Main Clock sources + * - \ref pmc_use_case_2 Advanced use case - Configure Programmable Clocks + * + * \section pmc_basic_use_case Basic use case - Switch Main Clock sources + * In this use case, the PMC module is configured for a variety of system clock + * sources and speeds. A LED is used to visually indicate the current clock + * speed as the source is switched. + * + * \section pmc_basic_use_case_setup Setup + * + * \subsection pmc_basic_use_case_setup_prereq Prerequisites + * -# \ref gpio_group "General Purpose I/O Management (gpio)" + * + * \subsection pmc_basic_use_case_setup_code Code + * The following function needs to be added to the user application, to flash a + * board LED a variable number of times at a rate given in CPU ticks. + * + * \code + * #define FLASH_TICK_COUNT 0x00012345 + * + * void flash_led(uint32_t tick_count, uint8_t flash_count) + * { + * SysTick->CTRL = SysTick_CTRL_ENABLE_Msk; + * SysTick->LOAD = tick_count; + * + * while (flash_count--) + * { + * gpio_toggle_pin(LED0_GPIO); + * while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); + * gpio_toggle_pin(LED0_GPIO); + * while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); + * } + * } + * \endcode + * + * \section pmc_basic_use_case_usage Use case + * + * \subsection pmc_basic_use_case_usage_code Example code + * Add to application C-file: + * \code + * for (;;) + * { + * pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz); + * flash_led(FLASH_TICK_COUNT, 5); + * pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_8_MHz); + * flash_led(FLASH_TICK_COUNT, 5); + * pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_4_MHz); + * flash_led(FLASH_TICK_COUNT, 5); + * pmc_switch_mainck_to_xtal(0); + * flash_led(FLASH_TICK_COUNT, 5); + * } + * \endcode + * + * \subsection pmc_basic_use_case_usage_flow Workflow + * -# Wrap the code in an infinite loop: + * \code + * for (;;) + * \endcode + * -# Switch the Master CPU frequency to the internal 12MHz RC oscillator, flash + * a LED on the board several times: + * \code + * pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz); + * flash_led(FLASH_TICK_COUNT, 5); + * \endcode + * -# Switch the Master CPU frequency to the internal 8MHz RC oscillator, flash + * a LED on the board several times: + * \code + * pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_8_MHz); + * flash_led(FLASH_TICK_COUNT, 5); + * \endcode + * -# Switch the Master CPU frequency to the internal 4MHz RC oscillator, flash + * a LED on the board several times: + * \code + * pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_4_MHz); + * flash_led(FLASH_TICK_COUNT, 5); + * \endcode + * -# Switch the Master CPU frequency to the external crystal oscillator, flash + * a LED on the board several times: + * \code + * pmc_switch_mainck_to_xtal(0); + * flash_led(FLASH_TICK_COUNT, 5); + * \endcode + */ + +/** + * \page pmc_use_case_2 Use case #2 - Configure Programmable Clocks + * In this use case, the PMC module is configured to start the Slow Clock from + * an attached 32KHz crystal, and start one of the Programmable Clock modules + * sourced from the Slow Clock divided down with a prescale factor of 64. + * + * \section pmc_use_case_2_setup Setup + * + * \subsection pmc_use_case_2_setup_prereq Prerequisites + * -# \ref pio_group "Parallel Input/Output Controller (pio)" + * + * \subsection pmc_use_case_2_setup_code Code + * The following code must be added to the user application: + * \code + * pio_set_peripheral(PIOA, PIO_PERIPH_B, PIO_PA17); + * \endcode + * + * \subsection pmc_use_case_2_setup_code_workflow Workflow + * -# Configure the PCK1 pin to output on a specific port pin (in this case, + * PIOA pin 17) of the microcontroller. + * \code + * pio_set_peripheral(PIOA, PIO_PERIPH_B, PIO_PA17); + * \endcode + * \note The peripheral selection and pin will vary according to your selected + * SAM device model. Refer to the "Peripheral Signal Multiplexing on I/O + * Lines" of your device's datasheet. + * + * \section pmc_use_case_2_usage Use case + * The generated PCK1 clock output can be viewed on an oscilloscope attached to + * the correct pin of the microcontroller. + * + * \subsection pmc_use_case_2_usage_code Example code + * Add to application C-file: + * \code + * pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL); + * pmc_switch_pck_to_sclk(PMC_PCK_1, PMC_PCK_PRES_CLK_64); + * pmc_enable_pck(PMC_PCK_1); + * + * for (;;) + * { + * // Do Nothing + * } + * \endcode + * + * \subsection pmc_use_case_2_usage_flow Workflow + * -# Switch the Slow Clock source input to an external 32KHz crystal: + * \code + * pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL); + * \endcode + * -# Switch the Programmable Clock module PCK1 source clock to the Slow Clock, + * with a prescaler of 64: + * \code + * pmc_switch_pck_to_sclk(PMC_PCK_1, PMC_PCK_PRES_CLK_64); + * \endcode + * -# Enable Programmable Clock module PCK1: + * \code + * pmc_enable_pck(PMC_PCK_1); + * \endcode + * -# Enter an infinite loop: + * \code + * for (;;) + * { + * // Do Nothing + * } + * \endcode + */ + +#endif /* PMC_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/libsam/source/pmc.c b/hardware/arduino/sam/system/libsam/source/pmc.c index 77839b7a9..93e9d8f33 100644 --- a/hardware/arduino/sam/system/libsam/source/pmc.c +++ b/hardware/arduino/sam/system/libsam/source/pmc.c @@ -1,7 +1,7 @@ /* ---------------------------------------------------------------------------- - * SAM Software Package License + * SAM Software Package License * ---------------------------------------------------------------------------- - * Copyright (c) 2011, Atmel Corporation + * Copyright (c) 2012, Atmel Corporation * * All rights reserved. * @@ -27,157 +27,1021 @@ * ---------------------------------------------------------------------------- */ -/*---------------------------------------------------------------------------- - * Headers - *----------------------------------------------------------------------------*/ #include "chip.h" -//#include +#if (SAM3N_SERIES) +# define MAX_PERIPH_ID 31 +#elif (SAM3XA_SERIES) +# define MAX_PERIPH_ID 44 +#elif (SAM3U_SERIES) +# define MAX_PERIPH_ID 29 +#elif (SAM3S_SERIES || SAM4S_SERIES) +# define MAX_PERIPH_ID 34 +#endif -/*---------------------------------------------------------------------------- - * Local definitions - *----------------------------------------------------------------------------*/ - -#define MASK_STATUS0 0xFFFFFFFC -#define MASK_STATUS1 0xFFFFFFFF - -/*---------------------------------------------------------------------------- - * Exported functions - *----------------------------------------------------------------------------*/ +/// @cond 0 +/**INDENT-OFF**/ +#ifdef __cplusplus +extern "C" { +#endif +/**INDENT-ON**/ +/// @endcond /** - * \brief Enables the clock of a peripheral. The peripheral ID is used - * to identify which peripheral is targetted. + * \defgroup sam_drivers_pmc_group Power Management Controller (PMC) * - * \note The ID must NOT be shifted (i.e. 1 << ID_xxx). + * \par Purpose * - * \param id Peripheral ID (ID_xxx). + * The Power Management Controller (PMC) optimizes power consumption by controlling + * all system and user peripheral clocks. The PMC enables/disables the clock inputs + * to many of the peripherals and the Cortex-M Processor. + * + * @{ */ -extern void PMC_EnablePeripheral( uint32_t dwId ) -{ -#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3XA_) - //assert( dwId < 35 ) ; - if ( dwId < 32 ) - { - if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) ) - { -// TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %u is already enabled\n\r", dwId ) ; - } - else - { - PMC->PMC_PCER0 = 1 << dwId ; - } - } - else - { - dwId -= 32; - if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId)) - { -// TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %u is already enabled\n\r", dwId + 32 ) ; - } - else - { - PMC->PMC_PCER1 = 1 << dwId ; - } - } -#elif (defined _SAM3N_) || (defined _SAM3U_) - if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) ) - { - PMC->PMC_PCER0 = 1 << dwId ; - } -#else - #error "The specified chip is not supported." +/** + * \brief Set the prescaler of the MCK. + * + * \param ul_pres Prescaler value. + */ +void pmc_mck_set_prescaler(uint32_t ul_pres) +{ + PMC->PMC_MCKR = + (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres; + while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); +} + +/** + * \brief Set the source of the MCK. + * + * \param ul_source Source selection value. + */ +void pmc_mck_set_source(uint32_t ul_source) +{ + PMC->PMC_MCKR = + (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | ul_source; + while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); +} + +/** + * \brief Switch master clock source selection to slow clock. + * + * \param ul_pres Processor clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS_SLOW_CLK; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} + +/** + * \brief Switch master clock source selection to main clock. + * + * \param ul_pres Processor clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | + PMC_MCKR_CSS_MAIN_CLK; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} + +/** + * \brief Switch master clock source selection to PLLA clock. + * + * \param ul_pres Processor clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | + PMC_MCKR_CSS_PLLA_CLK; + + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} + +#if (SAM3S_SERIES || SAM4S_SERIES) +/** + * \brief Switch master clock source selection to PLLB clock. + * + * \param ul_pres Processor clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | + PMC_MCKR_CSS_PLLB_CLK; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} +#endif + +#if (SAM3XA_SERIES || SAM3U_SERIES) +/** + * \brief Switch master clock source selection to UPLL clock. + * + * \param ul_pres Processor clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | + PMC_MCKR_CSS_UPLL_CLK; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} +#endif + +/** + * \brief Switch slow clock source selection to external 32k (Xtal or Bypass). + * + * \note This function disables the PLLs. + * + * \note Switching SCLK back to 32krc is only possible by shutting down the VDDIO + * power supply. + * + * \param ul_bypass 0 for Xtal, 1 for bypass. + */ +void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass) +{ + /* Set Bypass mode if required */ + if (ul_bypass == 1) { + SUPC->SUPC_MR |= SUPC_MR_KEY(SUPC_KEY_VALUE) | + SUPC_MR_OSCBYPASS; + } + + SUPC->SUPC_CR |= SUPC_CR_KEY(SUPC_KEY_VALUE) | SUPC_CR_XTALSEL; +} + +/** + * \brief Check if the external 32k Xtal is ready. + * + * \retval 1 External 32k Xtal is ready. + * \retval 0 External 32k Xtal is not ready. + */ +uint32_t pmc_osc_is_ready_32kxtal(void) +{ + return ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) + && (PMC->PMC_SR & PMC_SR_OSCSELS)); +} + +/** + * \brief Switch main clock source selection to internal fast RC. + * + * \param ul_moscrcf Fast RC oscillator(4/8/12Mhz). + * + * \retval 0 Success. + * \retval 1 Timeout error. + * \retval 2 Invalid frequency. + */ +void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf) +{ + uint32_t ul_needXTEN = 0; + + /* Enable Fast RC oscillator but DO NOT switch to RC now */ + if (PMC->CKGR_MOR & CKGR_MOR_MOSCXTEN) { + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) | + PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCRCEN | + ul_moscrcf; + } else { + ul_needXTEN = 1; + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) | + PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCRCEN | + CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCXTST(PMC_XTAL_STARTUP_TIME) | + ul_moscrcf; + } + + /* Wait the Fast RC to stabilize */ + while (!(PMC->PMC_SR & PMC_SR_MOSCRCS)); + + /* Switch to Fast RC */ + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | PMC_CKGR_MOR_KEY_VALUE; + + // BUG FIX : clock_example3_SAM3S_SERIES does not switch sclk->mainck with XT disabled. + if (ul_needXTEN) { + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) | + PMC_CKGR_MOR_KEY_VALUE; + } +} + +/** + * \brief Enable fast RC oscillator. + * + * \param ul_rc Fast RC oscillator(4/8/12Mhz). + */ +void pmc_osc_enable_fastrc(uint32_t ul_rc) +{ + /* Enable Fast RC oscillator but DO NOT switch to RC now. Keep MOSCSEL to 1 */ + PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCSEL | + CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCRCEN | ul_rc; + /* Wait the Fast RC to stabilize */ + while (!(PMC->PMC_SR & PMC_SR_MOSCRCS)); +} + +/** + * \brief Disable the internal fast RC. + */ +void pmc_osc_disable_fastrc(void) +{ + /* Disable Fast RC oscillator */ + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN) | PMC_CKGR_MOR_KEY_VALUE; +} + +/** + * \brief Switch main clock source selection to external Xtal/Bypass. + * The function may switch MCK to SCLK if MCK source is MAINCK to avoid any + * system crash. + * + * \note If used in Xtal mode, the Xtal is automatically enabled. + * + * \param ul_bypass 0 for Xtal, 1 for bypass. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +void pmc_switch_mainck_to_xtal(uint32_t ul_bypass) +{ + /* Enable Main Xtal oscillator */ + if (ul_bypass) { + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) | + PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTBY | + CKGR_MOR_MOSCSEL; + } else { + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) | + PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTEN | + CKGR_MOR_MOSCXTST(PMC_XTAL_STARTUP_TIME); + /* Wait the Xtal to stabilize */ + while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)); + + PMC->CKGR_MOR |= PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCSEL; + } +} + +/** + * \brief Disable the external Xtal. + * + * \param ul_bypass 0 for Xtal, 1 for bypass. + */ +void pmc_osc_disable_xtal(uint32_t ul_bypass) +{ + /* Disable xtal oscillator */ + if (ul_bypass) { + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) | + PMC_CKGR_MOR_KEY_VALUE; + } else { + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) | + PMC_CKGR_MOR_KEY_VALUE; + } +} + +/** + * \brief Check if the MAINCK is ready. Depending on MOSCEL, MAINCK can be one + * of Xtal, bypass or internal RC. + * + * \retval 1 Xtal is ready. + * \retval 0 Xtal is not ready. + */ +uint32_t pmc_osc_is_ready_mainck(void) +{ + return PMC->PMC_SR & PMC_SR_MOSCSELS; +} + +/** + * \brief Enable PLLA clock. + * + * \param mula PLLA multiplier. + * \param pllacount PLLA counter. + * \param diva Divider. + */ +void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva) +{ + pmc_disable_pllack(); // Hardware BUG FIX : first disable the PLL to unlock the lock! + // It occurs when re-enabling the PLL with the same parameters. + + PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_DIVA(diva) | + CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula); + while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0); +} + +/** + * \brief Disable PLLA clock. + */ +void pmc_disable_pllack(void) +{ + PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0); +} + +/** + * \brief Is PLLA locked? + * + * \retval 0 Not locked. + * \retval 1 Locked. + */ +uint32_t pmc_is_locked_pllack(void) +{ + return (PMC->PMC_SR & PMC_SR_LOCKA); +} + +#if (SAM3S_SERIES || SAM4S_SERIES) +/** + * \brief Enable PLLB clock. + * + * \param mulb PLLB multiplier. + * \param pllbcount PLLB counter. + * \param divb Divider. + */ +void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb) +{ + pmc_disable_pllbck(); // Hardware BUG FIX : first disable the PLL to unlock the lock! + // It occurs when re-enabling the PLL with the same parameters. + PMC->CKGR_PLLBR = + CKGR_PLLBR_DIVB(divb) | CKGR_PLLBR_PLLBCOUNT(pllbcount) + | CKGR_PLLBR_MULB(mulb); + while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0); +} + +/** + * \brief Disable PLLB clock. + */ +void pmc_disable_pllbck(void) +{ + PMC->CKGR_PLLBR = CKGR_PLLBR_MULB(0); +} + +/** + * \brief Is PLLB locked? + * + * \retval 0 Not locked. + * \retval 1 Locked. + */ +uint32_t pmc_is_locked_pllbck(void) +{ + return (PMC->PMC_SR & PMC_SR_LOCKB); +} +#endif + +#if (SAM3XA_SERIES || SAM3U_SERIES) +/** + * \brief Enable UPLL clock. + */ +void pmc_enable_upll_clock(void) +{ + PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(3) | CKGR_UCKR_UPLLEN; + + /* Wait UTMI PLL Lock Status */ + while (!(PMC->PMC_SR & PMC_SR_LOCKU)); +} + +/** + * \brief Disable UPLL clock. + */ +void pmc_disable_upll_clock(void) +{ + PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN; +} + +/** + * \brief Is UPLL locked? + * + * \retval 0 Not locked. + * \retval 1 Locked. + */ +uint32_t pmc_is_locked_upll(void) +{ + return (PMC->PMC_SR & PMC_SR_LOCKU); +} +#endif + +/** + * \brief Enable the specified peripheral clock. + * + * \note The ID must NOT be shifted (i.e., 1 << ID_xxx). + * + * \param ul_id Peripheral ID (ID_xxx). + * + * \retval 0 Success. + * \retval 1 Invalid parameter. + */ +uint32_t pmc_enable_periph_clk(uint32_t ul_id) +{ + if (ul_id > MAX_PERIPH_ID) { + return 1; + } + + if (ul_id < 32) { + if ((PMC->PMC_PCSR0 & (1u << ul_id)) != (1u << ul_id)) { + PMC->PMC_PCER0 = 1 << ul_id; + } +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) + } else { + ul_id -= 32; + if ((PMC->PMC_PCSR1 & (1u << ul_id)) != (1u << ul_id)) { + PMC->PMC_PCER1 = 1 << ul_id; + } +#endif + } + + return 0; +} + +/** + * \brief Disable the specified peripheral clock. + * + * \note The ID must NOT be shifted (i.e., 1 << ID_xxx). + * + * \param ul_id Peripheral ID (ID_xxx). + * + * \retval 0 Success. + * \retval 1 Invalid parameter. + */ +uint32_t pmc_disable_periph_clk(uint32_t ul_id) +{ + if (ul_id > MAX_PERIPH_ID) { + return 1; + } + + if (ul_id < 32) { + if ((PMC->PMC_PCSR0 & (1u << ul_id)) == (1u << ul_id)) { + PMC->PMC_PCDR0 = 1 << ul_id; + } +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) + } else { + ul_id -= 32; + if ((PMC->PMC_PCSR1 & (1u << ul_id)) == (1u << ul_id)) { + PMC->PMC_PCDR1 = 1 << ul_id; + } +#endif + } + return 0; +} + +/** + * \brief Enable all peripheral clocks. + */ +void pmc_enable_all_periph_clk(void) +{ + PMC->PMC_PCER0 = PMC_MASK_STATUS0; + while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != PMC_MASK_STATUS0); + +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) + PMC->PMC_PCER1 = PMC_MASK_STATUS1; + while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != PMC_MASK_STATUS1); #endif } /** - * \brief Disables the clock of a peripheral. The peripheral ID is used - * to identify which peripheral is targetted. - * - * \note The ID must NOT be shifted (i.e. 1 << ID_xxx). - * - * \param id Peripheral ID (ID_xxx). + * \brief Disable all peripheral clocks. */ -extern void PMC_DisablePeripheral( uint32_t dwId ) +void pmc_disable_all_periph_clk(void) { -#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3XA_) - //assert( dwId < 35 ) ; + PMC->PMC_PCDR0 = PMC_MASK_STATUS0; + while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != 0); - if ( dwId < 32 ) - { - if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) ) - { - PMC->PMC_PCDR0 = 1 << dwId ; - } - } - else - { - dwId -= 32 ; - if ( (PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) ) - { - PMC->PMC_PCDR1 = 1 << dwId ; - } - } -#elif (defined _SAM3N_) || (defined _SAM3U_) - if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) ) - { - PMC->PMC_PCDR0 = 1 << dwId ; - } -#else - #error "The specified chip is not supported." +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) + PMC->PMC_PCDR1 = PMC_MASK_STATUS1; + while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != 0); #endif } /** - * \brief Get the status of the specified peripheral clock. + * \brief Check if the specified peripheral clock is enabled. * - * \note The ID must NOT be shifted (i.e. 1 << ID_xxx). + * \note The ID must NOT be shifted (i.e., 1 << ID_xxx). * - * \param dwId Peripheral ID (ID_xxx). + * \param ul_id Peripheral ID (ID_xxx). * - * \retval 0 Clock is active. - * \retval 1 Clock is inactive. - * \retval 2 Invalid parameter. + * \retval 0 Peripheral clock is disabled or unknown. + * \retval 1 Peripheral clock is enabled. */ -extern uint32_t PMC_IsPeripheralEnabled( uint32_t dwId ) +uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id) { -#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3XA_) - //assert( dwId < 35 ) ; + if (ul_id > MAX_PERIPH_ID) { + return 0; + } - if ( dwId < 32 ) - { - if ( PMC->PMC_PCSR0 & (1 << dwId) ) - { - return 0 ; - } - else - { - return 1 ; - } - } - else - { - if ( PMC->PMC_PCSR1 & (1 << (dwId - 32)) ) - { - return 0 ; - } - else - { - return 1 ; - } - } -#elif (defined _SAM3N_) || (defined _SAM3U_) - if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) ) - { - return 0 ; - } - else - { - return 1 ; - } -#else - #error "The specified chip is not supported." +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) + if (ul_id < 32) { +#endif + if ((PMC->PMC_PCSR0 & (1u << ul_id))) { + return 1; + } else { + return 0; + } +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) + } else { + ul_id -= 32; + if ((PMC->PMC_PCSR1 & (1u << ul_id))) { + return 1; + } else { + return 0; + } + } #endif } + +/** + * \brief Set the prescaler for the specified programmable clock. + * + * \param ul_id Peripheral ID. + * \param ul_pres Prescaler value. + */ +void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres) +{ + PMC->PMC_PCK[ul_id] = + (PMC->PMC_PCK[ul_id] & ~PMC_PCK_PRES_Msk) | ul_pres; + while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id)) + && !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id))); +} + +/** + * \brief Set the source oscillator for the specified programmable clock. + * + * \param ul_id Peripheral ID. + * \param ul_source Source selection value. + */ +void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source) +{ + PMC->PMC_PCK[ul_id] = + (PMC->PMC_PCK[ul_id] & ~PMC_PCK_CSS_Msk) | ul_source; + while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id)) + && !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id))); +} + +/** + * \brief Switch programmable clock source selection to slow clock. + * + * \param ul_id Id of the programmable clock. + * \param ul_pres Programmable clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_SLOW_CLK | ul_pres; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} + +/** + * \brief Switch programmable clock source selection to main clock. + * + * \param ul_id Id of the programmable clock. + * \param ul_pres Programmable clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_MAIN_CLK | ul_pres; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} + +/** + * \brief Switch programmable clock source selection to PLLA clock. + * + * \param ul_id Id of the programmable clock. + * \param ul_pres Programmable clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLA_CLK | ul_pres; + for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} + +#if (SAM3S_SERIES || SAM4S_SERIES) +/** + * \brief Switch programmable clock source selection to PLLB clock. + * + * \param ul_id Id of the programmable clock. + * \param ul_pres Programmable clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLB_CLK | ul_pres; + for (ul_timeout = PMC_TIMEOUT; + !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} +#endif + +#if (SAM3XA_SERIES || SAM3U_SERIES) +/** + * \brief Switch programmable clock source selection to UPLL clock. + * + * \param ul_id Id of the programmable clock. + * \param ul_pres Programmable clock prescaler. + * + * \retval 0 Success. + * \retval 1 Timeout error. + */ +uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres) +{ + uint32_t ul_timeout; + + PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_UPLL_CLK | ul_pres; + for (ul_timeout = PMC_TIMEOUT; + !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); + --ul_timeout) { + if (ul_timeout == 0) { + return 1; + } + } + + return 0; +} +#endif + +/** + * \brief Enable the specified programmable clock. + * + * \param ul_id Id of the programmable clock. + */ +void pmc_enable_pck(uint32_t ul_id) +{ + PMC->PMC_SCER = PMC_SCER_PCK0 << ul_id; +} + +/** + * \brief Disable the specified programmable clock. + * + * \param ul_id Id of the programmable clock. + */ +void pmc_disable_pck(uint32_t ul_id) +{ + PMC->PMC_SCDR = PMC_SCER_PCK0 << ul_id; +} + +/** + * \brief Enable all programmable clocks. + */ +void pmc_enable_all_pck(void) +{ + PMC->PMC_SCER = PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2; +} + +/** + * \brief Disable all programmable clocks. + */ +void pmc_disable_all_pck(void) +{ + PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2; +} + +/** + * \brief Check if the specified programmable clock is enabled. + * + * \param ul_id Id of the programmable clock. + * + * \retval 0 Programmable clock is disabled or unknown. + * \retval 1 Programmable clock is enabled. + */ +uint32_t pmc_is_pck_enabled(uint32_t ul_id) +{ + if (ul_id > 2) { + return 0; + } + + return (PMC->PMC_SCSR & (PMC_SCSR_PCK0 << ul_id)); +} + +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) +/** + * \brief Switch UDP (USB) clock source selection to PLLA clock. + * + * \param ul_usbdiv Clock divisor. + */ +void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv) +{ + PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv); +} +#endif + +#if (SAM3S_SERIES || SAM4S_SERIES) +/** + * \brief Switch UDP (USB) clock source selection to PLLB clock. + * + * \param ul_usbdiv Clock divisor. + */ +void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv) +{ + PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv) | PMC_USB_USBS; +} +#endif + +#if (SAM3XA_SERIES) +/** + * \brief Switch UDP (USB) clock source selection to UPLL clock. + * + * \param dw_usbdiv Clock divisor. + */ +void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv) +{ + PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(ul_usbdiv); +} +#endif + +#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES) +/** + * \brief Enable UDP (USB) clock. + */ +void pmc_enable_udpck(void) +{ +# if (SAM3S_SERIES || SAM4S_SERIES) + PMC->PMC_SCER = PMC_SCER_UDP; +# else + PMC->PMC_SCER = PMC_SCER_UOTGCLK; +# endif +} + +/** + * \brief Disable UDP (USB) clock. + */ +void pmc_disable_udpck(void) +{ +# if (SAM3S_SERIES || SAM4S_SERIES) + PMC->PMC_SCDR = PMC_SCDR_UDP; +# else + PMC->PMC_SCDR = PMC_SCDR_UOTGCLK; +# endif +} +#endif + +/** + * \brief Enable PMC interrupts. + * + * \param ul_sources Interrupt sources bit map. + */ +void pmc_enable_interrupt(uint32_t ul_sources) +{ + PMC->PMC_IER = ul_sources; +} + +/** + * \brief Disable PMC interrupts. + * + * \param ul_sources Interrupt sources bit map. + */ +void pmc_disable_interrupt(uint32_t ul_sources) +{ + PMC->PMC_IDR = ul_sources; +} + +/** + * \brief Get PMC interrupt mask. + * + * \return The interrupt mask value. + */ +uint32_t pmc_get_interrupt_mask(void) +{ + return PMC->PMC_IMR; +} + +/** + * \brief Get current status. + * + * \return The current PMC status. + */ +uint32_t pmc_get_status(void) +{ + return PMC->PMC_SR; +} + +/** + * \brief Set the wake-up inputs for fast startup mode registers (event generation). + * + * \param ul_inputs Wake up inputs to enable. + */ +void pmc_set_fast_startup_input(uint32_t ul_inputs) +{ + ul_inputs &= (~ PMC_FAST_STARTUP_Msk); + PMC->PMC_FSMR |= ul_inputs; +} + +/** + * \brief Clear the wake-up inputs for fast startup mode registers (remove event generation). + * + * \param ul_inputs Wake up inputs to disable. + */ +void pmc_clr_fast_startup_input(uint32_t ul_inputs) +{ + ul_inputs &= (~ PMC_FAST_STARTUP_Msk); + PMC->PMC_FSMR &= ~ul_inputs; +} + +/** + * \brief Enable Sleep Mode. + * Enter condition: (WFE or WFI) + (SLEEPDEEP bit = 0) + (LPM bit = 0) + * + * \param uc_type 0 for wait for interrupt, 1 for wait for event. + */ +void pmc_enable_sleepmode(uint8_t uc_type) +{ + PMC->PMC_FSMR &= (uint32_t) ~ PMC_FSMR_LPM; // Enter Sleep mode + SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep + + if (uc_type == 0) { + __WFI(); + } else { + __WFE(); + } +} + +/** + * \brief Enable Wait Mode. + * Enter condition: WFE + (SLEEPDEEP bit = 0) + (LPM bit = 1) + */ +void pmc_enable_waitmode(void) +{ + uint32_t i; + + PMC->PMC_FSMR |= PMC_FSMR_LPM; // Enter Wait mode + SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep + __WFE(); + + /* Waiting for MOSCRCEN bit cleared is strongly recommended + * to ensure that the core will not execute undesired instructions + */ + for (i = 0; i < 500; i++) { + __NOP(); + } + while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN)); +} + +/** + * \brief Enable Backup Mode. + * Enter condition: WFE + (SLEEPDEEP bit = 1) + */ +void pmc_enable_backupmode(void) +{ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + __WFE(); +} + +/** + * \brief Enable or disable write protect of PMC registers. + * + * \param ul_enable 1 to enable, 0 to disable. + */ +void pmc_set_writeprotect(uint32_t ul_enable) +{ + if (ul_enable) { + PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE | PMC_WPMR_WPEN; + } else { + PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE; + } +} + +/** + * \brief Return write protect status. + * + * \retval 0 Protection disabled. + * \retval 1 Protection enabled. + */ +uint32_t pmc_get_writeprotect_status(void) +{ + return PMC->PMC_WPMR & PMC_WPMR_WPEN; +} + +/// @cond 0 +/**INDENT-OFF**/ +#ifdef __cplusplus +} +#endif +/**INDENT-ON**/ +/// @endcond diff --git a/hardware/arduino/sam/system/libsam/source/spi.c b/hardware/arduino/sam/system/libsam/source/spi.c index 058f2cd9b..acda7d9f9 100644 --- a/hardware/arduino/sam/system/libsam/source/spi.c +++ b/hardware/arduino/sam/system/libsam/source/spi.c @@ -1,5 +1,5 @@ /* ---------------------------------------------------------------------------- - * SAM Software Package License + * SAM Software Package License * ---------------------------------------------------------------------------- * Copyright (c) 2011, Atmel Corporation * @@ -128,7 +128,7 @@ extern void SPI_DisableIt( Spi* spi, uint32_t dwSources ) */ extern void SPI_Configure( Spi* spi, uint32_t dwId, uint32_t dwConfiguration ) { - PMC_EnablePeripheral( dwId ) ; + pmc_enable_periph_clk( dwId ) ; spi->SPI_CR = SPI_CR_SPIDIS ; /* Execute a software reset of the SPI twice */ diff --git a/hardware/arduino/sam/system/libsam/source/timetick.c b/hardware/arduino/sam/system/libsam/source/timetick.c index 8522e20a1..99ab5c9e1 100644 --- a/hardware/arduino/sam/system/libsam/source/timetick.c +++ b/hardware/arduino/sam/system/libsam/source/timetick.c @@ -1,5 +1,5 @@ /* ---------------------------------------------------------------------------- - * SAM Software Package License + * SAM Software Package License * ---------------------------------------------------------------------------- * Copyright (c) 2011, Atmel Corporation * diff --git a/hardware/arduino/sam/system/libsam/source/udp.c b/hardware/arduino/sam/system/libsam/source/udp.c index 590e8f6f7..47515aa57 100644 --- a/hardware/arduino/sam/system/libsam/source/udp.c +++ b/hardware/arduino/sam/system/libsam/source/udp.c @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -20,7 +20,7 @@ #if SAM3S_SERIES || SAM4S_SERIES -#include "USB_driver.h" +#include "USB_device.h" #include "udp.h" diff --git a/hardware/arduino/sam/system/libsam/source/udphs.c b/hardware/arduino/sam/system/libsam/source/udphs.c index 2e0036708..40267a229 100644 --- a/hardware/arduino/sam/system/libsam/source/udphs.c +++ b/hardware/arduino/sam/system/libsam/source/udphs.c @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -20,7 +20,7 @@ #if 0 //SAM3U_SERIES -#include "USB_driver.h" +#include "USB_device.h" #include "udphs.h" /// Max size of the FMA FIFO @@ -51,7 +51,7 @@ void USBD_WaitOUT(void) void USBD_ClearIN(void) { // UEINTX = ~(1<UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TX_COMPLT; + UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TX_COMPLT; } void USBD_ClearOUT(void) @@ -243,7 +243,7 @@ uint8_t USBD_SendSpace(uint8_t ep) { return 0; } - + return 64 - FifoByteCount(); } @@ -251,7 +251,7 @@ uint8_t USBD_SendSpace(uint8_t ep) uint8_t USBD_Available(uint8_t ep) { SetEP(ep); - + return FifoByteCount(); } @@ -290,11 +290,11 @@ void USBD_InitControl(int end) { SetEP(0); UDPHS->UDPHS_EPT[0].UDPHS_EPTCFG = _initEndpoints[0]; - + while( (signed int)UDPHS_EPTCFG_EPT_MAPD != (signed int)((UDPHS->UDPHS_EPT[0].UDPHS_EPTCFG) & (unsigned int)UDPHS_EPTCFG_EPT_MAPD) ) ; - - UDPHS->UDPHS_EPT[0].UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_RX_BK_RDY + + UDPHS->UDPHS_EPT[0].UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_RX_BK_RDY | UDPHS_EPTCTLENB_RX_SETUP | UDPHS_EPTCTLENB_EPT_ENABL; diff --git a/hardware/arduino/sam/variants/arduino_due_x/variant.cpp b/hardware/arduino/sam/variants/arduino_due_x/variant.cpp index ae8634e8d..fbc0f4f0f 100644 --- a/hardware/arduino/sam/variants/arduino_due_x/variant.cpp +++ b/hardware/arduino/sam/variants/arduino_due_x/variant.cpp @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -103,6 +103,12 @@ * #CS SS3 | PB23 * * + * USB pin | PORT + * ----------------+-------- + * ID | PB11 + * VBOF | PB10 + * + * * LEDs | PORT * ----------------+-------- * "TX" | PA21 @@ -263,6 +269,9 @@ extern const PinDescription g_APinDescription[]= // 84 - USART3 (Serial4) all pins { PIOD, PIO_PD4B_TXD3|PIO_PD5B_RXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NO_PWM, NO_TC }, + // 85 - USB + { PIOB, PIO_PB11A_UOTGID|PIO_PB10A_UOTGVBOF, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NO_PWM, NO_TC }, // ID - VBOF + // END { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NO_PWM, NO_TC } } ; @@ -355,8 +364,15 @@ extern void init( void ) g_APinDescription[PINS_USART2].ulPin, g_APinDescription[PINS_USART2].ulPinConfiguration); + // Initialize USB + PIO_Configure( + g_APinDescription[PINS_USB].pPort, + g_APinDescription[PINS_USB].ulPinType, + g_APinDescription[PINS_USB].ulPin, + g_APinDescription[PINS_USB].ulPinConfiguration); + // Initialize 10bit Analog Controller - PMC_EnablePeripheral( ID_ADC ) ; + pmc_enable_periph_clk( ID_ADC ) ; adc_init( ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST ) ; adc_configure_timing(ADC, 0, ADC_SETTLING_TIME_3, 1); adc_configure_trigger(ADC, ADC_TRIG_SW, 0); // Disable hardware trigger. diff --git a/hardware/arduino/sam/variants/arduino_due_x/variant.h b/hardware/arduino/sam/variants/arduino_due_x/variant.h index d59ba5136..ee26eda29 100644 --- a/hardware/arduino/sam/variants/arduino_due_x/variant.h +++ b/hardware/arduino/sam/variants/arduino_due_x/variant.h @@ -8,7 +8,7 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public @@ -125,6 +125,11 @@ static const uint8_t SCK = PIN_SPI_SCK ; #define PINS_USART1 (83u) #define PINS_USART2 (84u) +/* + * USB Interfaces + */ +#define PINS_USB (85u) + /* * Analog pins */