aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bossac/src/bossac.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bossac/src/bossac.cpp')
-rw-r--r--lib/bossac/src/bossac.cpp489
1 files changed, 489 insertions, 0 deletions
diff --git a/lib/bossac/src/bossac.cpp b/lib/bossac/src/bossac.cpp
new file mode 100644
index 00000000..450d0fa1
--- /dev/null
+++ b/lib/bossac/src/bossac.cpp
@@ -0,0 +1,489 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include <string>
+#include <exception>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/time.h>
+
+#include "CmdOpts.h"
+#include "Samba.h"
+#include "PortFactory.h"
+#include "Device.h"
+#include "Flasher.h"
+
+using namespace std;
+
+class BossaConfig
+{
+public:
+ BossaConfig();
+ virtual ~BossaConfig() {}
+
+ bool erase;
+ bool write;
+ bool read;
+ bool verify;
+ bool offset;
+ bool reset;
+ bool port;
+ bool boot;
+ bool bor;
+ bool bod;
+ bool lock;
+ bool unlock;
+ bool security;
+ bool info;
+ bool debug;
+ bool help;
+ bool usbPort;
+ bool arduinoErase;
+
+ int readArg;
+ int offsetArg;
+ string portArg;
+ int bootArg;
+ int bodArg;
+ int borArg;
+ string lockArg;
+ string unlockArg;
+ bool usbPortArg;
+};
+
+BossaConfig::BossaConfig()
+{
+ erase = false;
+ write = false;
+ read = false;
+ verify = false;
+ port = false;
+ boot = false;
+ bod = false;
+ bor = false;
+ lock = false;
+ security = false;
+ info = false;
+ help = false;
+ usbPort = false;
+ arduinoErase = false;
+
+ readArg = 0;
+ offsetArg = 0;
+ bootArg = 1;
+ bodArg = 1;
+ borArg = 1;
+ usbPortArg=1;
+
+ reset = false;
+}
+
+class BossaObserver : public FlasherObserver
+{
+public:
+ BossaObserver() : _lastTicks(-1) {}
+ virtual ~BossaObserver() {}
+
+ virtual void onStatus(const char *message, ...);
+ virtual void onProgress(int num, int div);
+private:
+ int _lastTicks;
+};
+
+void
+BossaObserver::onStatus(const char *message, ...)
+{
+ va_list ap;
+
+ va_start(ap, message);
+ vprintf(message, ap);
+ va_end(ap);
+}
+
+void
+BossaObserver::onProgress(int num, int div)
+{
+ int ticks;
+ int bars = 30;
+
+ ticks = num * bars / div;
+
+ if (ticks == _lastTicks)
+ return;
+
+ printf("\r[");
+ while (ticks-- > 0)
+ {
+ putchar('=');
+ bars--;
+ }
+ while (bars-- > 0)
+ {
+ putchar(' ');
+ }
+ printf("] %d%% (%d/%d pages)", num * 100 / div, num, div);
+ fflush(stdout);
+
+ _lastTicks = 0;
+}
+
+static BossaConfig config;
+static Option opts[] =
+{
+ {
+ 'e', "erase", &config.erase,
+ { ArgNone },
+ "erase the entire flash starting at the offset"
+ },
+ {
+ 'w', "write", &config.write,
+ { ArgNone },
+ "write FILE to the flash; accelerated when\n"
+ "combined with erase option"
+ },
+ {
+ 'r', "read", &config.read,
+ { ArgOptional, ArgInt, "SIZE", { &config.readArg } },
+ "read SIZE from flash and store in FILE;\n"
+ "read entire flash if SIZE not specified"
+ },
+ {
+ 'v', "verify", &config.verify,
+ { ArgNone },
+ "verify FILE matches flash contents"
+ },
+ {
+ 'o', "offset", &config.offset,
+ { ArgRequired, ArgInt, "OFFSET", { &config.offsetArg } },
+ "start erase/write/read/verify operation at flash OFFSET;\n"
+ "OFFSET must be aligned to a flash page boundary"
+ },
+ {
+ 'p', "port", &config.port,
+ { ArgRequired, ArgString, "PORT", { &config.portArg } },
+ "use serial PORT to communicate to device;\n"
+ "default behavior is to use first serial port"
+ },
+ {
+ 'b', "boot", &config.boot,
+ { ArgOptional, ArgInt, "BOOL", { &config.bootArg } },
+ "boot from ROM if BOOL is 0;\n"
+ "boot from FLASH if BOOL is 1 [default];\n"
+ "option is ignored on unsupported devices"
+ },
+ {
+ 'c', "bod", &config.bod,
+ { ArgOptional, ArgInt, "BOOL", { &config.bodArg } },
+ "no brownout detection if BOOL is 0;\n"
+ "brownout detection is on if BOOL is 1 [default]"
+ },
+ {
+ 't', "bor", &config.bor,
+ { ArgOptional, ArgInt, "BOOL", { &config.borArg } },
+ "no brownout reset if BOOL is 0;\n"
+ "brownout reset is on if BOOL is 1 [default]"
+ },
+ {
+ 'l', "lock", &config.lock,
+ { ArgOptional, ArgString, "REGION", { &config.lockArg } },
+ "lock the flash REGION as a comma-separated list;\n"
+ "lock all if not given [default]"
+ },
+ {
+ 'u', "unlock", &config.unlock,
+ { ArgOptional, ArgString, "REGION", { &config.unlockArg } },
+ "unlock the flash REGION as a comma-separated list;\n"
+ "unlock all if not given [default]"
+ },
+ {
+ 's', "security", &config.security,
+ { ArgNone },
+ "set the flash security flag"
+ },
+ {
+ 'i', "info", &config.info,
+ { ArgNone },
+ "display device information"
+ },
+ {
+ 'd', "debug", &config.debug,
+ { ArgNone },
+ "print debug messages"
+ },
+ {
+ 'h', "help", &config.help,
+ { ArgNone },
+ "display this help text"
+ },
+ {
+ 'U', "usb-port", &config.usbPort,
+ { ArgOptional, ArgInt, "BOOL", { &config.usbPortArg } },
+ "force serial port detection to USB if BOOL is 1 [default]\n"
+ "or to RS-232 if BOOL is 0"
+ },
+ {
+ 'R', "reset", &config.reset,
+ { ArgNone },
+ "reset CPU (if supported)"
+ },
+ {
+ 'a', "arduino-erase", &config.arduinoErase,
+ { ArgNone },
+ "erase and reset via Arduino 1200 baud hack"
+ }
+};
+
+int
+help(const char* program)
+{
+ fprintf(stderr, "Try '%s -h' or '%s --help' for more information\n", program, program);
+ return 1;
+}
+
+static struct timeval start_time;
+
+void
+timer_start()
+{
+ gettimeofday(&start_time, NULL);
+}
+
+float
+timer_stop()
+{
+ struct timeval end;
+ gettimeofday(&end, NULL);
+ return (end.tv_sec - start_time.tv_sec) + (end.tv_usec - start_time.tv_usec) / 1000000.0;
+}
+
+int
+main(int argc, char* argv[])
+{
+ int args;
+ char* pos;
+ CmdOpts cmd(argc, argv, sizeof(opts) / sizeof(opts[0]), opts);
+
+ if ((pos = strrchr(argv[0], '/')) || (pos = strrchr(argv[0], '\\')))
+ argv[0] = pos + 1;
+
+ if (argc <= 1)
+ {
+ fprintf(stderr, "%s: you must specify at least one option\n", argv[0]);
+ return help(argv[0]);
+ }
+
+ args = cmd.parse();
+ if (args < 0)
+ return help(argv[0]);
+
+ if (config.read && (config.write || config.verify))
+ {
+ fprintf(stderr, "%s: read option is exclusive of write or verify\n", argv[0]);
+ return help(argv[0]);
+ }
+
+ if (config.read || config.write || config.verify)
+ {
+ if (args == argc)
+ {
+ fprintf(stderr, "%s: missing file\n", argv[0]);
+ return help(argv[0]);
+ }
+ argc--;
+ }
+ if (args != argc)
+ {
+ fprintf(stderr, "%s: extra arguments found\n", argv[0]);
+ return help(argv[0]);
+ }
+
+ if (config.help)
+ {
+ printf("Usage: %s [OPTION...] [FILE]\n", argv[0]);
+ printf("Basic Open Source SAM-BA Application (BOSSA) Version " VERSION "\n"
+ "Flash programmer for Atmel SAM devices.\n"
+ "Copyright (c) 2011-2018 ShumaTech (http://www.shumatech.com)\n"
+ "\n"
+ "Examples:\n"
+ " bossac -e -w -v -b image.bin # Erase flash, write flash with image.bin,\n"
+ " # verify the write, and set boot from flash\n"
+ " bossac -r0x10000 image.bin # Read 64KB from flash and store in image.bin\n"
+ );
+ printf("\nOptions:\n");
+ cmd.usage(stdout);
+ printf("\nReport bugs to <bugs@shumatech.com>\n");
+ return 1;
+ }
+
+ try
+ {
+ Samba samba;
+ PortFactory portFactory;
+
+ if (config.debug)
+ samba.setDebug(true);
+
+ if (!config.port)
+ config.portArg = portFactory.def();
+
+ if (config.arduinoErase)
+ {
+ SerialPort::Ptr port;
+ port = portFactory.create(config.portArg, config.usbPortArg != 0);
+
+ if(!port->open(1200))
+ {
+ fprintf(stderr, "Failed to open port at 1200bps\n");
+ return 1;
+ }
+
+ port->setRTS(true);
+ port->setDTR(false);
+ port->close();
+ }
+
+ if (config.portArg.empty())
+ {
+ fprintf(stderr, "No serial ports available\n");
+ return 1;
+ }
+
+ bool res;
+ if (config.usbPort)
+ res = samba.connect(portFactory.create(config.portArg, config.usbPortArg != 0));
+ else
+ res = samba.connect(portFactory.create(config.portArg));
+ if (!res)
+ {
+ fprintf(stderr, "No device found on %s\n", config.portArg.c_str());
+ return 1;
+ }
+
+ Device device(samba);
+ device.create();
+
+ Device::FlashPtr& flash = device.getFlash();
+
+ BossaObserver observer;
+ Flasher flasher(samba, device, observer);
+
+ if (config.info)
+ {
+ FlasherInfo info;
+ flasher.info(info);
+ info.print();
+ }
+
+ if (config.unlock)
+ flasher.lock(config.unlockArg, false);
+
+ if (config.erase)
+ {
+ timer_start();
+ flasher.erase(config.offsetArg);
+ printf("\nDone in %5.3f seconds\n", timer_stop());
+ }
+
+ if (config.write)
+ {
+ timer_start();
+ flasher.write(argv[args], config.offsetArg);
+ printf("\nDone in %5.3f seconds\n", timer_stop());
+ }
+
+ if (config.verify)
+ {
+ uint32_t pageErrors;
+ uint32_t totalErrors;
+
+ timer_start();
+ if (!flasher.verify(argv[args], pageErrors, totalErrors, config.offsetArg))
+ {
+ printf("\nVerify failed\nPage errors: %d\nByte errors: %d\n",
+ pageErrors, totalErrors);
+ return 2;
+ }
+
+ printf("\nVerify successful\nDone in %5.3f seconds\n", timer_stop());
+ }
+
+ if (config.read)
+ {
+ timer_start();
+ flasher.read(argv[args], config.readArg, config.offsetArg);
+ printf("\nDone in %5.3f seconds\n", timer_stop());
+ }
+
+ if (config.boot)
+ {
+ printf("Set boot flash %s\n", config.bootArg ? "true" : "false");
+ flash->setBootFlash(config.bootArg);
+ }
+
+ if (config.bod)
+ {
+ printf("Set brownout detect %s\n", config.bodArg ? "true" : "false");
+ flash->setBod(config.bodArg);
+ }
+
+ if (config.bor)
+ {
+ printf("Set brownout reset %s\n", config.borArg ? "true" : "false");
+ flash->setBor(config.borArg);
+ }
+
+ if (config.security)
+ {
+ printf("Set security\n");
+ flash->setSecurity();
+ }
+
+ if (config.lock)
+ flasher.lock(config.lockArg, true);
+
+ flash->writeOptions();
+
+ if (config.reset)
+ device.reset();
+ }
+ catch (exception& e)
+ {
+ fprintf(stderr, "\n%s\n", e.what());
+ return 1;
+ }
+ catch(...)
+ {
+ fprintf(stderr, "\nUnhandled exception\n");
+ return 1;
+ }
+
+ return 0;
+}
+