47
47
import { DAPLink } from "dapjs" ;
48
48
import { Logging } from "./logging.js" ;
49
49
import { withTimeout , TimeoutError } from "./async-util.js" ;
50
- import { BoardId } from "./board-id.js" ;
51
50
import { DAPWrapper } from "./usb-device-wrapper.js" ;
52
- import { FlashDataSource } from "./device.js" ;
53
51
import {
54
52
CoreRegister ,
55
53
onlyChanged ,
56
54
Page ,
57
55
pageAlignBlocks ,
58
56
read32FromUInt8Array ,
59
57
} from "./usb-partial-flashing-utils.js" ;
58
+ import MemoryMap from "nrf-intel-hex" ;
59
+ import { BoardVersion } from "./device.js" ;
60
60
61
61
type ProgressCallback = ( n : number , partial : boolean ) => void ;
62
62
@@ -102,6 +102,7 @@ export class PartialFlashing {
102
102
constructor (
103
103
private dapwrapper : DAPWrapper ,
104
104
private logging : Logging ,
105
+ private boardVersion : BoardVersion ,
105
106
) { }
106
107
107
108
private log ( v : any ) : void {
@@ -204,11 +205,11 @@ export class PartialFlashing {
204
205
// Falls back to a full flash if partial flashing fails.
205
206
// Drawn from https://github.com/microsoft/pxt-microbit/blob/dec5b8ce72d5c2b4b0b20aafefce7474a6f0c7b2/editor/extension.tsx#L335
206
207
private async partialFlashAsync (
207
- boardId : BoardId ,
208
- dataSource : FlashDataSource ,
208
+ data : string | Uint8Array | MemoryMap . default ,
209
209
updateProgress : ProgressCallback ,
210
210
) : Promise < boolean > {
211
- const flashBytes = await dataSource . partialFlashData ( boardId ) ;
211
+ const flashBytes = this . convertDataToPaddedBytes ( data ) ;
212
+
212
213
const checksums = await this . getFlashChecksumsAsync ( ) ;
213
214
await this . dapwrapper . writeBlockAsync ( loadAddr , flashPageBIN ) ;
214
215
let aligned = pageAlignBlocks ( flashBytes , 0 , this . dapwrapper . pageSize ) ;
@@ -219,7 +220,7 @@ export class PartialFlashing {
219
220
let partial : boolean | undefined ;
220
221
if ( aligned . length > totalPages / 2 ) {
221
222
try {
222
- await this . fullFlashAsync ( boardId , dataSource , updateProgress ) ;
223
+ await this . fullFlashAsync ( data , updateProgress ) ;
223
224
partial = false ;
224
225
} catch ( e ) {
225
226
this . log ( e ) ;
@@ -234,7 +235,7 @@ export class PartialFlashing {
234
235
} catch ( e ) {
235
236
this . log ( e ) ;
236
237
this . log ( "Partial flash failed, attempting full flash." ) ;
237
- await this . fullFlashAsync ( boardId , dataSource , updateProgress ) ;
238
+ await this . fullFlashAsync ( data , updateProgress ) ;
238
239
partial = false ;
239
240
}
240
241
}
@@ -250,8 +251,7 @@ export class PartialFlashing {
250
251
251
252
// Perform full flash of micro:bit's ROM using daplink.
252
253
async fullFlashAsync (
253
- boardId : BoardId ,
254
- dataSource : FlashDataSource ,
254
+ data : string | Uint8Array | MemoryMap . default ,
255
255
updateProgress : ProgressCallback ,
256
256
) {
257
257
this . log ( "Full flash" ) ;
@@ -261,7 +261,7 @@ export class PartialFlashing {
261
261
} ;
262
262
this . dapwrapper . daplink . on ( DAPLink . EVENT_PROGRESS , fullFlashProgress ) ;
263
263
try {
264
- const data = await dataSource . fullFlashData ( boardId ) ;
264
+ data = this . convertDataToHexString ( data ) ;
265
265
await this . dapwrapper . transport . open ( ) ;
266
266
await this . dapwrapper . daplink . flash ( new TextEncoder ( ) . encode ( data ) ) ;
267
267
this . logging . event ( {
@@ -279,8 +279,7 @@ export class PartialFlashing {
279
279
// Flash the micro:bit's ROM with the provided image, resetting the micro:bit first.
280
280
// Drawn from https://github.com/microsoft/pxt-microbit/blob/dec5b8ce72d5c2b4b0b20aafefce7474a6f0c7b2/editor/extension.tsx#L439
281
281
async flashAsync (
282
- boardId : BoardId ,
283
- dataSource : FlashDataSource ,
282
+ data : string | Uint8Array | MemoryMap . default ,
284
283
updateProgress : ProgressCallback ,
285
284
) : Promise < boolean > {
286
285
let resetPromise = ( async ( ) => {
@@ -300,11 +299,7 @@ export class PartialFlashing {
300
299
await withTimeout ( resetPromise , 1000 ) ;
301
300
302
301
this . log ( "Begin flashing" ) ;
303
- return await this . partialFlashAsync (
304
- boardId ,
305
- dataSource ,
306
- updateProgress ,
307
- ) ;
302
+ return await this . partialFlashAsync ( data , updateProgress ) ;
308
303
} catch ( e ) {
309
304
if ( e instanceof TimeoutError ) {
310
305
this . log ( "Resetting micro:bit timed out" ) ;
@@ -313,7 +308,7 @@ export class PartialFlashing {
313
308
type : "WebUSB-info" ,
314
309
message : "flash-failed/attempting-full-flash" ,
315
310
} ) ;
316
- await this . fullFlashAsync ( boardId , dataSource , updateProgress ) ;
311
+ await this . fullFlashAsync ( data , updateProgress ) ;
317
312
return false ;
318
313
} else {
319
314
throw e ;
@@ -324,4 +319,56 @@ export class PartialFlashing {
324
319
await this . dapwrapper . disconnectAsync ( ) ;
325
320
}
326
321
}
322
+
323
+ private convertDataToHexString (
324
+ data : string | Uint8Array | MemoryMap . default ,
325
+ ) : string {
326
+ if ( typeof data === "string" ) {
327
+ return data ;
328
+ }
329
+ if ( data instanceof Uint8Array ) {
330
+ return this . paddedBytesToHexString ( data ) ;
331
+ }
332
+ return data . asHexString ( ) ;
333
+ }
334
+
335
+ private convertDataToPaddedBytes (
336
+ data : string | Uint8Array | MemoryMap . default ,
337
+ ) : Uint8Array {
338
+ if ( data instanceof Uint8Array ) {
339
+ return data ;
340
+ }
341
+ if ( typeof data === "string" ) {
342
+ return this . hexStringToPaddedBytes ( data ) ;
343
+ }
344
+ return this . memoryMapToPaddedBytes ( data ) ;
345
+ }
346
+
347
+ private hexStringToPaddedBytes ( hex : string ) : Uint8Array {
348
+ // Cludge for a packaging issue
349
+ const fromHex : (
350
+ hexText : string ,
351
+ maxBlockSize ?: number ,
352
+ ) => MemoryMap . default =
353
+ ( MemoryMap as any ) . fromHex ?? MemoryMap . default . fromHex ;
354
+
355
+ return this . memoryMapToPaddedBytes ( fromHex ( hex ) ) ;
356
+ }
357
+
358
+ private paddedBytesToHexString ( data : Uint8Array ) : string {
359
+ // Cludge for a packaging issue
360
+ const fromPaddedUint8Array : ( data : Uint8Array ) => MemoryMap . default =
361
+ ( MemoryMap as any ) . fromPaddedUint8Array ??
362
+ MemoryMap . default . fromPaddedUint8Array ;
363
+
364
+ return fromPaddedUint8Array ( data ) . asHexString ( ) ;
365
+ }
366
+
367
+ private memoryMapToPaddedBytes ( memoryMap : MemoryMap . default ) : Uint8Array {
368
+ const flashSize = {
369
+ V1 : 256 * 1024 ,
370
+ V2 : 512 * 1024 ,
371
+ } [ this . boardVersion ] ;
372
+ return memoryMap . slicePad ( 0 , flashSize ) ;
373
+ }
327
374
}
0 commit comments