Skip to content

Commit 352362d

Browse files
make MergeSketchWithBootloader a method recevier of arduino/builder
1 parent 9cf492b commit 352362d

File tree

4 files changed

+134
-191
lines changed

4 files changed

+134
-191
lines changed

arduino/builder/sketch.go

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ package builder
1818
import (
1919
"bytes"
2020
"fmt"
21+
"math"
2122
"regexp"
23+
"strconv"
24+
"strings"
2225

2326
"github.com/arduino/arduino-cli/arduino/builder/compilation"
2427
"github.com/arduino/arduino-cli/arduino/builder/cpp"
@@ -29,6 +32,7 @@ import (
2932
f "github.com/arduino/arduino-cli/internal/algorithms"
3033
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
3134
"github.com/arduino/go-paths-helper"
35+
"github.com/marcinbor85/gohex"
3236

3337
"github.com/pkg/errors"
3438
)
@@ -221,3 +225,128 @@ func (b *Builder) BuildSketch(
221225

222226
return sketchObjectFiles, nil
223227
}
228+
229+
// MergeSketchWithBootloader fixdoc
230+
func (b *Builder) MergeSketchWithBootloader(onlyUpdateCompilationDatabase bool) error {
231+
if onlyUpdateCompilationDatabase {
232+
return nil
233+
}
234+
235+
if !b.buildProperties.ContainsKey("bootloader.noblink") && !b.buildProperties.ContainsKey("bootloader.file") {
236+
return nil
237+
}
238+
239+
sketchFileName := b.sketch.MainFile.Base()
240+
sketchInBuildPath := b.buildPath.Join(sketchFileName + ".hex")
241+
sketchInSubfolder := b.buildPath.Join("sketch", sketchFileName+".hex")
242+
243+
var builtSketchPath *paths.Path
244+
if sketchInBuildPath.Exist() {
245+
builtSketchPath = sketchInBuildPath
246+
} else if sketchInSubfolder.Exist() {
247+
builtSketchPath = sketchInSubfolder
248+
} else {
249+
return nil
250+
}
251+
252+
bootloader := ""
253+
if bootloaderNoBlink, ok := b.buildProperties.GetOk("bootloader.noblink"); ok {
254+
bootloader = bootloaderNoBlink
255+
} else {
256+
bootloader = b.buildProperties.Get("bootloader.file")
257+
}
258+
bootloader = b.buildProperties.ExpandPropsInString(bootloader)
259+
260+
bootloaderPath := b.buildProperties.GetPath("runtime.platform.path").Join("bootloaders", bootloader)
261+
if bootloaderPath.NotExist() {
262+
if b.logger.Verbose() {
263+
b.logger.Warn(tr("Bootloader file specified but missing: %[1]s", bootloaderPath))
264+
}
265+
return nil
266+
}
267+
268+
mergedSketchPath := builtSketchPath.Parent().Join(sketchFileName + ".with_bootloader.hex")
269+
270+
// Ignore merger errors for the first iteration
271+
maximumBinSize := 16000000
272+
if uploadMaxSize, ok := b.buildProperties.GetOk("upload.maximum_size"); ok {
273+
maximumBinSize, _ = strconv.Atoi(uploadMaxSize)
274+
maximumBinSize *= 2
275+
}
276+
err := merge(builtSketchPath, bootloaderPath, mergedSketchPath, maximumBinSize)
277+
if err != nil && b.logger.Verbose() {
278+
b.logger.Info(err.Error())
279+
}
280+
281+
return nil
282+
}
283+
284+
func merge(builtSketchPath, bootloaderPath, mergedSketchPath *paths.Path, maximumBinSize int) error {
285+
if bootloaderPath.Ext() == ".bin" {
286+
bootloaderPath = paths.New(strings.TrimSuffix(bootloaderPath.String(), ".bin") + ".hex")
287+
}
288+
289+
memBoot := gohex.NewMemory()
290+
if bootFile, err := bootloaderPath.Open(); err == nil {
291+
defer bootFile.Close()
292+
if err := memBoot.ParseIntelHex(bootFile); err != nil {
293+
return errors.New(bootFile.Name() + " " + err.Error())
294+
}
295+
} else {
296+
return err
297+
}
298+
299+
memSketch := gohex.NewMemory()
300+
if buildFile, err := builtSketchPath.Open(); err == nil {
301+
defer buildFile.Close()
302+
if err := memSketch.ParseIntelHex(buildFile); err != nil {
303+
return errors.New(buildFile.Name() + " " + err.Error())
304+
}
305+
} else {
306+
return err
307+
}
308+
309+
memMerged := gohex.NewMemory()
310+
initialAddress := uint32(math.MaxUint32)
311+
lastAddress := uint32(0)
312+
313+
for _, segment := range memBoot.GetDataSegments() {
314+
if err := memMerged.AddBinary(segment.Address, segment.Data); err != nil {
315+
continue
316+
}
317+
if segment.Address < initialAddress {
318+
initialAddress = segment.Address
319+
}
320+
if segment.Address+uint32(len(segment.Data)) > lastAddress {
321+
lastAddress = segment.Address + uint32(len(segment.Data))
322+
}
323+
}
324+
for _, segment := range memSketch.GetDataSegments() {
325+
if err := memMerged.AddBinary(segment.Address, segment.Data); err != nil {
326+
continue
327+
}
328+
if segment.Address < initialAddress {
329+
initialAddress = segment.Address
330+
}
331+
if segment.Address+uint32(len(segment.Data)) > lastAddress {
332+
lastAddress = segment.Address + uint32(len(segment.Data))
333+
}
334+
}
335+
336+
if mergeFile, err := mergedSketchPath.Create(); err == nil {
337+
defer mergeFile.Close()
338+
memMerged.DumpIntelHex(mergeFile, 16)
339+
} else {
340+
return err
341+
}
342+
343+
// Write out a .bin if the addresses doesn't go too far away from origin
344+
// (and consequently produce a very large bin)
345+
size := lastAddress - initialAddress
346+
if size > uint32(maximumBinSize) {
347+
return nil
348+
}
349+
mergedSketchPathBin := paths.New(strings.TrimSuffix(mergedSketchPath.String(), ".hex") + ".bin")
350+
data := memMerged.ToBinary(initialAddress, size, 0xFF)
351+
return mergedSketchPathBin.WriteFile(data)
352+
}

legacy/builder/builder.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,7 @@ func (s *Builder) Run(ctx *types.Context) error {
177177
}),
178178

179179
types.BareCommand(func(ctx *types.Context) error {
180-
return MergeSketchWithBootloader(
181-
ctx.OnlyUpdateCompilationDatabase,
182-
ctx.Builder.GetBuildPath(), ctx.Builder.Sketch(), ctx.Builder.GetBuildProperties(),
183-
ctx.BuilderLogger,
184-
)
180+
return ctx.Builder.MergeSketchWithBootloader(ctx.OnlyUpdateCompilationDatabase)
185181
}),
186182

187183
types.BareCommand(func(ctx *types.Context) error {

legacy/builder/merge_sketch_with_bootloader.go

Lines changed: 0 additions & 160 deletions
This file was deleted.

legacy/builder/test/merge_sketch_with_bootloader_test.go

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ import (
2121
"strings"
2222
"testing"
2323

24-
"github.com/arduino/arduino-cli/arduino/builder/logger"
25-
"github.com/arduino/arduino-cli/legacy/builder"
2624
"github.com/arduino/arduino-cli/legacy/builder/constants"
2725
"github.com/arduino/arduino-cli/legacy/builder/types"
2826
paths "github.com/arduino/go-paths-helper"
@@ -70,12 +68,7 @@ func TestMergeSketchWithBootloader(t *testing.T) {
7068
err = buildPath.Join("sketch", "sketch1.ino.hex").WriteFile([]byte(fakeSketchHex))
7169
require.NoError(t, err)
7270

73-
builderLogger := logger.New(nil, nil, false, "")
74-
err = builder.MergeSketchWithBootloader(
75-
ctx.OnlyUpdateCompilationDatabase,
76-
ctx.Builder.GetBuildPath(), ctx.Builder.Sketch(), ctx.Builder.GetBuildProperties(),
77-
builderLogger,
78-
)
71+
err = ctx.Builder.MergeSketchWithBootloader(ctx.OnlyUpdateCompilationDatabase)
7972
require.NoError(t, err)
8073

8174
bytes, err := buildPath.Join("sketch", "sketch1.ino.with_bootloader.hex").ReadFile()
@@ -127,12 +120,7 @@ func TestMergeSketchWithBootloaderSketchInBuildPath(t *testing.T) {
127120
err = buildPath.Join("sketch1.ino.hex").WriteFile([]byte(fakeSketchHex))
128121
require.NoError(t, err)
129122

130-
builderLogger := logger.New(nil, nil, false, "")
131-
err = builder.MergeSketchWithBootloader(
132-
ctx.OnlyUpdateCompilationDatabase,
133-
ctx.Builder.GetBuildPath(), ctx.Builder.Sketch(), ctx.Builder.GetBuildProperties(),
134-
builderLogger,
135-
)
123+
err = ctx.Builder.MergeSketchWithBootloader(ctx.OnlyUpdateCompilationDatabase)
136124
require.NoError(t, err)
137125

138126
bytes, err := buildPath.Join("sketch1.ino.with_bootloader.hex").ReadFile()
@@ -153,12 +141,7 @@ func TestMergeSketchWithBootloaderWhenNoBootloaderAvailable(t *testing.T) {
153141
buildProperties.Remove(constants.BUILD_PROPERTIES_BOOTLOADER_NOBLINK)
154142
buildProperties.Remove(constants.BUILD_PROPERTIES_BOOTLOADER_FILE)
155143

156-
builderLogger := logger.New(nil, nil, false, "")
157-
err := builder.MergeSketchWithBootloader(
158-
ctx.OnlyUpdateCompilationDatabase,
159-
ctx.Builder.GetBuildPath(), ctx.Builder.Sketch(), ctx.Builder.GetBuildProperties(),
160-
builderLogger,
161-
)
144+
err := ctx.Builder.MergeSketchWithBootloader(ctx.OnlyUpdateCompilationDatabase)
162145
require.NoError(t, err)
163146

164147
exist, err := buildPath.Join("sketch.ino.with_bootloader.hex").ExistCheck()
@@ -213,12 +196,7 @@ func TestMergeSketchWithBootloaderPathIsParameterized(t *testing.T) {
213196
err = buildPath.Join("sketch", "sketch1.ino.hex").WriteFile([]byte(fakeSketchHex))
214197
require.NoError(t, err)
215198

216-
builderLogger := logger.New(nil, nil, false, "")
217-
err = builder.MergeSketchWithBootloader(
218-
ctx.OnlyUpdateCompilationDatabase,
219-
ctx.Builder.GetBuildPath(), ctx.Builder.Sketch(), ctx.Builder.GetBuildProperties(),
220-
builderLogger,
221-
)
199+
err = ctx.Builder.MergeSketchWithBootloader(ctx.OnlyUpdateCompilationDatabase)
222200
require.NoError(t, err)
223201

224202
bytes, err := buildPath.Join("sketch", "sketch1.ino.with_bootloader.hex").ReadFile()

0 commit comments

Comments
 (0)