From cc83916c712204e6e23e1917f02b5cd53fc3e595 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 18 Nov 2016 21:16:15 +0100 Subject: [PATCH 1/2] Produce merged sketch + bootloader on bin only platforms --- constants/constants.go | 1 + merge_sketch_with_bootloader.go | 89 ++++++++++++++++++++++++++++----- 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/constants/constants.go b/constants/constants.go index d83ee273..242f7712 100644 --- a/constants/constants.go +++ b/constants/constants.go @@ -47,6 +47,7 @@ const BUILD_PROPERTIES_BUILD_PROJECT_NAME = "build.project_name" const BUILD_PROPERTIES_BUILD_SYSTEM_PATH = "build.system.path" const BUILD_PROPERTIES_BUILD_VARIANT = "build.variant" const BUILD_PROPERTIES_BUILD_VARIANT_PATH = "build.variant.path" +const BUILD_PROPERTIES_BUILD_LDSCRIPT = "build.ldscript" const BUILD_PROPERTIES_COMPILER_C_ELF_FLAGS = "compiler.c.elf.flags" const BUILD_PROPERTIES_COMPILER_C_ELF_EXTRAFLAGS = "compiler.c.elf.extra_flags" const BUILD_PROPERTIES_COMPILER_CPP_FLAGS = "compiler.cpp.flags" diff --git a/merge_sketch_with_bootloader.go b/merge_sketch_with_bootloader.go index ebefa77e..88b9e64c 100644 --- a/merge_sketch_with_bootloader.go +++ b/merge_sketch_with_bootloader.go @@ -30,13 +30,15 @@ package builder import ( + "io/ioutil" + "os" + "path/filepath" + "strings" + "github.com/arduino/arduino-builder/constants" "github.com/arduino/arduino-builder/i18n" "github.com/arduino/arduino-builder/types" "github.com/arduino/arduino-builder/utils" - "os" - "path/filepath" - "strings" ) type MergeSketchWithBootloader struct{} @@ -52,15 +54,25 @@ func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error { sketchFileName := filepath.Base(sketch.MainFile.Name) logger := ctx.GetLogger() - sketchInBuildPath := filepath.Join(buildPath, sketchFileName+".hex") - sketchInSubfolder := filepath.Join(buildPath, constants.FOLDER_SKETCH, sketchFileName+".hex") + sketchInBuildPath := filepath.Join(buildPath, sketchFileName) + sketchInSubfolder := filepath.Join(buildPath, constants.FOLDER_SKETCH, sketchFileName) + availableExtensions := []string{".hex", ".bin"} builtSketchPath := constants.EMPTY_STRING - if _, err := os.Stat(sketchInBuildPath); err == nil { - builtSketchPath = sketchInBuildPath - } else if _, err := os.Stat(sketchInSubfolder); err == nil { - builtSketchPath = sketchInSubfolder - } else { + + extension := "" + + for _, extension = range availableExtensions { + if _, err := os.Stat(sketchInBuildPath + extension); err == nil { + builtSketchPath = sketchInBuildPath + extension + break + } else if _, err := os.Stat(sketchInSubfolder + extension); err == nil { + builtSketchPath = sketchInSubfolder + extension + break + } + } + + if builtSketchPath == constants.EMPTY_STRING { return nil } @@ -78,9 +90,17 @@ func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error { return nil } - mergedSketchPath := filepath.Join(filepath.Dir(builtSketchPath), sketchFileName+".with_bootloader.hex") + mergedSketchPath := filepath.Join(filepath.Dir(builtSketchPath), sketchFileName+".with_bootloader"+extension) - err := merge(builtSketchPath, bootloaderPath, mergedSketchPath) + var err error + if extension == ".hex" { + err = mergeHex(builtSketchPath, bootloaderPath, mergedSketchPath) + } else { + ldscript := buildProperties[constants.BUILD_PROPERTIES_BUILD_LDSCRIPT] + variantFolder := buildProperties[constants.BUILD_PROPERTIES_BUILD_VARIANT_PATH] + ldscriptPath := filepath.Join(variantFolder, ldscript) + err = mergeBin(builtSketchPath, ldscriptPath, bootloaderPath, mergedSketchPath) + } return err } @@ -127,7 +147,7 @@ func extractActualBootloader(bootloader []string) []string { return realBootloader } -func merge(builtSketchPath, bootloaderPath, mergedSketchPath string) error { +func mergeHex(builtSketchPath, bootloaderPath, mergedSketchPath string) error { sketch, err := utils.ReadFileToRows(builtSketchPath) if err != nil { return i18n.WrapError(err) @@ -147,3 +167,46 @@ func merge(builtSketchPath, bootloaderPath, mergedSketchPath string) error { return utils.WriteFile(mergedSketchPath, strings.Join(sketch, "\n")) } + +func mergeBin(builtSketchPath, ldscriptPath, bootloaderPath, mergedSketchPath string) error { + // 0xFF means empty + // only works if the bootloader is at the beginning of the flash + // only works if the flash address space is mapped at 0x00 + + // METHOD 1: (non appliable to most architectures) + // remove all comments from linkerscript + // find NAMESPACE of .text section -> FLASH + // find ORIGIN of FLASH section + + // METHOD 2: + // Round the bootloader to the next "power of 2" bytes boundary + + // generate a byte[FLASH] full of 0xFF and bitwise OR with bootloader BIN + // merge this slice with sketch BIN + + bootloader, _ := ioutil.ReadFile(bootloaderPath) + sketch, _ := ioutil.ReadFile(builtSketchPath) + + paddedBootloaderLen := nextPowerOf2(len(bootloader)) + + padding := make([]byte, paddedBootloaderLen-len(bootloader)) + for i, _ := range padding { + padding[i] = 0xFF + } + + bootloader = append(bootloader, padding...) + sketch = append(bootloader, sketch...) + + return ioutil.WriteFile(mergedSketchPath, sketch, 0644) +} + +func nextPowerOf2(v int) int { + v-- + v |= v >> 1 + v |= v >> 2 + v |= v >> 4 + v |= v >> 8 + v |= v >> 16 + v++ + return v +} From c2e408f4938600fe5e7f2cab8498272d956d30c5 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 18 Nov 2016 22:00:08 +0100 Subject: [PATCH 2/2] Fallback searching for an hex bootloader if hex sketch selected --- merge_sketch_with_bootloader.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/merge_sketch_with_bootloader.go b/merge_sketch_with_bootloader.go index 88b9e64c..62be77b4 100644 --- a/merge_sketch_with_bootloader.go +++ b/merge_sketch_with_bootloader.go @@ -92,6 +92,17 @@ func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error { mergedSketchPath := filepath.Join(filepath.Dir(builtSketchPath), sketchFileName+".with_bootloader"+extension) + // make sure that sketch and bootloader have the same format + + if (!strings.HasSuffix(bootloaderPath, extension)) { + // oops, need to retrieve the .hex version of the bootloader + if _, err := os.Stat(strings.TrimSuffix(bootloaderPath, ".bin") + extension); err != nil { + return nil + } else { + bootloaderPath = strings.TrimSuffix(bootloaderPath, ".bin") + extension + } + } + var err error if extension == ".hex" { err = mergeHex(builtSketchPath, bootloaderPath, mergedSketchPath)