@@ -34,6 +34,7 @@ import (
34
34
"arduino.cc/builder/i18n"
35
35
"arduino.cc/builder/types"
36
36
"arduino.cc/builder/utils"
37
+ "io/ioutil"
37
38
"os"
38
39
"path/filepath"
39
40
"strings"
@@ -52,15 +53,25 @@ func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error {
52
53
sketchFileName := filepath .Base (sketch .MainFile .Name )
53
54
logger := ctx .GetLogger ()
54
55
55
- sketchInBuildPath := filepath .Join (buildPath , sketchFileName + ".hex" )
56
- sketchInSubfolder := filepath .Join (buildPath , constants .FOLDER_SKETCH , sketchFileName + ".hex" )
56
+ sketchInBuildPath := filepath .Join (buildPath , sketchFileName )
57
+ sketchInSubfolder := filepath .Join (buildPath , constants .FOLDER_SKETCH , sketchFileName )
57
58
59
+ availableExtensions := []string {".hex" , ".bin" }
58
60
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 {
61
+
62
+ extension := ""
63
+
64
+ for _ , extension = range availableExtensions {
65
+ if _ , err := os .Stat (sketchInBuildPath + extension ); err == nil {
66
+ builtSketchPath = sketchInBuildPath + extension
67
+ break
68
+ } else if _ , err := os .Stat (sketchInSubfolder + extension ); err == nil {
69
+ builtSketchPath = sketchInSubfolder + extension
70
+ break
71
+ }
72
+ }
73
+
74
+ if builtSketchPath == constants .EMPTY_STRING {
64
75
return nil
65
76
}
66
77
@@ -78,9 +89,17 @@ func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error {
78
89
return nil
79
90
}
80
91
81
- mergedSketchPath := filepath .Join (filepath .Dir (builtSketchPath ), sketchFileName + ".with_bootloader.hex" )
92
+ mergedSketchPath := filepath .Join (filepath .Dir (builtSketchPath ), sketchFileName + ".with_bootloader" + extension )
82
93
83
- err := merge (builtSketchPath , bootloaderPath , mergedSketchPath )
94
+ var err error
95
+ if extension == ".hex" {
96
+ err = mergeHex (builtSketchPath , bootloaderPath , mergedSketchPath )
97
+ } else {
98
+ ldscript := buildProperties [constants .BUILD_PROPERTIES_BUILD_LDSCRIPT ]
99
+ variantFolder := buildProperties [constants .BUILD_PROPERTIES_BUILD_VARIANT_PATH ]
100
+ ldscriptPath := filepath .Join (variantFolder , ldscript )
101
+ err = mergeBin (builtSketchPath , ldscriptPath , bootloaderPath , mergedSketchPath )
102
+ }
84
103
85
104
return err
86
105
}
@@ -127,7 +146,7 @@ func extractActualBootloader(bootloader []string) []string {
127
146
return realBootloader
128
147
}
129
148
130
- func merge (builtSketchPath , bootloaderPath , mergedSketchPath string ) error {
149
+ func mergeHex (builtSketchPath , bootloaderPath , mergedSketchPath string ) error {
131
150
sketch , err := utils .ReadFileToRows (builtSketchPath )
132
151
if err != nil {
133
152
return i18n .WrapError (err )
@@ -147,3 +166,46 @@ func merge(builtSketchPath, bootloaderPath, mergedSketchPath string) error {
147
166
148
167
return utils .WriteFile (mergedSketchPath , strings .Join (sketch , "\n " ))
149
168
}
169
+
170
+ func mergeBin (builtSketchPath , ldscriptPath , bootloaderPath , mergedSketchPath string ) error {
171
+ // 0xFF means empty
172
+ // only works if the bootloader is at the beginning of the flash
173
+ // only works if the flash address space is mapped at 0x00
174
+
175
+ // METHOD 1: (non appliable to most architectures)
176
+ // remove all comments from linkerscript
177
+ // find NAMESPACE of .text section -> FLASH
178
+ // find ORIGIN of FLASH section
179
+
180
+ // METHOD 2:
181
+ // Round the bootloader to the next "power of 2" bytes boundary
182
+
183
+ // generate a byte[FLASH] full of 0xFF and bitwise OR with bootloader BIN
184
+ // merge this slice with sketch BIN
185
+
186
+ bootloader , _ := ioutil .ReadFile (bootloaderPath )
187
+ sketch , _ := ioutil .ReadFile (builtSketchPath )
188
+
189
+ paddedBootloaderLen := nextPowerOf2 (len (bootloader ))
190
+
191
+ padding := make ([]byte , paddedBootloaderLen - len (bootloader ))
192
+ for i , _ := range padding {
193
+ padding [i ] = 0xFF
194
+ }
195
+
196
+ bootloader = append (bootloader , padding ... )
197
+ sketch = append (bootloader , sketch ... )
198
+
199
+ return ioutil .WriteFile (mergedSketchPath , sketch , 0644 )
200
+ }
201
+
202
+ func nextPowerOf2 (v int ) int {
203
+ v --
204
+ v |= v >> 1
205
+ v |= v >> 2
206
+ v |= v >> 4
207
+ v |= v >> 8
208
+ v |= v >> 16
209
+ v ++
210
+ return v
211
+ }
0 commit comments