Package: bossa-cli
Version: 1.3~20120408-1
Severity: wishlist
Tags: patch

I wrote a makefile a little more than six months ago for compiling Arduino
projects on command line. I used it for a few of my own simple projects on both
my Arduino Uno R2 and Arduino Due R3. However, since the Arduino Due requires
the Arduino IDE 1.5.x, which was not in Debian at the time, I coded my makefile
to use the version from the binary Linux package provided on the Arduino
website. Since that package includes a pre-build toolchain, I used the version
of gcc and bossac that it provided as well. Now that Arduino IDE 1.5.4 is in
Experimental and gcc-arm-none-eabi ships a C++ compiler, I have been working on
modifying my makefile to use only the tools available in the Debian archive. As
of now I can successfully compile my projects using this new makefile, but I
can't upload any of them to the Arduino Due because the version of bossac in
Debian is missing some of the features and bugfixes found in the Arduino
version.

With that in mind, I took a look at both the upstream bossa git repository and
the git repository for the Arduino bossa fork. While the Arduino fork of bossa
on github appears to be based on a pretty old version of bossa, the diff
between the Arduino fork and the latest version of bossa in its git repository
is actually surprisingly manageable. Based on the complete diff I generated,
the commit history of both bossa versions, and a few hours spent familiarizing
myself with the bossa source code, I separated what I believe are the most
important parts of the Arduino bossa fork into a series of 5 diffs which apply
cleanly to both the Debian bossa source and the latest upstream code. Using
this patched version of bossac I can successfully upload my projects to the
Arduino Due. Would it be acceptable to either apply these patches to the Debian
bossa package or rebase the package on the Arduino bossa fork? A diff of the
changes I made to the current bossa package is attached. I appreciate your
consideration.



-- System Information:
Debian Release: jessie/sid
  APT prefers testing
  APT policy: (800, 'testing'), (400, 'unstable'), (200, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.12-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages bossa-cli depends on:
ii  libc6         2.17-97
ii  libgcc1       1:4.8.2-10
ii  libreadline6  6.2+dfsg-0.1
ii  libstdc++6    4.8.2-10

bossa-cli recommends no packages.

bossa-cli suggests no packages.

-- no debconf information
--- a/debian/patches/add-reset-command.patch    1969-12-31 19:00:00.000000000 -0500
+++ b/debian/patches/add-reset-command.patch    2014-01-09 06:06:11.901684390 -0500
@@ -0,0 +1,129 @@
+Description: Add a 'reset' command to be applied after a successful upload
+Author: Cristian Maglie <c.mag...@bug.st>
+--- a/src/Command.cpp
++++ b/src/Command.cpp
+@@ -1211,3 +1211,16 @@
+ 
+     _flasher.write(argv[1]);
+ }
++
++CommandReset::CommandReset() :
++    Command("reset",
++            "Reset the CPU. (only for supported CPU)",
++            "reset\n")
++{}
++
++void
++CommandReset::invoke(char* argv[], int argc)
++{
++    _samba.reset();
++}
++
+--- a/src/Command.h
++++ b/src/Command.h
+@@ -260,4 +260,11 @@
+     virtual void invoke(char* argv[], int argc);
+ };
+ 
++class CommandReset : public Command
++{
++public:
++    CommandReset();
++    virtual void invoke(char* argv[], int argc);
++};
++
+ #endif // _COMMAND_H
+--- a/src/Samba.cpp
++++ b/src/Samba.cpp
+@@ -22,6 +22,7 @@
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <ctype.h>
++#include <unistd.h>
+ 
+ using namespace std;
+ 
+@@ -545,3 +546,21 @@
+     }
+     return cid;
+ }
++
++void
++Samba::reset(void)
++{
++    if (chipId() != 0x285e0a60) {
++        printf("Reset not supported for this CPU");
++        return;
++    }
++
++    printf("CPU reset.\n");
++    writeWord(0x400E1A00, 0xA500000D);
++
++    // Some linux users experienced a lock up if the serial
++    // port is closed while the port itself is being destroyed.
++    // This delay is here to give the time to kernel driver to
++    // sort out things before closing the port.
++    usleep(100000);
++}
+--- a/src/Samba.h
++++ b/src/Samba.h
+@@ -60,6 +60,8 @@
+     void setDebug(bool debug) { _debug = debug; }
+ 
+     const SerialPort& getSerialPort() { return *_port; }
++    
++    void reset(void);
+ 
+ private:
+     bool _debug;
+--- a/src/Shell.cpp
++++ b/src/Shell.cpp
+@@ -55,6 +55,7 @@
+     add(new CommandSecurity);
+     add(new CommandVerify);
+     add(new CommandWrite);
++    add(new CommandReset);
+ 
+     _commandList.sort();
+ }
+--- a/src/bossac.cpp
++++ b/src/bossac.cpp
+@@ -40,6 +40,7 @@
+     bool write;
+     bool read;
+     bool verify;
++    bool reset;
+     bool port;
+     bool boot;
+     bool bor;
+@@ -79,6 +80,8 @@
+     bootArg = 1;
+     bodArg = 1;
+     borArg = 1;
++
++    reset = false;
+ }
+ 
+ static BossaConfig config;
+@@ -162,6 +165,11 @@
+       'h', "help", &config.help,
+       { ArgNone },
+       "display this help text"
++    },
++    {
++      'R', "reset", &config.reset,
++      { ArgNone },
++      "reset CPU (if supported)"
+     }
+ };
+ 
+@@ -331,6 +339,9 @@
+ 
+         if (config.info)
+             flasher.info(samba);
++
++        if (config.reset)
++            samba.reset();
+     }
+     catch (exception& e)
+     {
--- a/debian/patches/allow-autoreset.patch  1969-12-31 19:00:00.000000000 -0500
+++ b/debian/patches/allow-autoreset.patch  2014-01-09 06:09:38.013689668 -0500
@@ -0,0 +1,17 @@
+Description: Allow the microcontroller to reset after flashing (if supported)
+Author: Cristian Maglie <c.mag...@bug.st>
+--- a/src/Samba.cpp
++++ b/src/Samba.cpp
+@@ -57,6 +57,12 @@
+ 
+     _port->timeout(TIMEOUT_QUICK);
+ 
++    // Allows Arduino auto-reset
++    usleep(3000000);
++    // Flush garbage
++    uint8_t dummy[1024];
++    _port->read(dummy, 1024);
++
+     if (!_isUsb)
+     {
+         if (_debug)
--- a/debian/patches/flush-after-upload.patch   1969-12-31 19:00:00.000000000 -0500
+++ b/debian/patches/flush-after-upload.patch   2014-01-09 06:19:52.781705409 -0500
@@ -0,0 +1,72 @@
+Description: Flush the serial port after upload to work around potential driver bugs
+Author: Cristian Maglie <c.mag...@bug.st>
+--- a/src/EefcFlash.cpp
++++ b/src/EefcFlash.cpp
+@@ -62,7 +62,7 @@
+       _regs(regs), _canBrownout(canBrownout), _eraseAuto(true)
+ {
+     assert(planes == 1 || planes == 2);
+-    assert(pages <= 1024);
++    assert(pages <= 2048);
+     assert(lockRegions <= 32);
+ 
+     // SAM3 Errata (FWS must be 6)
+@@ -236,6 +236,8 @@
+ {
+     waitFSR();
+     writeFCR0(enable ? EEFC_FCMD_SGPB : EEFC_FCMD_CGPB, (_canBrownout ? 3 : 1));
++    waitFSR();
++    usleep(10000);
+ }
+ 
+ void
+--- a/src/PosixSerialPort.cpp
++++ b/src/PosixSerialPort.cpp
+@@ -36,7 +36,8 @@
+ #endif
+ 
+ PosixSerialPort::PosixSerialPort(const std::string& name, bool isUsb) :
+-    SerialPort(name), _devfd(-1), _isUsb(isUsb), _timeout(0)
++    SerialPort(name), _devfd(-1), _isUsb(isUsb), _timeout(0),
++    _autoFlush(false)
+ {
+ }
+ 
+@@ -237,7 +238,11 @@
+     if (_devfd == -1)
+         return -1;
+ 
+-    return ::write(_devfd, buffer, len);
++    int res = ::write(_devfd, buffer, len);
++    // Used on macos to avoid upload errors
++    if (_autoFlush)
++        flush();
++    return res;
+ }
+ 
+ int
+@@ -279,3 +284,8 @@
+     return true;
+ }
+ 
++void
++PosixSerialPort::setAutoFlush(bool autoflush)
++{
++    _autoFlush = autoflush;
++}
+--- a/src/PosixSerialPort.h
++++ b/src/PosixSerialPort.h
+@@ -42,11 +42,13 @@
+ 
+     bool timeout(int millisecs);
+     void flush();
++    void setAutoFlush(bool autoflush);
+ 
+ private:
+     int _devfd;
+     bool _isUsb;
+     int _timeout;
++    bool _autoFlush;
+ };
+ 
+ #endif // _POSIXSERIALPORT_H
--- a/debian/patches/override-usb-autodetection.patch   1969-12-31 19:00:00.000000000 -0500
+++ b/debian/patches/override-usb-autodetection.patch   2014-01-09 06:07:33.881686489 -0500
@@ -0,0 +1,148 @@
+Description: Add a command to override USB port autodetection
+Author: Cristian Maglie <c.mag...@bug.st>
+--- a/src/LinuxPortFactory.cpp
++++ b/src/LinuxPortFactory.cpp
+@@ -44,6 +44,12 @@
+         name.find("ttyACM") != std::string::npos)
+         isUsb = true;
+ 
++    return create(name, isUsb);
++}
++
++SerialPort::Ptr
++LinuxPortFactory::create(const std::string& name, bool isUsb)
++{
+     return SerialPort::Ptr(new PosixSerialPort(name, isUsb));
+ }
+ 
+--- a/src/LinuxPortFactory.h
++++ b/src/LinuxPortFactory.h
+@@ -38,6 +38,7 @@
+     virtual std::string next();
+ 
+     virtual SerialPort::Ptr create(const std::string& name);
++    virtual SerialPort::Ptr create(const std::string& name, bool isUsb);
+ 
+ private:
+     std::string _empty;
+--- a/src/OSXPortFactory.cpp
++++ b/src/OSXPortFactory.cpp
+@@ -43,6 +43,12 @@
+     if (name.find("usb") != std::string::npos)
+         isUsb = true;
+ 
++    return create(name, isUsb);
++}
++
++SerialPort::Ptr
++OSXPortFactory::create(const std::string& name, bool isUsb)
++{
+     return SerialPort::Ptr(new PosixSerialPort(name, isUsb));
+ }
+ 
+--- a/src/OSXPortFactory.h
++++ b/src/OSXPortFactory.h
+@@ -38,6 +38,7 @@
+     virtual std::string next();
+ 
+     virtual SerialPort::Ptr create(const std::string& name);
++    virtual SerialPort::Ptr create(const std::string& name, bool isUsb);
+ 
+ private:
+     std::string _empty;
+--- a/src/PortFactory.h
++++ b/src/PortFactory.h
+@@ -34,6 +34,7 @@
+     virtual std::string next() = 0;
+ 
+     virtual SerialPort::Ptr create(const std::string& name) = 0;
++    virtual SerialPort::Ptr create(const std::string& name, bool isUsb) = 0;
+ };
+ 
+ #if defined(__WIN32__)
+--- a/src/WinPortFactory.cpp
++++ b/src/WinPortFactory.cpp
+@@ -45,6 +45,12 @@
+         }
+     }
+ 
++    return create(name, isUsb);
++}
++
++SerialPort::Ptr
++WinPortFactory::create(const std::string& name, bool isUsb)
++{
+     return SerialPort::Ptr(new WinSerialPort(name, isUsb));
+ }
+ 
+--- a/src/WinPortFactory.h
++++ b/src/WinPortFactory.h
+@@ -36,6 +36,7 @@
+     std::string next();
+ 
+     SerialPort::Ptr create(const std::string& name);
++    SerialPort::Ptr create(const std::string& name, bool isUsb);
+ 
+ private:
+     typedef DWORD WINAPI (*CM_Open_DevNode_Key)(DWORD, DWORD, DWORD, DWORD, ::PHKEY, DWORD);
+--- a/src/bossac.cpp
++++ b/src/bossac.cpp
+@@ -51,6 +51,8 @@
+     bool info;
+     bool debug;
+     bool help;
++    bool forceUsb;
++    string forceUsbArg;
+ 
+     int readArg;
+     string portArg;
+@@ -75,6 +77,7 @@
+     security = false;
+     info = false;
+     help = false;
++    forceUsb = false;
+ 
+     readArg = 0;
+     bootArg = 1;
+@@ -167,6 +170,11 @@
+       "display this help text"
+     },
+     {
++      'U', "force_usb_port", &config.forceUsb,
++      { ArgRequired, ArgString, "true/false", { &config.forceUsbArg } },
++      "override USB port autodetection"
++    },
++    {
+       'R', "reset", &config.reset,
+       { ArgNone },
+       "reset CPU (if supported)"
+@@ -264,9 +272,28 @@
+         if (config.debug)
+             samba.setDebug(true);
+ 
++        bool isUsb = false;
++        if (config.forceUsb)
++        {
++            if (config.forceUsbArg.compare("true")==0)
++                isUsb = true;
++            else if (config.forceUsbArg.compare("false")==0)
++                isUsb = false;
++            else
++            {
++                fprintf(stderr, "Invalid USB value: %s\n", config.forceUsbArg.c_str());
++                return 1;
++            }
++        }
++
+         if (config.port)
+         {
+-            if (!samba.connect(portFactory.create(config.portArg)))
++            bool res;
++            if (config.forceUsb)
++                res = samba.connect(portFactory.create(config.portArg, isUsb));
++            else
++                res = samba.connect(portFactory.create(config.portArg));
++            if (!res)
+             {
+                 fprintf(stderr, "No device found on %s\n", config.portArg.c_str());
+                 return 1;
--- a/debian/patches/series 2013-10-14 17:02:38.000000000 -0400
+++ b/debian/patches/series 2014-01-09 05:54:29.245666399 -0500
@@ -1 +1,6 @@
 build_system.patch
+add-reset-command.patch
+override-usb-autodetection.patch
+uart-set-speed.patch
+allow-autoreset.patch
+flush-after-upload.patch
--- a/debian/patches/uart-set-speed.patch   1969-12-31 19:00:00.000000000 -0500
+++ b/debian/patches/uart-set-speed.patch   2014-01-09 06:09:00.277688702 -0500
@@ -0,0 +1,37 @@
+Description: Add internal uart speed parameter
+Author: Cristian Maglie <c.mag...@bug.st>
+--- a/src/Samba.cpp
++++ b/src/Samba.cpp
+@@ -136,7 +136,7 @@
+ }
+ 
+ bool
+-Samba::connect(SerialPort::Ptr port)
++Samba::connect(SerialPort::Ptr port, int bps)
+ {
+     _port = port;
+ 
+@@ -151,10 +151,10 @@
+     _isUsb = false;
+ 
+     // Try the serial port at slower speed
+-    if (_port->open(115200) && init())
++    if (_port->open(bps) && init())
+     {
+         if (_debug)
+-            printf("Connected at 115200 baud\n");
++            printf("Connected at %d baud\n", bps);
+         return true;
+     }
+ 
+--- a/src/Samba.h
++++ b/src/Samba.h
+@@ -39,7 +39,7 @@
+     Samba();
+     virtual ~Samba();
+ 
+-    bool connect(SerialPort::Ptr port);
++    bool connect(SerialPort::Ptr port, int bps=115200);
+     void disconnect();
+ 
+     void writeByte(uint32_t addr, uint8_t value);

Reply via email to