Skip to content

Commit cc83916

Browse files
facchinmcmaglie
authored andcommitted
Produce merged sketch + bootloader on bin only platforms
1 parent 0d042f0 commit cc83916

File tree

2 files changed

+77
-13
lines changed

2 files changed

+77
-13
lines changed

constants/constants.go

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const BUILD_PROPERTIES_BUILD_PROJECT_NAME = "build.project_name"
4747
const BUILD_PROPERTIES_BUILD_SYSTEM_PATH = "build.system.path"
4848
const BUILD_PROPERTIES_BUILD_VARIANT = "build.variant"
4949
const BUILD_PROPERTIES_BUILD_VARIANT_PATH = "build.variant.path"
50+
const BUILD_PROPERTIES_BUILD_LDSCRIPT = "build.ldscript"
5051
const BUILD_PROPERTIES_COMPILER_C_ELF_FLAGS = "compiler.c.elf.flags"
5152
const BUILD_PROPERTIES_COMPILER_C_ELF_EXTRAFLAGS = "compiler.c.elf.extra_flags"
5253
const BUILD_PROPERTIES_COMPILER_CPP_FLAGS = "compiler.cpp.flags"

merge_sketch_with_bootloader.go

+76-13
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@
3030
package builder
3131

3232
import (
33+
"io/ioutil"
34+
"os"
35+
"path/filepath"
36+
"strings"
37+
3338
"github.com/arduino/arduino-builder/constants"
3439
"github.com/arduino/arduino-builder/i18n"
3540
"github.com/arduino/arduino-builder/types"
3641
"github.com/arduino/arduino-builder/utils"
37-
"os"
38-
"path/filepath"
39-
"strings"
4042
)
4143

4244
type MergeSketchWithBootloader struct{}
@@ -52,15 +54,25 @@ func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error {
5254
sketchFileName := filepath.Base(sketch.MainFile.Name)
5355
logger := ctx.GetLogger()
5456

55-
sketchInBuildPath := filepath.Join(buildPath, sketchFileName+".hex")
56-
sketchInSubfolder := filepath.Join(buildPath, constants.FOLDER_SKETCH, sketchFileName+".hex")
57+
sketchInBuildPath := filepath.Join(buildPath, sketchFileName)
58+
sketchInSubfolder := filepath.Join(buildPath, constants.FOLDER_SKETCH, sketchFileName)
5759

60+
availableExtensions := []string{".hex", ".bin"}
5861
builtSketchPath := constants.EMPTY_STRING
59-
if _, err := os.Stat(sketchInBuildPath); err == nil {
60-
builtSketchPath = sketchInBuildPath
61-
} else if _, err := os.Stat(sketchInSubfolder); err == nil {
62-
builtSketchPath = sketchInSubfolder
63-
} else {
62+
63+
extension := ""
64+
65+
for _, extension = range availableExtensions {
66+
if _, err := os.Stat(sketchInBuildPath + extension); err == nil {
67+
builtSketchPath = sketchInBuildPath + extension
68+
break
69+
} else if _, err := os.Stat(sketchInSubfolder + extension); err == nil {
70+
builtSketchPath = sketchInSubfolder + extension
71+
break
72+
}
73+
}
74+
75+
if builtSketchPath == constants.EMPTY_STRING {
6476
return nil
6577
}
6678

@@ -78,9 +90,17 @@ func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error {
7890
return nil
7991
}
8092

81-
mergedSketchPath := filepath.Join(filepath.Dir(builtSketchPath), sketchFileName+".with_bootloader.hex")
93+
mergedSketchPath := filepath.Join(filepath.Dir(builtSketchPath), sketchFileName+".with_bootloader"+extension)
8294

83-
err := merge(builtSketchPath, bootloaderPath, mergedSketchPath)
95+
var err error
96+
if extension == ".hex" {
97+
err = mergeHex(builtSketchPath, bootloaderPath, mergedSketchPath)
98+
} else {
99+
ldscript := buildProperties[constants.BUILD_PROPERTIES_BUILD_LDSCRIPT]
100+
variantFolder := buildProperties[constants.BUILD_PROPERTIES_BUILD_VARIANT_PATH]
101+
ldscriptPath := filepath.Join(variantFolder, ldscript)
102+
err = mergeBin(builtSketchPath, ldscriptPath, bootloaderPath, mergedSketchPath)
103+
}
84104

85105
return err
86106
}
@@ -127,7 +147,7 @@ func extractActualBootloader(bootloader []string) []string {
127147
return realBootloader
128148
}
129149

130-
func merge(builtSketchPath, bootloaderPath, mergedSketchPath string) error {
150+
func mergeHex(builtSketchPath, bootloaderPath, mergedSketchPath string) error {
131151
sketch, err := utils.ReadFileToRows(builtSketchPath)
132152
if err != nil {
133153
return i18n.WrapError(err)
@@ -147,3 +167,46 @@ func merge(builtSketchPath, bootloaderPath, mergedSketchPath string) error {
147167

148168
return utils.WriteFile(mergedSketchPath, strings.Join(sketch, "\n"))
149169
}
170+
171+
func mergeBin(builtSketchPath, ldscriptPath, bootloaderPath, mergedSketchPath string) error {
172+
// 0xFF means empty
173+
// only works if the bootloader is at the beginning of the flash
174+
// only works if the flash address space is mapped at 0x00
175+
176+
// METHOD 1: (non appliable to most architectures)
177+
// remove all comments from linkerscript
178+
// find NAMESPACE of .text section -> FLASH
179+
// find ORIGIN of FLASH section
180+
181+
// METHOD 2:
182+
// Round the bootloader to the next "power of 2" bytes boundary
183+
184+
// generate a byte[FLASH] full of 0xFF and bitwise OR with bootloader BIN
185+
// merge this slice with sketch BIN
186+
187+
bootloader, _ := ioutil.ReadFile(bootloaderPath)
188+
sketch, _ := ioutil.ReadFile(builtSketchPath)
189+
190+
paddedBootloaderLen := nextPowerOf2(len(bootloader))
191+
192+
padding := make([]byte, paddedBootloaderLen-len(bootloader))
193+
for i, _ := range padding {
194+
padding[i] = 0xFF
195+
}
196+
197+
bootloader = append(bootloader, padding...)
198+
sketch = append(bootloader, sketch...)
199+
200+
return ioutil.WriteFile(mergedSketchPath, sketch, 0644)
201+
}
202+
203+
func nextPowerOf2(v int) int {
204+
v--
205+
v |= v >> 1
206+
v |= v >> 2
207+
v |= v >> 4
208+
v |= v >> 8
209+
v |= v >> 16
210+
v++
211+
return v
212+
}

0 commit comments

Comments
 (0)