@@ -24,6 +24,7 @@ import (
24
24
"time"
25
25
26
26
"github.com/arduino/arduino-cli/arduino/cores"
27
+ "github.com/arduino/arduino-cli/arduino/cores/packagemanager"
27
28
"github.com/arduino/arduino-cli/arduino/sketches"
28
29
"github.com/arduino/arduino-cli/cli/feedback"
29
30
"github.com/arduino/arduino-cli/commands"
@@ -80,45 +81,62 @@ func Upload(ctx context.Context, req *rpc.UploadReq, outStream io.Writer, errStr
80
81
pm := commands .GetPackageManager (req .GetInstance ().GetId ())
81
82
82
83
// Find target board and board properties
83
- _ , _ , board , boardProperties , _ , err := pm .ResolveFQBN (fqbn )
84
+ _ , boardPlatform , board , boardProperties , buildPlatform , err := pm .ResolveFQBN (fqbn )
84
85
if err != nil {
85
86
return nil , fmt .Errorf ("incorrect FQBN: %s" , err )
86
87
}
87
88
88
- // Load programmer tool
89
- uploadToolPattern , have := boardProperties .GetOk ("upload.tool" )
90
- if ! have || uploadToolPattern == "" {
91
- return nil , fmt .Errorf ("cannot get programmer tool: undefined 'upload.tool' property" )
92
- }
93
-
94
- var referencedPlatformRelease * cores.PlatformRelease
95
- if split := strings .Split (uploadToolPattern , ":" ); len (split ) > 2 {
96
- return nil , fmt .Errorf ("invalid 'upload.tool' property: %s" , uploadToolPattern )
97
- } else if len (split ) == 2 {
98
- referencedPackageName := split [0 ]
99
- uploadToolPattern = split [1 ]
100
- architecture := board .PlatformRelease .Platform .Architecture
101
-
102
- if referencedPackage := pm .Packages [referencedPackageName ]; referencedPackage == nil {
103
- return nil , fmt .Errorf ("required platform %s:%s not installed" , referencedPackageName , architecture )
104
- } else if referencedPlatform := referencedPackage .Platforms [architecture ]; referencedPlatform == nil {
105
- return nil , fmt .Errorf ("required platform %s:%s not installed" , referencedPackageName , architecture )
106
- } else {
107
- referencedPlatformRelease = pm .GetInstalledPlatformRelease (referencedPlatform )
89
+ // Load upload tool definitions
90
+ var uploadToolName string
91
+ var uploadToolPlatform * cores.PlatformRelease
92
+ var programmer * cores.Programmer
93
+ if programmerID := req .GetProgrammer (); programmerID != "" {
94
+ programmer = boardPlatform .Programmers [programmerID ]
95
+ if programmer == nil {
96
+ // Try to find the programmer in the referenced build platform
97
+ programmer = buildPlatform .Programmers [programmerID ]
98
+ }
99
+ if programmer == nil {
100
+ return nil , fmt .Errorf ("programmer '%s' not available" , programmerID )
101
+ }
102
+ uploadToolName = programmer .Properties .Get ("program.tool" )
103
+ uploadToolPlatform = programmer .PlatformRelease
104
+ if uploadToolName == "" {
105
+ return nil , fmt .Errorf ("cannot get programmer tool: undefined 'program.tool' property" )
106
+ }
107
+ } else {
108
+ uploadToolName = boardProperties .Get ("upload.tool" )
109
+ uploadToolPlatform = boardPlatform
110
+ if uploadToolName == "" {
111
+ return nil , fmt .Errorf ("cannot get upload tool: undefined 'upload.tool' property" )
112
+ }
113
+ if split := strings .Split (uploadToolName , ":" ); len (split ) > 2 {
114
+ return nil , fmt .Errorf ("invalid 'upload.tool' property: %s" , uploadToolName )
115
+ } else if len (split ) == 2 {
116
+ uploadToolName = split [1 ]
117
+ uploadToolPlatform = pm .GetInstalledPlatformRelease (
118
+ pm .FindPlatform (& packagemanager.PlatformReference {
119
+ Package : split [0 ],
120
+ PlatformArchitecture : boardPlatform .Platform .Architecture ,
121
+ }),
122
+ )
108
123
}
109
124
}
110
125
111
126
// Build configuration for upload
112
127
uploadProperties := properties .NewMap ()
113
- if referencedPlatformRelease != nil {
114
- uploadProperties .Merge (referencedPlatformRelease .Properties )
128
+ if uploadToolPlatform != nil {
129
+ uploadProperties .Merge (uploadToolPlatform .Properties )
115
130
}
116
- uploadProperties .Merge (board . PlatformRelease .Properties )
117
- uploadProperties .Merge (board . PlatformRelease .RuntimeProperties ())
131
+ uploadProperties .Merge (boardPlatform .Properties )
132
+ uploadProperties .Merge (boardPlatform .RuntimeProperties ())
118
133
uploadProperties .Merge (boardProperties )
119
134
120
- uploadToolProperties := uploadProperties .SubTree ("tools." + uploadToolPattern )
135
+ uploadToolProperties := uploadProperties .SubTree ("tools." + uploadToolName )
121
136
uploadProperties .Merge (uploadToolProperties )
137
+ if programmer != nil {
138
+ uploadProperties .Merge (programmer .Properties )
139
+ }
122
140
123
141
if requiredTools , err := pm .FindToolsRequiredForBoard (board ); err == nil {
124
142
for _ , requiredTool := range requiredTools {
@@ -132,17 +150,25 @@ func Upload(ctx context.Context, req *rpc.UploadReq, outStream io.Writer, errStr
132
150
if v , ok := uploadProperties .GetOk ("upload.params.verbose" ); ok {
133
151
uploadProperties .Set ("upload.verbose" , v )
134
152
}
153
+ if v , ok := uploadProperties .GetOk ("program.params.verbose" ); ok {
154
+ uploadProperties .Set ("program.verbose" , v )
155
+ }
135
156
} else {
136
157
if v , ok := uploadProperties .GetOk ("upload.params.quiet" ); ok {
137
158
uploadProperties .Set ("upload.verbose" , v )
138
159
}
160
+ if v , ok := uploadProperties .GetOk ("program.params.quiet" ); ok {
161
+ uploadProperties .Set ("program.verbose" , v )
162
+ }
139
163
}
140
164
141
165
// Set properties for verify
142
166
if req .GetVerify () {
143
167
uploadProperties .Set ("upload.verify" , uploadProperties .Get ("upload.params.verify" ))
168
+ uploadProperties .Set ("program.verify" , uploadProperties .Get ("program.params.verify" ))
144
169
} else {
145
170
uploadProperties .Set ("upload.verify" , uploadProperties .Get ("upload.params.noverify" ))
171
+ uploadProperties .Set ("program.verify" , uploadProperties .Get ("program.params.noverify" ))
146
172
}
147
173
148
174
var importPath * paths.Path
@@ -165,50 +191,54 @@ func Upload(ctx context.Context, req *rpc.UploadReq, outStream io.Writer, errStr
165
191
uploadProperties .SetPath ("build.path" , importPath )
166
192
uploadProperties .Set ("build.project_name" , sketch .Name + ".ino" )
167
193
168
- // Perform reset via 1200bps touch if requested
169
- if uploadProperties .GetBoolean ("upload.use_1200bps_touch" ) {
170
- ports , err := serial .GetPortsList ()
171
- if err != nil {
172
- return nil , fmt .Errorf ("cannot get serial port list: %s" , err )
173
- }
174
- for _ , p := range ports {
175
- if req .GetVerbose () {
176
- outStream .Write ([]byte (fmt .Sprintf ("Performing 1200-bps touch reset on serial port %s" , p )))
177
- outStream .Write ([]byte (fmt .Sprintln ()))
194
+ // If not using programmer perform some action required
195
+ // to set the board in bootloader mode
196
+ actualPort := port
197
+ if programmer == nil {
198
+ // Perform reset via 1200bps touch if requested
199
+ if uploadProperties .GetBoolean ("upload.use_1200bps_touch" ) {
200
+ ports , err := serial .GetPortsList ()
201
+ if err != nil {
202
+ return nil , fmt .Errorf ("cannot get serial port list: %s" , err )
178
203
}
179
- if p == port {
180
- if err := touchSerialPortAt1200bps (p ); err != nil {
181
- return nil , fmt .Errorf ("cannot perform reset: %s" , err )
204
+ for _ , p := range ports {
205
+ if req .GetVerbose () {
206
+ outStream .Write ([]byte (fmt .Sprintf ("Performing 1200-bps touch reset on serial port %s" , p )))
207
+ outStream .Write ([]byte (fmt .Sprintln ()))
208
+ }
209
+ if p == port {
210
+ if err := touchSerialPortAt1200bps (p ); err != nil {
211
+ return nil , fmt .Errorf ("cannot perform reset: %s" , err )
212
+ }
213
+ break
182
214
}
183
- break
184
215
}
216
+
217
+ // Scanning for available ports seems to open the port or
218
+ // otherwise assert DTR, which would cancel the WDT reset if
219
+ // it happened within 250 ms. So we wait until the reset should
220
+ // have already occurred before we start scanning.
221
+ time .Sleep (500 * time .Millisecond )
185
222
}
186
223
187
- // Scanning for available ports seems to open the port or
188
- // otherwise assert DTR, which would cancel the WDT reset if
189
- // it happened within 250 ms. So we wait until the reset should
190
- // have already occurred before we start scanning.
191
- time .Sleep (500 * time .Millisecond )
192
- }
224
+ // Wait for upload port if requested
225
+ if uploadProperties .GetBoolean ("upload.wait_for_upload_port" ) {
226
+ if req .GetVerbose () {
227
+ outStream .Write ([]byte (fmt .Sprintln ("Waiting for upload port..." )))
228
+ }
229
+ if p , err := waitForNewSerialPort (); err != nil {
230
+ return nil , fmt .Errorf ("cannot detect serial ports: %s" , err )
231
+ } else if p == "" {
232
+ feedback .Print ("No new serial port detected." )
233
+ } else {
234
+ actualPort = p
235
+ }
193
236
194
- // Wait for upload port if requested
195
- actualPort := port // default
196
- if uploadProperties .GetBoolean ("upload.wait_for_upload_port" ) {
197
- if req .GetVerbose () {
198
- outStream .Write ([]byte (fmt .Sprintln ("Waiting for upload port..." )))
199
- }
200
- if p , err := waitForNewSerialPort (); err != nil {
201
- return nil , fmt .Errorf ("cannot detect serial ports: %s" , err )
202
- } else if p == "" {
203
- feedback .Print ("No new serial port detected." )
204
- } else {
205
- actualPort = p
237
+ // on OS X, if the port is opened too quickly after it is detected,
238
+ // a "Resource busy" error occurs, add a delay to workaround.
239
+ // This apply to other platforms as well.
240
+ time .Sleep (500 * time .Millisecond )
206
241
}
207
-
208
- // on OS X, if the port is opened too quickly after it is detected,
209
- // a "Resource busy" error occurs, add a delay to workaround.
210
- // This apply to other platforms as well.
211
- time .Sleep (500 * time .Millisecond )
212
242
}
213
243
214
244
// Set serial port property
@@ -220,7 +250,12 @@ func Upload(ctx context.Context, req *rpc.UploadReq, outStream io.Writer, errStr
220
250
}
221
251
222
252
// Build recipe for upload
223
- recipe := uploadProperties .Get ("upload.pattern" )
253
+ var recipe string
254
+ if programmer != nil {
255
+ recipe = uploadProperties .Get ("program.pattern" )
256
+ } else {
257
+ recipe = uploadProperties .Get ("upload.pattern" )
258
+ }
224
259
cmdLine := uploadProperties .ExpandPropsInString (recipe )
225
260
if req .GetVerbose () {
226
261
outStream .Write ([]byte (fmt .Sprintln (cmdLine )))
0 commit comments