From ee8110e7312effe55f1d5ddaf5bed05c3392976b Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 17 Jul 2013 14:36:20 +0200 Subject: [PATCH 01/16] Updated StringReplacer.quotedSplit() to accept more than one quote char. --- .../app/helpers/StringReplacer.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/app/src/processing/app/helpers/StringReplacer.java b/app/src/processing/app/helpers/StringReplacer.java index c6b02a23b..2ab42896a 100644 --- a/app/src/processing/app/helpers/StringReplacer.java +++ b/app/src/processing/app/helpers/StringReplacer.java @@ -34,7 +34,7 @@ public class StringReplacer { String res; // Recursive replace with a max depth of 10 levels. - for (int i=0; i<10; i++) { + for (int i = 0; i < 10; i++) { // Do a replace with dictionary res = StringReplacer.replaceFromMapping(src, dict); if (!recursive) @@ -45,30 +45,31 @@ public class StringReplacer { } // Split the resulting string in arguments - return quotedSplit(src, '"', false); + return quotedSplit(src, "\"'", false); } - public static String[] quotedSplit(String src, char escapeChar, + public static String[] quotedSplit(String src, String quoteChars, boolean acceptEmptyArguments) throws Exception { - String quote = "" + escapeChar; List res = new ArrayList(); String escapedArg = null; - boolean escaping = false; + String escapingChar = null; for (String i : src.split(" ")) { - if (!escaping) { - if (!i.startsWith(quote)) { + if (escapingChar == null) { + // If the first char is not an escape char.. + String first = i.substring(0, 1); + if (!quoteChars.contains(first)) { if (i.trim().length() != 0 || acceptEmptyArguments) res.add(i); continue; } - escaping = true; + escapingChar = first; i = i.substring(1); escapedArg = ""; } - if (!i.endsWith(quote)) { + if (!i.endsWith(escapingChar)) { escapedArg += i + " "; continue; } @@ -76,11 +77,11 @@ public class StringReplacer { escapedArg += i.substring(0, i.length() - 1); if (escapedArg.trim().length() != 0 || acceptEmptyArguments) res.add(escapedArg); - escaping = false; + escapingChar = null; } - if (escaping) - throw new Exception("Invalid quoting: no closing '" + escapeChar + - "' char found."); + if (escapingChar != null) + throw new Exception("Invalid quoting: no closing [" + escapingChar + + "] char found."); return res.toArray(new String[0]); } From 15e73e8daac8b358bb3bdb962ae3971b56f215e1 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 17 May 2013 14:34:06 +1000 Subject: [PATCH 02/16] Allow USB product and manufacturer strings to be supplied in boards.txt --- hardware/arduino/avr/boards.txt | 13 ++-- .../arduino/avr/cores/arduino/USBCore.cpp | 72 ++++++++++++------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/hardware/arduino/avr/boards.txt b/hardware/arduino/avr/boards.txt index 893e8804d..1ec00c0e2 100644 --- a/hardware/arduino/avr/boards.txt +++ b/hardware/arduino/avr/boards.txt @@ -188,10 +188,11 @@ leonardo.build.mcu=atmega32u4 leonardo.build.f_cpu=16000000L leonardo.build.vid=0x2341 leonardo.build.pid=0x8036 +leonardo.build.usb_product="Arduino Leonardo" leonardo.build.board=AVR_LEONARDO leonardo.build.core=arduino leonardo.build.variant=leonardo -leonardo.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} +leonardo.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} ############################################################## @@ -217,10 +218,11 @@ micro.build.mcu=atmega32u4 micro.build.f_cpu=16000000L micro.build.vid=0x2341 micro.build.pid=0x8037 +micro.build.usb_product=Arduino Micro micro.build.board=AVR_MICRO micro.build.core=arduino micro.build.variant=micro -micro.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} +micro.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} ############################################################## @@ -246,10 +248,11 @@ esplora.build.mcu=atmega32u4 esplora.build.f_cpu=16000000L esplora.build.vid=0x2341 esplora.build.pid=0x803c +esplora.build.usb_product=Arduino Esplora esplora.build.board=AVR_ESPLORA esplora.build.core=arduino esplora.build.variant=leonardo -esplora.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} +esplora.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} ############################################################## @@ -407,15 +410,15 @@ LilyPadUSB.bootloader.extended_fuses=0xce LilyPadUSB.bootloader.file=caterina-LilyPadUSB/Caterina-LilyPadUSB.hex LilyPadUSB.bootloader.unlock_bits=0x3F LilyPadUSB.bootloader.lock_bits=0x2F - LilyPadUSB.build.mcu=atmega32u4 LilyPadUSB.build.f_cpu=8000000L LilyPadUSB.build.vid=0x1B4F LilyPadUSB.build.pid=0x9208 +LilyPadUSB.build.usb_product=LilyPad USB LilyPadUSB.build.board=AVR_LILYPAD_USB LilyPadUSB.build.core=arduino LilyPadUSB.build.variant=leonardo -LilyPadUSB.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} +LilyPadUSB.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} ############################################################## diff --git a/hardware/arduino/avr/cores/arduino/USBCore.cpp b/hardware/arduino/avr/cores/arduino/USBCore.cpp index d3e017065..680cba7c5 100644 --- a/hardware/arduino/avr/cores/arduino/USBCore.cpp +++ b/hardware/arduino/avr/cores/arduino/USBCore.cpp @@ -39,8 +39,8 @@ volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ //================================================================== extern const u16 STRING_LANGUAGE[] PROGMEM; -extern const u16 STRING_IPRODUCT[] PROGMEM; -extern const u16 STRING_IMANUFACTURER[] PROGMEM; +extern const u8 STRING_PRODUCT[] PROGMEM; +extern const u8 STRING_MANUFACTURER[] PROGMEM; extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; @@ -49,31 +49,34 @@ const u16 STRING_LANGUAGE[2] = { 0x0409 // English }; -const u16 STRING_IPRODUCT[17] = { - (3<<8) | (2+2*16), -#if USB_PID == 0x8036 - 'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o' +#ifndef USB_PRODUCT +// Use a hardcoded product name if none is provided +#if USB_PID == 0x8036 +#define USB_PRODUCT "Arduino Leonardo" #elif USB_PID == 0x8037 - 'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ',' ',' ' +#define USB_PRODUCT "Arduino Micro" #elif USB_PID == 0x803C - 'A','r','d','u','i','n','o',' ','E','s','p','l','o','r','a',' ' +#define USB_PRODUCT "Arduino Esplora" #elif USB_PID == 0x9208 - 'L','i','l','y','P','a','d','U','S','B',' ',' ',' ',' ',' ',' ' +#define USB_PRODUCT "LilyPad USB" #else - 'U','S','B',' ','I','O',' ','B','o','a','r','d',' ',' ',' ',' ' +#define USB_PRODUCT "USB IO Board" +#endif #endif -}; -const u16 STRING_IMANUFACTURER[12] = { - (3<<8) | (2+2*11), +const u8 STRING_PRODUCT[] PROGMEM = USB_PRODUCT; + #if USB_VID == 0x2341 - 'A','r','d','u','i','n','o',' ','L','L','C' +#define USB_MANUFACTURER "Arduino LLC" #elif USB_VID == 0x1b4f - 'S','p','a','r','k','F','u','n',' ',' ',' ' -#else - 'U','n','k','n','o','w','n',' ',' ',' ',' ' +#define USB_MANUFACTURER "SparkFun" +#elif !defined(USB_MANUFACTURER) +// Fall through to unknown if no manufacturer name was provided in a macro +#define USB_MANUFACTURER "Unknown" #endif -}; + +const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; + #ifdef CDC_ENABLED #define DEVICE_CLASS 0x02 @@ -416,6 +419,22 @@ int USB_SendControl(u8 flags, const void* d, int len) return sent; } +// Send a USB descriptor string. The string is stored in PROGMEM as a +// plain ASCII string but is sent out as UTF-16 with the correct 2-byte +// prefix +static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) { + SendControl(2 + string_len * 2); + SendControl(3); + for(u8 i = 0; i < string_len; i++) { + bool r = SendControl(pgm_read_byte(&string_P[i])); + r &= SendControl(0); // high byte + if(!r) { + return false; + } + } + return true; +} + // Does not timeout or cross fifo boundaries // Will only work for transfers <= 64 bytes // TODO @@ -476,7 +495,6 @@ bool SendDescriptor(Setup& setup) return HID_GetDescriptor(t); #endif - u8 desc_length = 0; const u8* desc_addr = 0; if (USB_DEVICE_DESCRIPTOR_TYPE == t) { @@ -486,20 +504,22 @@ bool SendDescriptor(Setup& setup) } else if (USB_STRING_DESCRIPTOR_TYPE == t) { - if (setup.wValueL == 0) + if (setup.wValueL == 0) { desc_addr = (const u8*)&STRING_LANGUAGE; - else if (setup.wValueL == IPRODUCT) - desc_addr = (const u8*)&STRING_IPRODUCT; - else if (setup.wValueL == IMANUFACTURER) - desc_addr = (const u8*)&STRING_IMANUFACTURER; + } + else if (setup.wValueL == IPRODUCT) { + return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT)); + } + else if (setup.wValueL == IMANUFACTURER) { + return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER)); + } else return false; } if (desc_addr == 0) return false; - if (desc_length == 0) - desc_length = pgm_read_byte(desc_addr); + u8 desc_length = pgm_read_byte(desc_addr); USB_SendControl(TRANSFER_PGM,desc_addr,desc_length); return true; From a7ad83cb73da993d0d5bdc7102eff32861e3cd4c Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 24 Apr 2013 17:49:24 +1000 Subject: [PATCH 03/16] boards.txt: Refactor the default usb build flags into a generic property in platform.txt --- hardware/arduino/avr/boards.txt | 8 ++++---- hardware/arduino/avr/platform.txt | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/hardware/arduino/avr/boards.txt b/hardware/arduino/avr/boards.txt index 1ec00c0e2..8ee45614c 100644 --- a/hardware/arduino/avr/boards.txt +++ b/hardware/arduino/avr/boards.txt @@ -192,7 +192,7 @@ leonardo.build.usb_product="Arduino Leonardo" leonardo.build.board=AVR_LEONARDO leonardo.build.core=arduino leonardo.build.variant=leonardo -leonardo.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} +leonardo.build.extra_flags={build.usb_flags} ############################################################## @@ -222,7 +222,7 @@ micro.build.usb_product=Arduino Micro micro.build.board=AVR_MICRO micro.build.core=arduino micro.build.variant=micro -micro.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} +micro.build.extra_flags={build.usb_flags} ############################################################## @@ -252,7 +252,7 @@ esplora.build.usb_product=Arduino Esplora esplora.build.board=AVR_ESPLORA esplora.build.core=arduino esplora.build.variant=leonardo -esplora.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} +esplora.build.extra_flags={build.usb_flags} ############################################################## @@ -418,7 +418,7 @@ LilyPadUSB.build.usb_product=LilyPad USB LilyPadUSB.build.board=AVR_LILYPAD_USB LilyPadUSB.build.core=arduino LilyPadUSB.build.variant=leonardo -LilyPadUSB.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} +LilyPadUSB.build.extra_flags={build.usb_flags} ############################################################## diff --git a/hardware/arduino/avr/platform.txt b/hardware/arduino/avr/platform.txt index eaf946947..a0e35c3ec 100644 --- a/hardware/arduino/avr/platform.txt +++ b/hardware/arduino/avr/platform.txt @@ -86,3 +86,9 @@ tools.avrdude.bootloader.params.verbose=-v -v -v -v tools.avrdude.bootloader.params.quiet=-q -q tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.ide.path}/hardware/arduino/avr/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m + +# USB Default Flags +# Default blank usb manufacturer will be filled it at compile time +# - from numeric vendor ID, set to Unknown otherwise +build.usb_manufacturer= +build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} From 6abdeecbf592840e08e24532659a39553ab612e8 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 17 May 2013 15:01:15 +1000 Subject: [PATCH 04/16] Fix whitespace (tabify), oops --- hardware/arduino/avr/cores/arduino/USBCore.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/USBCore.cpp b/hardware/arduino/avr/cores/arduino/USBCore.cpp index 680cba7c5..9a50bda8e 100644 --- a/hardware/arduino/avr/cores/arduino/USBCore.cpp +++ b/hardware/arduino/avr/cores/arduino/USBCore.cpp @@ -504,22 +504,22 @@ bool SendDescriptor(Setup& setup) } else if (USB_STRING_DESCRIPTOR_TYPE == t) { - if (setup.wValueL == 0) { + if (setup.wValueL == 0) { desc_addr = (const u8*)&STRING_LANGUAGE; - } + } else if (setup.wValueL == IPRODUCT) { - return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT)); - } + return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT)); + } else if (setup.wValueL == IMANUFACTURER) { - return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER)); - } + return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER)); + } else return false; } if (desc_addr == 0) return false; - u8 desc_length = pgm_read_byte(desc_addr); + u8 desc_length = pgm_read_byte(desc_addr); USB_SendControl(TRANSFER_PGM,desc_addr,desc_length); return true; From 1a99be33a36e0e62e4aec62a179bb13584a4e599 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 17 May 2013 15:02:51 +1000 Subject: [PATCH 05/16] Remove hardcoded product names (all provided for in boards.txt) --- hardware/arduino/avr/cores/arduino/USBCore.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/USBCore.cpp b/hardware/arduino/avr/cores/arduino/USBCore.cpp index 9a50bda8e..c46c75fe9 100644 --- a/hardware/arduino/avr/cores/arduino/USBCore.cpp +++ b/hardware/arduino/avr/cores/arduino/USBCore.cpp @@ -50,19 +50,9 @@ const u16 STRING_LANGUAGE[2] = { }; #ifndef USB_PRODUCT -// Use a hardcoded product name if none is provided -#if USB_PID == 0x8036 -#define USB_PRODUCT "Arduino Leonardo" -#elif USB_PID == 0x8037 -#define USB_PRODUCT "Arduino Micro" -#elif USB_PID == 0x803C -#define USB_PRODUCT "Arduino Esplora" -#elif USB_PID == 0x9208 -#define USB_PRODUCT "LilyPad USB" -#else +// If no product is provided, use USB IO Board #define USB_PRODUCT "USB IO Board" #endif -#endif const u8 STRING_PRODUCT[] PROGMEM = USB_PRODUCT; From c32c3517a5a19a26e45900a333d30489299b8c5e Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 17 Jul 2013 14:42:41 +0200 Subject: [PATCH 06/16] Added quoting to usb_product key to preserve double quotes. See #1422. --- hardware/arduino/avr/platform.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/arduino/avr/platform.txt b/hardware/arduino/avr/platform.txt index a0e35c3ec..6bf3cdbe0 100644 --- a/hardware/arduino/avr/platform.txt +++ b/hardware/arduino/avr/platform.txt @@ -91,4 +91,4 @@ tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verb # Default blank usb manufacturer will be filled it at compile time # - from numeric vendor ID, set to Unknown otherwise build.usb_manufacturer= -build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} -DUSB_PRODUCT={build.usb_product} +build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSB_MANUFACTURER={build.usb_manufacturer} '-DUSB_PRODUCT={build.usb_product}' From f8ec9418d12d2c653746a710207fc86f6e62c2d4 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 19 Jul 2013 16:08:36 +0200 Subject: [PATCH 07/16] Fixed bug in StringReplacer --- .../app/helpers/StringReplacer.java | 6 ++-- .../app/helpers/StringReplacerTest.java | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 app/test/processing/app/helpers/StringReplacerTest.java diff --git a/app/src/processing/app/helpers/StringReplacer.java b/app/src/processing/app/helpers/StringReplacer.java index 2ab42896a..60445e063 100644 --- a/app/src/processing/app/helpers/StringReplacer.java +++ b/app/src/processing/app/helpers/StringReplacer.java @@ -57,8 +57,10 @@ public class StringReplacer { for (String i : src.split(" ")) { if (escapingChar == null) { // If the first char is not an escape char.. - String first = i.substring(0, 1); - if (!quoteChars.contains(first)) { + String first = null; + if (i.length() > 0) + first = i.substring(0, 1); + if (first == null || !quoteChars.contains(first)) { if (i.trim().length() != 0 || acceptEmptyArguments) res.add(i); continue; diff --git a/app/test/processing/app/helpers/StringReplacerTest.java b/app/test/processing/app/helpers/StringReplacerTest.java new file mode 100644 index 000000000..90ecd0144 --- /dev/null +++ b/app/test/processing/app/helpers/StringReplacerTest.java @@ -0,0 +1,29 @@ +package processing.app.helpers; + +import static org.junit.Assert.assertArrayEquals; + +import org.junit.Test; + +public class StringReplacerTest { + + @Test + public void quotingCheck() throws Exception { + String in = "a\"bc ab'c 'abc abc' "; + in += "\"abc abc\" '\"abc abc\"' "; + in += "\"'abc abc'\""; + String[] res = StringReplacer.quotedSplit(in, "\"'", false); + assertArrayEquals(res, new String[] { "a\"bc", "ab'c", "abc abc", + "abc abc", "\"abc abc\"", "'abc abc'" }); + } + + @Test + public void quotingCheckWithEmptyStringsAccepted() throws Exception { + String in = "a\"bc ab'c 'abc abc' "; + in += "\"abc abc\" '\"abc abc\"' "; + in += "\"'abc abc'\""; + String[] res = StringReplacer.quotedSplit(in, "\"'", true); + assertArrayEquals(res, new String[] { "a\"bc", "ab'c", "", "", "abc abc", + "abc abc", "\"abc abc\"", "'abc abc'" }); + } + +} From f8d32a0659d7dc8c860d7b9f6ef11db245658199 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 22 Jul 2013 12:29:02 +0200 Subject: [PATCH 08/16] Parametric USB configuration for Arduino Due (experimental) --- hardware/arduino/sam/boards.txt | 6 +- .../arduino/sam/cores/arduino/USB/USBCore.cpp | 67 ++++++++++++------- hardware/arduino/sam/platform.txt | 9 +++ 3 files changed, 55 insertions(+), 27 deletions(-) diff --git a/hardware/arduino/sam/boards.txt b/hardware/arduino/sam/boards.txt index c61b01fac..c0afc3d13 100644 --- a/hardware/arduino/sam/boards.txt +++ b/hardware/arduino/sam/boards.txt @@ -8,9 +8,10 @@ arduino_due_x_dbg.upload.wait_for_upload_port=false arduino_due_x_dbg.upload.native_usb=false arduino_due_x_dbg.build.mcu=cortex-m3 arduino_due_x_dbg.build.f_cpu=84000000L +arduino_due_x_dbg.build.usb_product="Arduino Due" arduino_due_x_dbg.build.board=SAM_DUE arduino_due_x_dbg.build.core=arduino -arduino_due_x_dbg.build.extra_flags=-D__SAM3X8E__ -mthumb -DUSB_PID={build.pid} -DUSB_VID={build.vid} -DUSBCON +arduino_due_x_dbg.build.extra_flags=-D__SAM3X8E__ -mthumb {build.usb_flags} arduino_due_x_dbg.build.ldscript=linker_scripts/gcc/flash.ld arduino_due_x_dbg.build.variant=arduino_due_x arduino_due_x_dbg.build.variant_system_lib=libsam_sam3x8e_gcc_rel.a @@ -26,9 +27,10 @@ arduino_due_x.upload.wait_for_upload_port=true arduino_due_x.upload.native_usb=true arduino_due_x.build.mcu=cortex-m3 arduino_due_x.build.f_cpu=84000000L +arduino_due_x.build.usb_product="Arduino Due" arduino_due_x.build.board=SAM_DUE arduino_due_x.build.core=arduino -arduino_due_x.build.extra_flags=-D__SAM3X8E__ -mthumb -DUSB_PID={build.pid} -DUSB_VID={build.vid} -DUSBCON +arduino_due_x.build.extra_flags=-D__SAM3X8E__ -mthumb {build.usb_flags} arduino_due_x.build.ldscript=linker_scripts/gcc/flash.ld arduino_due_x.build.variant=arduino_due_x arduino_due_x.build.variant_system_lib=libsam_sam3x8e_gcc_rel.a diff --git a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp index 8cb01a51a..7876762b7 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp +++ b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp @@ -47,8 +47,8 @@ static char isEndpointHalt = 0; //================================================================== extern const uint16_t STRING_LANGUAGE[]; -extern const uint16_t STRING_IPRODUCT[]; -extern const uint16_t STRING_IMANUFACTURER[]; +extern const uint8_t STRING_PRODUCT[]; +extern const uint8_t STRING_MANUFACTURER[]; extern const DeviceDescriptor USB_DeviceDescriptor; extern const DeviceDescriptor USB_DeviceDescriptorA; @@ -57,23 +57,25 @@ const uint16_t STRING_LANGUAGE[2] = { 0x0409 // English }; -const uint16_t STRING_IPRODUCT[17] = { - (3<<8) | (2+2*16), -#if USB_PID == USB_PID_LEONARDO - 'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o' -#elif USB_PID == USB_PID_MICRO - 'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ',' ',' ' -#elif USB_PID == USB_PID_DUE - 'A','r','d','u','i','n','o',' ','D','u','e',' ',' ',' ',' ',' ' +#ifndef USB_PRODUCT +// Use a hardcoded product name if none is provided +#if USB_PID == USB_PID_DUE +#define USB_PRODUCT "Arduino Due" #else -#error "Need an USB PID" +#define USB_PRODUCT "USB IO Board" +#endif #endif -}; -const uint16_t STRING_IMANUFACTURER[12] = { - (3<<8) | (2+2*11), - 'A','r','d','u','i','n','o',' ','L','L','C' -}; +const uint8_t STRING_PRODUCT[] = USB_PRODUCT; + +#if USB_VID == 0x2341 +#define USB_MANUFACTURER "Arduino LLC" +#elif !defined(USB_MANUFACTURER) +// Fall through to unknown if no manufacturer name was provided in a macro +#define USB_MANUFACTURER "Unknown" +#endif + +const uint8_t STRING_MANUFACTURER[12] = USB_MANUFACTURER; #ifdef CDC_ENABLED #define DEVICE_CLASS 0x02 @@ -241,6 +243,21 @@ int USBD_SendControl(uint8_t flags, const void* d, uint32_t len) return length; } +// Send a USB descriptor string. The string is stored as a +// plain ASCII string but is sent out as UTF-16 with the +// correct 2-byte prefix +static bool USB_SendStringDescriptor(const uint8_t *string, int wLength) { + uint16_t buff[64]; + int l = 1; + wLength-=2; + while (*string && wLength>0) { + buff[l++] = (uint8_t)(*string++); + wLength-=2; + } + buff[0] = (3<<8) | (l*2); + return USBD_SendControl(0, (uint8_t*)buff, l*2); +} + // Does not timeout or cross fifo boundaries // Will only work for transfers <= 64 bytes // TODO @@ -400,19 +417,19 @@ static bool USBD_SendDescriptor(Setup& setup) TRACE_CORE(puts("=> USBD_SendDescriptor : USB_STRING_DESCRIPTOR_TYPE\r\n");) if (setup.wValueL == 0) { desc_addr = (const uint8_t*)&STRING_LANGUAGE; - } + } else if (setup.wValueL == IPRODUCT) { - desc_addr = (const uint8_t*)&STRING_IPRODUCT; - } + return USB_SendStringDescriptor(STRING_PRODUCT, setup.wLength); + } else if (setup.wValueL == IMANUFACTURER) { - desc_addr = (const uint8_t*)&STRING_IMANUFACTURER; - } + return USB_SendStringDescriptor(STRING_MANUFACTURER, setup.wLength); + } else { return false; - } - if( *desc_addr > setup.wLength ) { - desc_length = setup.wLength; - } + } + if( *desc_addr > setup.wLength ) { + desc_length = setup.wLength; + } } else if (USB_DEVICE_QUALIFIER == t) { diff --git a/hardware/arduino/sam/platform.txt b/hardware/arduino/sam/platform.txt index 2aa8c0ab3..7f0adce20 100644 --- a/hardware/arduino/sam/platform.txt +++ b/hardware/arduino/sam/platform.txt @@ -33,6 +33,15 @@ build.extra_flags= compiler.libsam.c.flags="-I{build.system.path}/libsam" "-I{build.system.path}/CMSIS/CMSIS/Include/" "-I{build.system.path}/CMSIS/Device/ATMEL/" +# USB Flags +# --------- +build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSBCON -DUSB_MANUFACTURER={build.usb_manufacturer} '-DUSB_PRODUCT={build.usb_product}' + +# Default usb manufacturer will be replaced at compile time using +# numeric vendor ID if available or by board's specific value. +build.usb_manufacturer="Unknown" + + # SAM3 compile patterns # --------------------- From d6a5e41b5c394adc7196993d1414a9f0622edd32 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 22 Jul 2013 12:30:25 +0200 Subject: [PATCH 09/16] Fixed usb_products on some AVR boards --- hardware/arduino/avr/boards.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hardware/arduino/avr/boards.txt b/hardware/arduino/avr/boards.txt index 8ee45614c..ebcbf21f7 100644 --- a/hardware/arduino/avr/boards.txt +++ b/hardware/arduino/avr/boards.txt @@ -218,7 +218,7 @@ micro.build.mcu=atmega32u4 micro.build.f_cpu=16000000L micro.build.vid=0x2341 micro.build.pid=0x8037 -micro.build.usb_product=Arduino Micro +micro.build.usb_product="Arduino Micro" micro.build.board=AVR_MICRO micro.build.core=arduino micro.build.variant=micro @@ -248,7 +248,7 @@ esplora.build.mcu=atmega32u4 esplora.build.f_cpu=16000000L esplora.build.vid=0x2341 esplora.build.pid=0x803c -esplora.build.usb_product=Arduino Esplora +esplora.build.usb_product="Arduino Esplora" esplora.build.board=AVR_ESPLORA esplora.build.core=arduino esplora.build.variant=leonardo @@ -414,7 +414,7 @@ LilyPadUSB.build.mcu=atmega32u4 LilyPadUSB.build.f_cpu=8000000L LilyPadUSB.build.vid=0x1B4F LilyPadUSB.build.pid=0x9208 -LilyPadUSB.build.usb_product=LilyPad USB +LilyPadUSB.build.usb_product="LilyPad USB" LilyPadUSB.build.board=AVR_LILYPAD_USB LilyPadUSB.build.core=arduino LilyPadUSB.build.variant=leonardo From e0a9a7676b7b3b0db359b4edcabaf3ef9946eae7 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 18 Apr 2013 18:50:10 +0200 Subject: [PATCH 10/16] Use uint8_t for HardwareSerial ringbuffer pointers Since the buffers aren't bigger than 64 bytes, these values can be smaller. This saves a few bytes of ram, but also saves around 50 bytes of program space, since the values can now be loaded using a single instruction. To prevent problems when people manually increase the buffer size, a compile-time check is added. Closes: #1078 --- hardware/arduino/avr/cores/arduino/HardwareSerial.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp b/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp index eb2365f33..7b056e989 100644 --- a/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp +++ b/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp @@ -62,10 +62,14 @@ struct ring_buffer { unsigned char buffer[SERIAL_BUFFER_SIZE]; - volatile unsigned int head; - volatile unsigned int tail; + volatile uint8_t head; + volatile uint8_t tail; }; +#if SERIAL_BUFFER_SIZE > 256 +#error Serial buffer size too big for head and tail pointers +#endif + #if defined(USBCON) ring_buffer rx_buffer = { { 0 }, 0, 0}; ring_buffer tx_buffer = { { 0 }, 0, 0}; From 0bd6a2d20fb9664255b20e0db11dd4586ebe9007 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 18 Apr 2013 18:52:48 +0200 Subject: [PATCH 11/16] Move buffers into HardwareSerial This removes the need for doing an extra pointer dereference on every access to the buffers, shrinking the code by around 100 bytes. The members for these buffers must be public for now, since the interrupt handlers also need to access them. These can later be made private again. Furthermore, the struct ring_buffer was removed. This allows the all head and tail pointers to be put into the HardwareSerial struct before the actual buffers, so the pointers all end up in the first 32 bytes of the struct that can be accessed using a single instruction (ldd). References: #947 --- .../avr/cores/arduino/HardwareSerial.cpp | 125 ++++++------------ .../avr/cores/arduino/HardwareSerial.h | 26 +++- 2 files changed, 63 insertions(+), 88 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp b/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp index 7b056e989..e40bfbc0f 100644 --- a/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp +++ b/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp @@ -49,59 +49,17 @@ #endif #endif -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which head is the index of the location -// to which to write the next incoming character and tail is the index of the -// location from which to read. -#if (RAMEND < 1000) - #define SERIAL_BUFFER_SIZE 16 -#else - #define SERIAL_BUFFER_SIZE 64 -#endif - -struct ring_buffer +inline void store_char(unsigned char c, HardwareSerial *s) { - unsigned char buffer[SERIAL_BUFFER_SIZE]; - volatile uint8_t head; - volatile uint8_t tail; -}; - -#if SERIAL_BUFFER_SIZE > 256 -#error Serial buffer size too big for head and tail pointers -#endif - -#if defined(USBCON) - ring_buffer rx_buffer = { { 0 }, 0, 0}; - ring_buffer tx_buffer = { { 0 }, 0, 0}; -#endif -#if defined(UBRRH) || defined(UBRR0H) - ring_buffer rx_buffer = { { 0 }, 0, 0 }; - ring_buffer tx_buffer = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR1H) - ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; - ring_buffer tx_buffer1 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR2H) - ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; - ring_buffer tx_buffer2 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR3H) - ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; - ring_buffer tx_buffer3 = { { 0 }, 0, 0 }; -#endif - -inline void store_char(unsigned char c, ring_buffer *buffer) -{ - int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE; + int i = (unsigned int)(s->_rx_buffer_head + 1) % SERIAL_BUFFER_SIZE; // if we should be storing the received character into the location // just before the tail (meaning that the head would advance to the // current location of the tail), we're about to overflow the buffer // and so we don't write the character or advance the head. - if (i != buffer->tail) { - buffer->buffer[buffer->head] = c; - buffer->head = i; + if (i != s->_rx_buffer_tail) { + s->_rx_buffer[s->_rx_buffer_head] = c; + s->_rx_buffer_head = i; } } @@ -126,7 +84,7 @@ inline void store_char(unsigned char c, ring_buffer *buffer) #if defined(UDR0) if (bit_is_clear(UCSR0A, UPE0)) { unsigned char c = UDR0; - store_char(c, &rx_buffer); + store_char(c, &Serial); } else { unsigned char c = UDR0; }; @@ -152,7 +110,7 @@ inline void store_char(unsigned char c, ring_buffer *buffer) { if (bit_is_clear(UCSR1A, UPE1)) { unsigned char c = UDR1; - store_char(c, &rx_buffer1); + store_char(c, &Serial1); } else { unsigned char c = UDR1; }; @@ -167,7 +125,7 @@ inline void store_char(unsigned char c, ring_buffer *buffer) { if (bit_is_clear(UCSR2A, UPE2)) { unsigned char c = UDR2; - store_char(c, &rx_buffer2); + store_char(c, &Serial2); } else { unsigned char c = UDR2; }; @@ -182,7 +140,7 @@ inline void store_char(unsigned char c, ring_buffer *buffer) { if (bit_is_clear(UCSR3A, UPE3)) { unsigned char c = UDR3; - store_char(c, &rx_buffer3); + store_char(c, &Serial3); } else { unsigned char c = UDR3; }; @@ -222,7 +180,7 @@ ISR(USART0_UDRE_vect) ISR(USART_UDRE_vect) #endif { - if (tx_buffer.head == tx_buffer.tail) { + if (Serial._tx_buffer_head == Serial._tx_buffer_tail) { // Buffer empty, so disable interrupts #if defined(UCSR0B) cbi(UCSR0B, UDRIE0); @@ -232,8 +190,8 @@ ISR(USART_UDRE_vect) } else { // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer.buffer[tx_buffer.tail]; - tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = Serial._tx_buffer[Serial._tx_buffer_tail]; + Serial._tx_buffer_tail = (Serial._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; #if defined(UDR0) UDR0 = c; @@ -250,14 +208,14 @@ ISR(USART_UDRE_vect) #ifdef USART1_UDRE_vect ISR(USART1_UDRE_vect) { - if (tx_buffer1.head == tx_buffer1.tail) { + if (Serial1._tx_buffer_head == Serial1._tx_buffer_tail) { // Buffer empty, so disable interrupts cbi(UCSR1B, UDRIE1); } else { // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer1.buffer[tx_buffer1.tail]; - tx_buffer1.tail = (tx_buffer1.tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = Serial1._tx_buffer[Serial1._tx_buffer_tail]; + Serial1._tx_buffer_tail = (Serial1._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; UDR1 = c; } @@ -267,14 +225,14 @@ ISR(USART1_UDRE_vect) #ifdef USART2_UDRE_vect ISR(USART2_UDRE_vect) { - if (tx_buffer2.head == tx_buffer2.tail) { + if (Serial2._tx_buffer_head == Serial2._tx_buffer_tail) { // Buffer empty, so disable interrupts cbi(UCSR2B, UDRIE2); } else { // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer2.buffer[tx_buffer2.tail]; - tx_buffer2.tail = (tx_buffer2.tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = Serial2._tx_buffer[Serial2._tx_buffer_tail]; + Serial2._tx_buffer_tail = (Serial2._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; UDR2 = c; } @@ -284,31 +242,30 @@ ISR(USART2_UDRE_vect) #ifdef USART3_UDRE_vect ISR(USART3_UDRE_vect) { - if (tx_buffer3.head == tx_buffer3.tail) { + if (Serial3._tx_buffer_head == Serial3._tx_buffer_tail) { // Buffer empty, so disable interrupts cbi(UCSR3B, UDRIE3); } else { // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer3.buffer[tx_buffer3.tail]; - tx_buffer3.tail = (tx_buffer3.tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = Serial3._tx_buffer[Serial3._tx_buffer_tail]; + Serial3._tx_buffer_tail = (Serial3._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; UDR3 = c; } } #endif - // Constructors //////////////////////////////////////////////////////////////// -HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, +HardwareSerial::HardwareSerial( volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *ucsrc, volatile uint8_t *udr, uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x) { - _rx_buffer = rx_buffer; - _tx_buffer = tx_buffer; + _tx_buffer_head = _tx_buffer_tail = 0; + _rx_buffer_head = _rx_buffer_tail = 0; _ubrrh = ubrrh; _ubrrl = ubrrl; _ucsra = ucsra; @@ -416,7 +373,7 @@ try_again: void HardwareSerial::end() { // wait for transmission of outgoing data - while (_tx_buffer->head != _tx_buffer->tail) + while (_tx_buffer_head != _tx_buffer_tail) ; cbi(*_ucsrb, _rxen); @@ -425,31 +382,31 @@ void HardwareSerial::end() cbi(*_ucsrb, _udrie); // clear any received data - _rx_buffer->head = _rx_buffer->tail; + _rx_buffer_head = _rx_buffer_tail; } int HardwareSerial::available(void) { - return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE; + return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail) % SERIAL_BUFFER_SIZE; } int HardwareSerial::peek(void) { - if (_rx_buffer->head == _rx_buffer->tail) { + if (_rx_buffer_head == _rx_buffer_tail) { return -1; } else { - return _rx_buffer->buffer[_rx_buffer->tail]; + return _rx_buffer[_rx_buffer_tail]; } } int HardwareSerial::read(void) { // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer->head == _rx_buffer->tail) { + if (_rx_buffer_head == _rx_buffer_tail) { return -1; } else { - unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = _rx_buffer[_rx_buffer_tail]; + _rx_buffer_tail = (unsigned int)(_rx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; return c; } } @@ -463,16 +420,16 @@ void HardwareSerial::flush() size_t HardwareSerial::write(uint8_t c) { - int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE; + int i = (_tx_buffer_head + 1) % SERIAL_BUFFER_SIZE; // If the output buffer is full, there's nothing for it other than to // wait for the interrupt handler to empty it a bit // ???: return 0 here instead? - while (i == _tx_buffer->tail) + while (i == _tx_buffer_tail) ; - _tx_buffer->buffer[_tx_buffer->head] = c; - _tx_buffer->head = i; + _tx_buffer[_tx_buffer_head] = c; + _tx_buffer_head = i; sbi(*_ucsrb, _udrie); // clear the TXC bit -- "can be cleared by writing a one to its bit location" @@ -489,9 +446,9 @@ HardwareSerial::operator bool() { // Preinstantiate Objects ////////////////////////////////////////////////////// #if defined(UBRRH) && defined(UBRRL) - HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X); + HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X); #elif defined(UBRR0H) && defined(UBRR0L) - HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0); + HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0); #elif defined(USBCON) // do nothing - Serial object and buffers are initialized in CDC code #else @@ -499,13 +456,13 @@ HardwareSerial::operator bool() { #endif #if defined(UBRR1H) - HardwareSerial Serial1(&rx_buffer1, &tx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1); + HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1); #endif #if defined(UBRR2H) - HardwareSerial Serial2(&rx_buffer2, &tx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2); + HardwareSerial Serial2(&UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2); #endif #if defined(UBRR3H) - HardwareSerial Serial3(&rx_buffer3, &tx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3); + HardwareSerial Serial3(&UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3); #endif #endif // whole file diff --git a/hardware/arduino/avr/cores/arduino/HardwareSerial.h b/hardware/arduino/avr/cores/arduino/HardwareSerial.h index a73117f56..a091e0374 100644 --- a/hardware/arduino/avr/cores/arduino/HardwareSerial.h +++ b/hardware/arduino/avr/cores/arduino/HardwareSerial.h @@ -27,13 +27,19 @@ #include "Stream.h" -struct ring_buffer; +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which head is the index of the location +// to which to write the next incoming character and tail is the index of the +// location from which to read. +#if (RAMEND < 1000) + #define SERIAL_BUFFER_SIZE 16 +#else + #define SERIAL_BUFFER_SIZE 64 +#endif class HardwareSerial : public Stream { private: - ring_buffer *_rx_buffer; - ring_buffer *_tx_buffer; volatile uint8_t *_ubrrh; volatile uint8_t *_ubrrl; volatile uint8_t *_ucsra; @@ -46,8 +52,20 @@ class HardwareSerial : public Stream uint8_t _udrie; uint8_t _u2x; bool transmitting; + public: - HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, + volatile uint8_t _rx_buffer_head; + volatile uint8_t _rx_buffer_tail; + volatile uint8_t _tx_buffer_head; + volatile uint8_t _tx_buffer_tail; + + // Don't put any members after these buffers, since only the first + // 32 bytes of this struct can be accessed quickly using the ldd + // instruction. + unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; + unsigned char _tx_buffer[SERIAL_BUFFER_SIZE]; + + HardwareSerial( volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *ucsrc, volatile uint8_t *udr, From f50372a2a633c7f77c8abef5ea5221884f867ddc Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 18 Apr 2013 18:46:14 +0200 Subject: [PATCH 12/16] Make private members of HardwareSerial protected This allows users to create subclasses. Closes: #947 --- hardware/arduino/avr/cores/arduino/HardwareSerial.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/arduino/avr/cores/arduino/HardwareSerial.h b/hardware/arduino/avr/cores/arduino/HardwareSerial.h index a091e0374..0f6226253 100644 --- a/hardware/arduino/avr/cores/arduino/HardwareSerial.h +++ b/hardware/arduino/avr/cores/arduino/HardwareSerial.h @@ -39,7 +39,7 @@ class HardwareSerial : public Stream { - private: + protected: volatile uint8_t *_ubrrh; volatile uint8_t *_ubrrl; volatile uint8_t *_ucsra; From ae4427f2ea82584e0a92a46dbf57775acea773b9 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 26 Jul 2013 12:50:17 +0200 Subject: [PATCH 13/16] Fixed compile problem for Leonardo after 0bd6a2d20fb9664255b20e0db11dd4586ebe9007 --- hardware/arduino/avr/cores/arduino/USBAPI.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hardware/arduino/avr/cores/arduino/USBAPI.h b/hardware/arduino/avr/cores/arduino/USBAPI.h index eb2e5937d..1a4183bae 100644 --- a/hardware/arduino/avr/cores/arduino/USBAPI.h +++ b/hardware/arduino/avr/cores/arduino/USBAPI.h @@ -25,6 +25,8 @@ extern USBDevice_ USBDevice; //================================================================================ // Serial over CDC (Serial1 is the physical port) +struct ring_buffer; + class Serial_ : public Stream { private: @@ -193,4 +195,4 @@ void USB_Flush(uint8_t ep); #endif -#endif /* if defined(USBCON) */ \ No newline at end of file +#endif /* if defined(USBCON) */ From 4055ac13f3c894fbb32844fcfe46020716f6b492 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 26 Jul 2013 13:50:34 +0200 Subject: [PATCH 14/16] Applied HardwareSerial updates to robot's core. --- .../avr/cores/robot/HardwareSerial.cpp | 121 ++++++------------ .../arduino/avr/cores/robot/HardwareSerial.h | 28 +++- hardware/arduino/avr/cores/robot/USBAPI.h | 4 +- 3 files changed, 67 insertions(+), 86 deletions(-) diff --git a/hardware/arduino/avr/cores/robot/HardwareSerial.cpp b/hardware/arduino/avr/cores/robot/HardwareSerial.cpp index eb2365f33..e40bfbc0f 100644 --- a/hardware/arduino/avr/cores/robot/HardwareSerial.cpp +++ b/hardware/arduino/avr/cores/robot/HardwareSerial.cpp @@ -49,55 +49,17 @@ #endif #endif -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which head is the index of the location -// to which to write the next incoming character and tail is the index of the -// location from which to read. -#if (RAMEND < 1000) - #define SERIAL_BUFFER_SIZE 16 -#else - #define SERIAL_BUFFER_SIZE 64 -#endif - -struct ring_buffer +inline void store_char(unsigned char c, HardwareSerial *s) { - unsigned char buffer[SERIAL_BUFFER_SIZE]; - volatile unsigned int head; - volatile unsigned int tail; -}; - -#if defined(USBCON) - ring_buffer rx_buffer = { { 0 }, 0, 0}; - ring_buffer tx_buffer = { { 0 }, 0, 0}; -#endif -#if defined(UBRRH) || defined(UBRR0H) - ring_buffer rx_buffer = { { 0 }, 0, 0 }; - ring_buffer tx_buffer = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR1H) - ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; - ring_buffer tx_buffer1 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR2H) - ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; - ring_buffer tx_buffer2 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR3H) - ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; - ring_buffer tx_buffer3 = { { 0 }, 0, 0 }; -#endif - -inline void store_char(unsigned char c, ring_buffer *buffer) -{ - int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE; + int i = (unsigned int)(s->_rx_buffer_head + 1) % SERIAL_BUFFER_SIZE; // if we should be storing the received character into the location // just before the tail (meaning that the head would advance to the // current location of the tail), we're about to overflow the buffer // and so we don't write the character or advance the head. - if (i != buffer->tail) { - buffer->buffer[buffer->head] = c; - buffer->head = i; + if (i != s->_rx_buffer_tail) { + s->_rx_buffer[s->_rx_buffer_head] = c; + s->_rx_buffer_head = i; } } @@ -122,7 +84,7 @@ inline void store_char(unsigned char c, ring_buffer *buffer) #if defined(UDR0) if (bit_is_clear(UCSR0A, UPE0)) { unsigned char c = UDR0; - store_char(c, &rx_buffer); + store_char(c, &Serial); } else { unsigned char c = UDR0; }; @@ -148,7 +110,7 @@ inline void store_char(unsigned char c, ring_buffer *buffer) { if (bit_is_clear(UCSR1A, UPE1)) { unsigned char c = UDR1; - store_char(c, &rx_buffer1); + store_char(c, &Serial1); } else { unsigned char c = UDR1; }; @@ -163,7 +125,7 @@ inline void store_char(unsigned char c, ring_buffer *buffer) { if (bit_is_clear(UCSR2A, UPE2)) { unsigned char c = UDR2; - store_char(c, &rx_buffer2); + store_char(c, &Serial2); } else { unsigned char c = UDR2; }; @@ -178,7 +140,7 @@ inline void store_char(unsigned char c, ring_buffer *buffer) { if (bit_is_clear(UCSR3A, UPE3)) { unsigned char c = UDR3; - store_char(c, &rx_buffer3); + store_char(c, &Serial3); } else { unsigned char c = UDR3; }; @@ -218,7 +180,7 @@ ISR(USART0_UDRE_vect) ISR(USART_UDRE_vect) #endif { - if (tx_buffer.head == tx_buffer.tail) { + if (Serial._tx_buffer_head == Serial._tx_buffer_tail) { // Buffer empty, so disable interrupts #if defined(UCSR0B) cbi(UCSR0B, UDRIE0); @@ -228,8 +190,8 @@ ISR(USART_UDRE_vect) } else { // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer.buffer[tx_buffer.tail]; - tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = Serial._tx_buffer[Serial._tx_buffer_tail]; + Serial._tx_buffer_tail = (Serial._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; #if defined(UDR0) UDR0 = c; @@ -246,14 +208,14 @@ ISR(USART_UDRE_vect) #ifdef USART1_UDRE_vect ISR(USART1_UDRE_vect) { - if (tx_buffer1.head == tx_buffer1.tail) { + if (Serial1._tx_buffer_head == Serial1._tx_buffer_tail) { // Buffer empty, so disable interrupts cbi(UCSR1B, UDRIE1); } else { // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer1.buffer[tx_buffer1.tail]; - tx_buffer1.tail = (tx_buffer1.tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = Serial1._tx_buffer[Serial1._tx_buffer_tail]; + Serial1._tx_buffer_tail = (Serial1._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; UDR1 = c; } @@ -263,14 +225,14 @@ ISR(USART1_UDRE_vect) #ifdef USART2_UDRE_vect ISR(USART2_UDRE_vect) { - if (tx_buffer2.head == tx_buffer2.tail) { + if (Serial2._tx_buffer_head == Serial2._tx_buffer_tail) { // Buffer empty, so disable interrupts cbi(UCSR2B, UDRIE2); } else { // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer2.buffer[tx_buffer2.tail]; - tx_buffer2.tail = (tx_buffer2.tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = Serial2._tx_buffer[Serial2._tx_buffer_tail]; + Serial2._tx_buffer_tail = (Serial2._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; UDR2 = c; } @@ -280,31 +242,30 @@ ISR(USART2_UDRE_vect) #ifdef USART3_UDRE_vect ISR(USART3_UDRE_vect) { - if (tx_buffer3.head == tx_buffer3.tail) { + if (Serial3._tx_buffer_head == Serial3._tx_buffer_tail) { // Buffer empty, so disable interrupts cbi(UCSR3B, UDRIE3); } else { // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer3.buffer[tx_buffer3.tail]; - tx_buffer3.tail = (tx_buffer3.tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = Serial3._tx_buffer[Serial3._tx_buffer_tail]; + Serial3._tx_buffer_tail = (Serial3._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; UDR3 = c; } } #endif - // Constructors //////////////////////////////////////////////////////////////// -HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, +HardwareSerial::HardwareSerial( volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *ucsrc, volatile uint8_t *udr, uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x) { - _rx_buffer = rx_buffer; - _tx_buffer = tx_buffer; + _tx_buffer_head = _tx_buffer_tail = 0; + _rx_buffer_head = _rx_buffer_tail = 0; _ubrrh = ubrrh; _ubrrl = ubrrl; _ucsra = ucsra; @@ -412,7 +373,7 @@ try_again: void HardwareSerial::end() { // wait for transmission of outgoing data - while (_tx_buffer->head != _tx_buffer->tail) + while (_tx_buffer_head != _tx_buffer_tail) ; cbi(*_ucsrb, _rxen); @@ -421,31 +382,31 @@ void HardwareSerial::end() cbi(*_ucsrb, _udrie); // clear any received data - _rx_buffer->head = _rx_buffer->tail; + _rx_buffer_head = _rx_buffer_tail; } int HardwareSerial::available(void) { - return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE; + return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail) % SERIAL_BUFFER_SIZE; } int HardwareSerial::peek(void) { - if (_rx_buffer->head == _rx_buffer->tail) { + if (_rx_buffer_head == _rx_buffer_tail) { return -1; } else { - return _rx_buffer->buffer[_rx_buffer->tail]; + return _rx_buffer[_rx_buffer_tail]; } } int HardwareSerial::read(void) { // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer->head == _rx_buffer->tail) { + if (_rx_buffer_head == _rx_buffer_tail) { return -1; } else { - unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = _rx_buffer[_rx_buffer_tail]; + _rx_buffer_tail = (unsigned int)(_rx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; return c; } } @@ -459,16 +420,16 @@ void HardwareSerial::flush() size_t HardwareSerial::write(uint8_t c) { - int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE; + int i = (_tx_buffer_head + 1) % SERIAL_BUFFER_SIZE; // If the output buffer is full, there's nothing for it other than to // wait for the interrupt handler to empty it a bit // ???: return 0 here instead? - while (i == _tx_buffer->tail) + while (i == _tx_buffer_tail) ; - _tx_buffer->buffer[_tx_buffer->head] = c; - _tx_buffer->head = i; + _tx_buffer[_tx_buffer_head] = c; + _tx_buffer_head = i; sbi(*_ucsrb, _udrie); // clear the TXC bit -- "can be cleared by writing a one to its bit location" @@ -485,9 +446,9 @@ HardwareSerial::operator bool() { // Preinstantiate Objects ////////////////////////////////////////////////////// #if defined(UBRRH) && defined(UBRRL) - HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X); + HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X); #elif defined(UBRR0H) && defined(UBRR0L) - HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0); + HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0); #elif defined(USBCON) // do nothing - Serial object and buffers are initialized in CDC code #else @@ -495,13 +456,13 @@ HardwareSerial::operator bool() { #endif #if defined(UBRR1H) - HardwareSerial Serial1(&rx_buffer1, &tx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1); + HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1); #endif #if defined(UBRR2H) - HardwareSerial Serial2(&rx_buffer2, &tx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2); + HardwareSerial Serial2(&UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2); #endif #if defined(UBRR3H) - HardwareSerial Serial3(&rx_buffer3, &tx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3); + HardwareSerial Serial3(&UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3); #endif #endif // whole file diff --git a/hardware/arduino/avr/cores/robot/HardwareSerial.h b/hardware/arduino/avr/cores/robot/HardwareSerial.h index a73117f56..0f6226253 100644 --- a/hardware/arduino/avr/cores/robot/HardwareSerial.h +++ b/hardware/arduino/avr/cores/robot/HardwareSerial.h @@ -27,13 +27,19 @@ #include "Stream.h" -struct ring_buffer; +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which head is the index of the location +// to which to write the next incoming character and tail is the index of the +// location from which to read. +#if (RAMEND < 1000) + #define SERIAL_BUFFER_SIZE 16 +#else + #define SERIAL_BUFFER_SIZE 64 +#endif class HardwareSerial : public Stream { - private: - ring_buffer *_rx_buffer; - ring_buffer *_tx_buffer; + protected: volatile uint8_t *_ubrrh; volatile uint8_t *_ubrrl; volatile uint8_t *_ucsra; @@ -46,8 +52,20 @@ class HardwareSerial : public Stream uint8_t _udrie; uint8_t _u2x; bool transmitting; + public: - HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, + volatile uint8_t _rx_buffer_head; + volatile uint8_t _rx_buffer_tail; + volatile uint8_t _tx_buffer_head; + volatile uint8_t _tx_buffer_tail; + + // Don't put any members after these buffers, since only the first + // 32 bytes of this struct can be accessed quickly using the ldd + // instruction. + unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; + unsigned char _tx_buffer[SERIAL_BUFFER_SIZE]; + + HardwareSerial( volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *ucsrc, volatile uint8_t *udr, diff --git a/hardware/arduino/avr/cores/robot/USBAPI.h b/hardware/arduino/avr/cores/robot/USBAPI.h index eb2e5937d..1a4183bae 100644 --- a/hardware/arduino/avr/cores/robot/USBAPI.h +++ b/hardware/arduino/avr/cores/robot/USBAPI.h @@ -25,6 +25,8 @@ extern USBDevice_ USBDevice; //================================================================================ // Serial over CDC (Serial1 is the physical port) +struct ring_buffer; + class Serial_ : public Stream { private: @@ -193,4 +195,4 @@ void USB_Flush(uint8_t ep); #endif -#endif /* if defined(USBCON) */ \ No newline at end of file +#endif /* if defined(USBCON) */ From 8c1ce4553169128cf88a3bc4b781f4f16b758634 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sat, 27 Jul 2013 12:06:42 +0200 Subject: [PATCH 15/16] Move buffers into USB CDC (look #947 and #1369 for reference) --- hardware/arduino/avr/cores/arduino/CDC.cpp | 41 ++++++--------------- hardware/arduino/avr/cores/arduino/USBAPI.h | 12 +++++- hardware/arduino/avr/cores/robot/CDC.cpp | 41 ++++++--------------- hardware/arduino/avr/cores/robot/USBAPI.h | 12 +++++- 4 files changed, 42 insertions(+), 64 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/CDC.cpp b/hardware/arduino/avr/cores/arduino/CDC.cpp index 701e48398..fb25a9622 100644 --- a/hardware/arduino/avr/cores/arduino/CDC.cpp +++ b/hardware/arduino/avr/cores/arduino/CDC.cpp @@ -23,21 +23,6 @@ #if defined(USBCON) #ifdef CDC_ENABLED -#if (RAMEND < 1000) -#define SERIAL_BUFFER_SIZE 16 -#else -#define SERIAL_BUFFER_SIZE 64 -#endif - -struct ring_buffer -{ - unsigned char buffer[SERIAL_BUFFER_SIZE]; - volatile int head; - volatile int tail; -}; - -ring_buffer cdc_rx_buffer = { { 0 }, 0, 0}; - typedef struct { u32 dwDTERate; @@ -140,8 +125,7 @@ void Serial_::end(void) void Serial_::accept(void) { - ring_buffer *buffer = &cdc_rx_buffer; - int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE; + int i = (unsigned int)(_rx_buffer_head+1) % SERIAL_BUFFER_SIZE; // if we should be storing the received character into the location // just before the tail (meaning that the head would advance to the @@ -149,42 +133,39 @@ void Serial_::accept(void) // and so we don't write the character or advance the head. // while we have room to store a byte - while (i != buffer->tail) { + while (i != _rx_buffer_tail) { int c = USB_Recv(CDC_RX); if (c == -1) break; // no more data - buffer->buffer[buffer->head] = c; - buffer->head = i; + _rx_buffer[_rx_buffer_head] = c; + _rx_buffer_head = i; - i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE; + i = (unsigned int)(_rx_buffer_head+1) % SERIAL_BUFFER_SIZE; } } int Serial_::available(void) { - ring_buffer *buffer = &cdc_rx_buffer; - return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE; + return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail) % SERIAL_BUFFER_SIZE; } int Serial_::peek(void) { - ring_buffer *buffer = &cdc_rx_buffer; - if (buffer->head == buffer->tail) { + if (_rx_buffer_head == _rx_buffer_tail) { return -1; } else { - return buffer->buffer[buffer->tail]; + return _rx_buffer[_rx_buffer_tail]; } } int Serial_::read(void) { - ring_buffer *buffer = &cdc_rx_buffer; // if the head isn't ahead of the tail, we don't have any characters - if (buffer->head == buffer->tail) { + if (_rx_buffer_head == _rx_buffer_tail) { return -1; } else { - unsigned char c = buffer->buffer[buffer->tail]; - buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = _rx_buffer[_rx_buffer_tail]; + _rx_buffer_tail = (unsigned int)(_rx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; return c; } } diff --git a/hardware/arduino/avr/cores/arduino/USBAPI.h b/hardware/arduino/avr/cores/arduino/USBAPI.h index 1a4183bae..cabecf354 100644 --- a/hardware/arduino/avr/cores/arduino/USBAPI.h +++ b/hardware/arduino/avr/cores/arduino/USBAPI.h @@ -27,10 +27,14 @@ extern USBDevice_ USBDevice; struct ring_buffer; +#if (RAMEND < 1000) +#define SERIAL_BUFFER_SIZE 16 +#else +#define SERIAL_BUFFER_SIZE 64 +#endif + class Serial_ : public Stream { -private: - ring_buffer *_cdc_rx_buffer; public: void begin(uint16_t baud_count); void end(void); @@ -43,6 +47,10 @@ public: virtual size_t write(uint8_t); using Print::write; // pull in write(str) and write(buf, size) from Print operator bool(); + + volatile uint8_t _rx_buffer_head; + volatile uint8_t _rx_buffer_tail; + unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; }; extern Serial_ Serial; diff --git a/hardware/arduino/avr/cores/robot/CDC.cpp b/hardware/arduino/avr/cores/robot/CDC.cpp index 701e48398..fb25a9622 100644 --- a/hardware/arduino/avr/cores/robot/CDC.cpp +++ b/hardware/arduino/avr/cores/robot/CDC.cpp @@ -23,21 +23,6 @@ #if defined(USBCON) #ifdef CDC_ENABLED -#if (RAMEND < 1000) -#define SERIAL_BUFFER_SIZE 16 -#else -#define SERIAL_BUFFER_SIZE 64 -#endif - -struct ring_buffer -{ - unsigned char buffer[SERIAL_BUFFER_SIZE]; - volatile int head; - volatile int tail; -}; - -ring_buffer cdc_rx_buffer = { { 0 }, 0, 0}; - typedef struct { u32 dwDTERate; @@ -140,8 +125,7 @@ void Serial_::end(void) void Serial_::accept(void) { - ring_buffer *buffer = &cdc_rx_buffer; - int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE; + int i = (unsigned int)(_rx_buffer_head+1) % SERIAL_BUFFER_SIZE; // if we should be storing the received character into the location // just before the tail (meaning that the head would advance to the @@ -149,42 +133,39 @@ void Serial_::accept(void) // and so we don't write the character or advance the head. // while we have room to store a byte - while (i != buffer->tail) { + while (i != _rx_buffer_tail) { int c = USB_Recv(CDC_RX); if (c == -1) break; // no more data - buffer->buffer[buffer->head] = c; - buffer->head = i; + _rx_buffer[_rx_buffer_head] = c; + _rx_buffer_head = i; - i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE; + i = (unsigned int)(_rx_buffer_head+1) % SERIAL_BUFFER_SIZE; } } int Serial_::available(void) { - ring_buffer *buffer = &cdc_rx_buffer; - return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE; + return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail) % SERIAL_BUFFER_SIZE; } int Serial_::peek(void) { - ring_buffer *buffer = &cdc_rx_buffer; - if (buffer->head == buffer->tail) { + if (_rx_buffer_head == _rx_buffer_tail) { return -1; } else { - return buffer->buffer[buffer->tail]; + return _rx_buffer[_rx_buffer_tail]; } } int Serial_::read(void) { - ring_buffer *buffer = &cdc_rx_buffer; // if the head isn't ahead of the tail, we don't have any characters - if (buffer->head == buffer->tail) { + if (_rx_buffer_head == _rx_buffer_tail) { return -1; } else { - unsigned char c = buffer->buffer[buffer->tail]; - buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE; + unsigned char c = _rx_buffer[_rx_buffer_tail]; + _rx_buffer_tail = (unsigned int)(_rx_buffer_tail + 1) % SERIAL_BUFFER_SIZE; return c; } } diff --git a/hardware/arduino/avr/cores/robot/USBAPI.h b/hardware/arduino/avr/cores/robot/USBAPI.h index 1a4183bae..cabecf354 100644 --- a/hardware/arduino/avr/cores/robot/USBAPI.h +++ b/hardware/arduino/avr/cores/robot/USBAPI.h @@ -27,10 +27,14 @@ extern USBDevice_ USBDevice; struct ring_buffer; +#if (RAMEND < 1000) +#define SERIAL_BUFFER_SIZE 16 +#else +#define SERIAL_BUFFER_SIZE 64 +#endif + class Serial_ : public Stream { -private: - ring_buffer *_cdc_rx_buffer; public: void begin(uint16_t baud_count); void end(void); @@ -43,6 +47,10 @@ public: virtual size_t write(uint8_t); using Print::write; // pull in write(str) and write(buf, size) from Print operator bool(); + + volatile uint8_t _rx_buffer_head; + volatile uint8_t _rx_buffer_tail; + unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; }; extern Serial_ Serial; From d3be60ead6cddb06a9ca53c69c8bb6501618dd43 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 30 Jul 2013 10:39:41 +0200 Subject: [PATCH 16/16] Applied USB CDC updates to robot's core. --- hardware/arduino/avr/cores/robot/USBCore.cpp | 70 +++++++++++--------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/hardware/arduino/avr/cores/robot/USBCore.cpp b/hardware/arduino/avr/cores/robot/USBCore.cpp index d3e017065..c46c75fe9 100644 --- a/hardware/arduino/avr/cores/robot/USBCore.cpp +++ b/hardware/arduino/avr/cores/robot/USBCore.cpp @@ -39,8 +39,8 @@ volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ //================================================================== extern const u16 STRING_LANGUAGE[] PROGMEM; -extern const u16 STRING_IPRODUCT[] PROGMEM; -extern const u16 STRING_IMANUFACTURER[] PROGMEM; +extern const u8 STRING_PRODUCT[] PROGMEM; +extern const u8 STRING_MANUFACTURER[] PROGMEM; extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; @@ -49,31 +49,24 @@ const u16 STRING_LANGUAGE[2] = { 0x0409 // English }; -const u16 STRING_IPRODUCT[17] = { - (3<<8) | (2+2*16), -#if USB_PID == 0x8036 - 'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o' -#elif USB_PID == 0x8037 - 'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ',' ',' ' -#elif USB_PID == 0x803C - 'A','r','d','u','i','n','o',' ','E','s','p','l','o','r','a',' ' -#elif USB_PID == 0x9208 - 'L','i','l','y','P','a','d','U','S','B',' ',' ',' ',' ',' ',' ' -#else - 'U','S','B',' ','I','O',' ','B','o','a','r','d',' ',' ',' ',' ' +#ifndef USB_PRODUCT +// If no product is provided, use USB IO Board +#define USB_PRODUCT "USB IO Board" #endif -}; -const u16 STRING_IMANUFACTURER[12] = { - (3<<8) | (2+2*11), +const u8 STRING_PRODUCT[] PROGMEM = USB_PRODUCT; + #if USB_VID == 0x2341 - 'A','r','d','u','i','n','o',' ','L','L','C' +#define USB_MANUFACTURER "Arduino LLC" #elif USB_VID == 0x1b4f - 'S','p','a','r','k','F','u','n',' ',' ',' ' -#else - 'U','n','k','n','o','w','n',' ',' ',' ',' ' +#define USB_MANUFACTURER "SparkFun" +#elif !defined(USB_MANUFACTURER) +// Fall through to unknown if no manufacturer name was provided in a macro +#define USB_MANUFACTURER "Unknown" #endif -}; + +const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; + #ifdef CDC_ENABLED #define DEVICE_CLASS 0x02 @@ -416,6 +409,22 @@ int USB_SendControl(u8 flags, const void* d, int len) return sent; } +// Send a USB descriptor string. The string is stored in PROGMEM as a +// plain ASCII string but is sent out as UTF-16 with the correct 2-byte +// prefix +static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) { + SendControl(2 + string_len * 2); + SendControl(3); + for(u8 i = 0; i < string_len; i++) { + bool r = SendControl(pgm_read_byte(&string_P[i])); + r &= SendControl(0); // high byte + if(!r) { + return false; + } + } + return true; +} + // Does not timeout or cross fifo boundaries // Will only work for transfers <= 64 bytes // TODO @@ -476,7 +485,6 @@ bool SendDescriptor(Setup& setup) return HID_GetDescriptor(t); #endif - u8 desc_length = 0; const u8* desc_addr = 0; if (USB_DEVICE_DESCRIPTOR_TYPE == t) { @@ -486,20 +494,22 @@ bool SendDescriptor(Setup& setup) } else if (USB_STRING_DESCRIPTOR_TYPE == t) { - if (setup.wValueL == 0) + if (setup.wValueL == 0) { desc_addr = (const u8*)&STRING_LANGUAGE; - else if (setup.wValueL == IPRODUCT) - desc_addr = (const u8*)&STRING_IPRODUCT; - else if (setup.wValueL == IMANUFACTURER) - desc_addr = (const u8*)&STRING_IMANUFACTURER; + } + else if (setup.wValueL == IPRODUCT) { + return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT)); + } + else if (setup.wValueL == IMANUFACTURER) { + return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER)); + } else return false; } if (desc_addr == 0) return false; - if (desc_length == 0) - desc_length = pgm_read_byte(desc_addr); + u8 desc_length = pgm_read_byte(desc_addr); USB_SendControl(TRANSFER_PGM,desc_addr,desc_length); return true;