diff --git a/arduino101load/arduino101load b/arduino101load/arduino101load index 8d567d6..fc07d4b 100755 Binary files a/arduino101load/arduino101load and b/arduino101load/arduino101load differ diff --git a/arduino101load/deploy.sh b/arduino101load/deploy.sh new file mode 100755 index 0000000..3bbf960 --- /dev/null +++ b/arduino101load/deploy.sh @@ -0,0 +1,43 @@ +#!/bin/bash -xe + +VERSION=`cat main.go| grep "const Version" |cut -f4 -d " " | tr -d '"'` + +#Remember to set GOROOT accordingly with your installation + +export GOPATH=$PWD + +declare -a target_folders=("linux_amd64" "linux_386" "linux_arm" "darwin_amd64" "windows_386") + +rm -rf distrib +mkdir distrib + +package_index=`cat package_index.template | sed s/%%VERSION%%/${VERSION}/` + +for folder in "${target_folders[@]}" +do + rm -rf arduino101load* + rm -rf bin + mkdir bin + IFS=_ read -a fields <<< $folder + GOOS=${fields[0]} GOARCH=${fields[1]} go build + FILENAME=arduino101load-${VERSION}-${folder}.tar.bz2 + cp -r arduino101load* firmwares/ bin + tar cjvf ${FILENAME} bin/ + T_OS=`echo ${folder} | awk '{print toupper($0)}'` + SHASUM=`sha256sum ${FILENAME} | cut -f1 -d" "` + SIZE=`stat --printf="%s" ${FILENAME}` + package_index=`echo $package_index | + sed s/%%FILENAME_${T_OS}%%/${FILENAME}/ | + sed s/%%FILENAME_${T_OS}%%/${FILENAME}/ | + sed s/%%SIZE_${T_OS}%%/${SIZE}/ | + sed s/%%SHA_${T_OS}%%/${SHASUM}/` + + mv ${FILENAME} distrib/ +done + +set +x + +echo ================== CUT ME HERE ===================== + +echo ${package_index} | python -m json.tool + diff --git a/arduino101load/firmwares/1.0.8/ble_core.bin b/arduino101load/firmwares/1.0.8/ble_core.bin new file mode 100644 index 0000000..d037291 Binary files /dev/null and b/arduino101load/firmwares/1.0.8/ble_core.bin differ diff --git a/arduino101load/firmwares/1.0.8/quark.bin b/arduino101load/firmwares/1.0.8/quark.bin new file mode 100644 index 0000000..308deca Binary files /dev/null and b/arduino101load/firmwares/1.0.8/quark.bin differ diff --git a/arduino101load/firmwares/2.0.0/ble_core.bin b/arduino101load/firmwares/2.0.0/ble_core.bin new file mode 100644 index 0000000..93c0395 Binary files /dev/null and b/arduino101load/firmwares/2.0.0/ble_core.bin differ diff --git a/arduino101load/firmwares/2.0.0/quark.bin b/arduino101load/firmwares/2.0.0/quark.bin new file mode 100644 index 0000000..308deca Binary files /dev/null and b/arduino101load/firmwares/2.0.0/quark.bin differ diff --git a/arduino101load/main.go b/arduino101load/main.go index c6a343a..09c8484 100644 --- a/arduino101load/main.go +++ b/arduino101load/main.go @@ -2,84 +2,99 @@ package main import ( "bufio" + "flag" "fmt" + "github.com/kardianos/osext" "github.com/mattn/go-shellwords" + "github.com/tj/go-spin" "io" "io/ioutil" "os" "os/exec" "path/filepath" "runtime" + "strconv" "strings" "time" ) -var verbose bool +var ( + verbose = flag.Bool("v", false, "Show verbose logging") + quiet = flag.Bool("q", true, "Show quiet logging") + force = flag.Bool("f", false, "Force firmware update") + copier = flag.Bool("c", false, "Copy bin_file to bin_save") + core = flag.String("core", "", "Core version") + from = flag.String("from", "", "Original file location") + to = flag.String("to", "", "Save file location") + dfu_path = flag.String("dfu", "", "Location of dfu-util binaries") + bin_file_name = flag.String("bin", "", "Location of sketch binary") + com_port = flag.String("port", "", "Upload serial port") + ble_compliance_string = flag.String("ble_fw_str", "", "BLE FW ID string") + ble_compliance_offset = flag.Int("ble_fw_pos", 0, "BLE FW ID offset") + rtos_compliance_string = flag.String("rtos_fw_str", "", "RTOS FW ID string") + rtos_compliance_offset = flag.Int("rtos_fw_pos", 0, "RTOS FW ID offset") +) + +const Version = "2.0.0" + +const dfu_flags = "-d,8087:0ABA" +const rtos_firmware = "quark.bin" +const ble_firmware = "ble_core.bin" func PrintlnVerbose(a ...interface{}) { - if verbose { + if *verbose { fmt.Println(a...) } } -func main_load(args []string) { +func PrintVerbose(a ...interface{}) { + if *verbose { + fmt.Print(a...) + } +} - // ARG 1: Path to binaries - // ARG 2: BIN File to download - // ARG 3: TTY port to use. - // ARG 4: quiet/verbose - // path may contain \ need to change all to / +func main_load() { - if len(args) < 4 { - fmt.Println("Not enough arguments") + if *dfu_path == "" { + fmt.Println("Need to specify dfu-util location") os.Exit(1) } - bin_path := args[0] - dfu := bin_path + "/dfu-util" - dfu = filepath.ToSlash(dfu) - dfu_flags := "-d,8087:0ABA" - - bin_file_name := args[1] - - com_port := args[2] - verbosity := args[3] - - ble_compliance_string := "" - ble_compliance_offset := "" - if len(args) >= 5 { - // Called by post 1.0.6 platform.txt - ble_compliance_string = args[4] - ble_compliance_offset = args[5] + if *bin_file_name == "" && *force == false { + fmt.Println("Need to specify a binary location or force FW update") + os.Exit(1) } - if verbosity == "quiet" { - verbose = false - } else { - verbose = true - } + // Remove ""s from the strings + *dfu_path = strings.Replace(*dfu_path, "\"", "", -1) + *bin_file_name = strings.Replace(*bin_file_name, "\"", "", -1) + *ble_compliance_string = strings.Replace(*ble_compliance_string, "\"", "", -1) + *rtos_compliance_string = strings.Replace(*rtos_compliance_string, "\"", "", -1) + + dfu := *dfu_path + "/dfu-util" + dfu = filepath.ToSlash(dfu) - PrintlnVerbose("Args to shell:", args) - PrintlnVerbose("Serial Port: " + com_port) - PrintlnVerbose("BIN FILE " + bin_file_name) + PrintlnVerbose("Serial Port: " + *com_port) + PrintlnVerbose("BIN FILE " + *bin_file_name) counter := 0 board_found := false if runtime.GOOS == "darwin" { library_path := os.Getenv("DYLD_LIBRARY_PATH") - if !strings.Contains(library_path, bin_path) { - os.Setenv("DYLD_LIBRARY_PATH", bin_path+":"+library_path) + if !strings.Contains(library_path, *dfu_path) { + os.Setenv("DYLD_LIBRARY_PATH", *dfu_path+":"+library_path) } } dfu_search_command := []string{dfu, dfu_flags, "-l"} + var err error for counter < 100 && board_found == false { if counter%10 == 0 { PrintlnVerbose("Waiting for device...") } - err, found, _ := launchCommandAndWaitForOutput(dfu_search_command, "sensor_core", false) + err, found, _ := launchCommandAndWaitForOutput(dfu_search_command, "sensor_core", false, false) if err != nil { fmt.Println(err) os.Exit(1) @@ -98,11 +113,14 @@ func main_load(args []string) { } if board_found == false { - fmt.Println("ERROR: Timed out waiting for Arduino 101 on " + com_port) + fmt.Println("ERROR: Timed out waiting for Arduino 101 on " + *com_port) os.Exit(1) } - if ble_compliance_string != "" { + needUpdateRTOS := false + needUpdateBLE := false + + if *ble_compliance_string != "" { // obtain a temporary filename tmpfile, _ := ioutil.TempFile(os.TempDir(), "dfu") @@ -112,7 +130,7 @@ func main_load(args []string) { // reset DFU interface counter dfu_reset_command := []string{dfu, dfu_flags, "-U", tmpfile.Name(), "--alt", "8", "-K", "1"} - err, _, _ := launchCommandAndWaitForOutput(dfu_reset_command, "", false) + err, _, _ := launchCommandAndWaitForOutput(dfu_reset_command, "", false, false) if err != nil { fmt.Println(err) os.Exit(1) @@ -121,39 +139,116 @@ func main_load(args []string) { os.Remove(tmpfile.Name()) // download a piece of BLE firmware - dfu_ble_dump_command := []string{dfu, dfu_flags, "-U", tmpfile.Name(), "--alt", "8", "-K", ble_compliance_offset} + dfu_ble_dump_command := []string{dfu, dfu_flags, "-U", tmpfile.Name(), "--alt", "8", "-K", strconv.Itoa(*ble_compliance_offset)} + + err, _, _ = launchCommandAndWaitForOutput(dfu_ble_dump_command, "", false, false) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // check for BLE library compliance + PrintlnVerbose("Verifying BLE version:", *ble_compliance_string) + found := searchVersionInDFU(tmpfile.Name(), *ble_compliance_string) + + // remove the temporary file + os.Remove(tmpfile.Name()) + + if !found { + needUpdateBLE = true + } else { + PrintlnVerbose("BLE version: verified") + } + } + + if *rtos_compliance_string != "" { + + // obtain a temporary filename + tmpfile, _ := ioutil.TempFile(os.TempDir(), "dfu") + tmpfile.Close() + os.Remove(tmpfile.Name()) + + // reset DFU interface counter + dfu_reset_command := []string{dfu, dfu_flags, "-U", tmpfile.Name(), "--alt", "2", "-K", "1"} + + err, _, _ := launchCommandAndWaitForOutput(dfu_reset_command, "", false, false) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + os.Remove(tmpfile.Name()) + + // download a piece of RTOS firmware + dfu_rtos_dump_command := []string{dfu, dfu_flags, "-U", tmpfile.Name(), "--alt", "2", "-K", strconv.Itoa(*rtos_compliance_offset)} - err, _, _ = launchCommandAndWaitForOutput(dfu_ble_dump_command, "", false) + err, _, _ = launchCommandAndWaitForOutput(dfu_rtos_dump_command, "", false, false) if err != nil { fmt.Println(err) os.Exit(1) } // check for BLE library compliance - PrintlnVerbose("Verifying BLE version:", ble_compliance_string) - found := searchBLEversionInDFU(tmpfile.Name(), ble_compliance_string) + PrintlnVerbose("Verifying RTOS version:", *rtos_compliance_string) + found := searchVersionInDFU(tmpfile.Name(), *rtos_compliance_string) // remove the temporary file os.Remove(tmpfile.Name()) if !found { - fmt.Println("!! BLE firmware version is not in sync with CurieBLE library !!") - fmt.Println("* Set Programmer to \"Arduino/Genuino 101 Firmware Updater\"") - fmt.Println("* Update it using \"Burn Bootloader\" menu") + needUpdateRTOS = true + } else { + PrintlnVerbose("RTOS version: verified") + } + } + + executablePath, _ := osext.ExecutableFolder() + firmwarePath := executablePath + "/firmwares/" + *core + "/" + + if needUpdateBLE || *force == true { + + // flash current BLE firmware to partition 8 + dfu_ble_flash_command := []string{dfu, dfu_flags, "-D", firmwarePath + ble_firmware, "--alt", "8"} + + fmt.Println("ATTENTION: BLE firmware is being flashed") + fmt.Println("DO NOT DISCONNECT THE BOARD") + + err, _, _ = launchCommandAndWaitForOutput(dfu_ble_flash_command, "", true, true) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } + + if needUpdateRTOS || *force == true { + + // flash current RTOS firmware to partition 2 + dfu_rtos_flash_command := []string{dfu, dfu_flags, "-D", firmwarePath + rtos_firmware, "--alt", "2"} + + fmt.Println("ATTENTION: RTOS firmware is being flashed") + fmt.Println("DO NOT DISCONNECT THE BOARD") + + err, _, _ = launchCommandAndWaitForOutput(dfu_rtos_flash_command, "", true, true) + if err != nil { + fmt.Println(err) os.Exit(1) } - PrintlnVerbose("BLE version: verified") + } + + // Finally flash the sketch + if *bin_file_name == "" { + os.Exit(0) } - dfu_download := []string{dfu, dfu_flags, "-D", bin_file_name, "-v", "--alt", "7", "-R"} - err, _, _ := launchCommandAndWaitForOutput(dfu_download, "", true) + dfu_download := []string{dfu, dfu_flags, "-D", *bin_file_name, "-v", "--alt", "7", "-R"} + err, _, _ = launchCommandAndWaitForOutput(dfu_download, "", true, false) if err == nil { fmt.Println("SUCCESS: Sketch will execute in about 5 seconds.") os.Exit(0) } else { - fmt.Println("ERROR: Upload failed on " + com_port) + fmt.Println("ERROR: Upload failed on " + *com_port) os.Exit(1) } } @@ -165,7 +260,7 @@ func main_debug(args []string) { os.Exit(1) } - verbose = true + *verbose = true type Command struct { command string @@ -193,7 +288,7 @@ func main_debug(args []string) { cmd, _ := shellwords.Parse(command.command) fmt.Println(cmd) if command.background == false { - err, _, _ = launchCommandAndWaitForOutput(cmd, "", true) + err, _, _ = launchCommandAndWaitForOutput(cmd, "", true, false) } else { err, _ = launchCommandBackground(cmd, "", true) } @@ -206,51 +301,108 @@ func main_debug(args []string) { } func main() { - name := os.Args[0] - args := os.Args[1:] + name := filepath.Base(os.Args[0]) + + flag.Parse() + + PrintlnVerbose(name + " " + Version + " - compiled with " + runtime.Version()) + + if *copier { + if *from == "" || *to == "" { + fmt.Println("ERROR: need -from and -to arguments") + os.Exit(1) + } + *from = strings.Replace(*from, "\"", "", -1) + *to = strings.Replace(*to, "\"", "", -1) + copy(*from, *to) + os.Exit(0) + } if strings.Contains(name, "load") { fmt.Println("Starting download script...") - main_load(args) + main_load() } if strings.Contains(name, "debug") { fmt.Println("Starting debug script...") - main_debug(args) + main_debug(os.Args[1:]) } fmt.Println("Wrong executable name") os.Exit(1) } -func searchBLEversionInDFU(file string, string_to_search string) bool { +// Copy a file +func copy(source, destination string) { + // Open original file + originalFile, err := os.Open(source) + if err != nil { + os.Exit(1) + } + defer originalFile.Close() + + // Create new file + newFile, err := os.Create(destination) + if err != nil { + os.Exit(1) + } + defer newFile.Close() + + // Copy the bytes to destination from source + _, err = io.Copy(newFile, originalFile) + if err != nil { + os.Exit(1) + } + + // Commit the file contents + // Flushes memory to disk + err = newFile.Sync() + if err != nil { + os.Exit(1) + } +} + +func searchVersionInDFU(file string, string_to_search string) bool { read, _ := ioutil.ReadFile(file) return strings.Contains(string(read), string_to_search) } -func launchCommandAndWaitForOutput(command []string, stringToSearch string, print_output bool) (error, bool, string) { +func launchCommandAndWaitForOutput(command []string, stringToSearch string, print_output bool, show_spinner bool) (error, bool, string) { oscmd := exec.Command(command[0], command[1:]...) tellCommandNotToSpawnShell(oscmd) stdout, _ := oscmd.StdoutPipe() stderr, _ := oscmd.StderrPipe() - multi := io.MultiReader(stderr, stdout) + multi := io.MultiReader(stdout, stderr) + + s := spin.New() + s.Set(spin.Spin1) + + if print_output && *verbose { + oscmd.Stdout = os.Stdout + oscmd.Stderr = os.Stderr + } err := oscmd.Start() in := bufio.NewScanner(multi) - in.Split(bufio.ScanLines) + in.Split(bufio.ScanRunes) found := false out := "" for in.Scan() { - if print_output { - PrintlnVerbose(in.Text()) + + if show_spinner { + fmt.Printf("\r %s", s.Next()) } - out += in.Text() + "\n" + + out += in.Text() if stringToSearch != "" { - if strings.Contains(in.Text(), stringToSearch) { + if strings.Contains(out, stringToSearch) { found = true } } } err = oscmd.Wait() + if show_spinner { + fmt.Println("") + } return err, found, out } diff --git a/arduino101load/package_index.template b/arduino101load/package_index.template new file mode 100644 index 0000000..9badc5e --- /dev/null +++ b/arduino101load/package_index.template @@ -0,0 +1,41 @@ + { + "name": "arduino101load", + "version": "%%VERSION%%", + "systems": [ + { + "host": "i386-apple-darwin11", + "url": "http://downloads.arduino.cc/tools/%%FILENAME_DARWIN_AMD64%%", + "archiveFileName": "%%FILENAME_DARWIN_AMD64%%", + "size": "%%SIZE_DARWIN_AMD64%%", + "checksum": "SHA-256:%%SHA_DARWIN_AMD64%%" + }, + { + "host": "arm-linux-gnueabihf", + "url": "http://downloads.arduino.cc/tools/%%FILENAME_LINUX_ARM%%", + "archiveFileName": "%%FILENAME_LINUX_ARM%%", + "size": "%%SIZE_LINUX_ARM%%", + "checksum": "SHA-256:%%SHA_LINUX_ARM%%" + }, + { + "host": "x86_64-linux-gnu", + "url": "http://downloads.arduino.cc/tools/%%FILENAME_LINUX_AMD64%%", + "archiveFileName": "%%FILENAME_LINUX_AMD64%%", + "size": "%%SIZE_LINUX_AMD64%%", + "checksum": "SHA-256:%%SHA_LINUX_AMD64%%" + }, + { + "host": "i686-linux-gnu", + "url": "http://downloads.arduino.cc/tools/%%FILENAME_LINUX_386%%", + "archiveFileName": "%%FILENAME_LINUX_386%%", + "size": "%%SIZE_LINUX_386%%", + "checksum": "SHA-256:%%SHA_LINUX_386%%" + }, + { + "host": "i686-mingw32", + "url": "http://downloads.arduino.cc/tools/%%FILENAME_WINDOWS_386%%", + "archiveFileName": "%%FILENAME_WINDOWS_386%%", + "size": "%%SIZE_WINDOWS_386%%", + "checksum": "SHA-256:%%SHA_WINDOWS_386%%" + } + ] + }