forked from microsoft/devicescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbundle.ts
More file actions
109 lines (92 loc) · 3.22 KB
/
bundle.ts
File metadata and controls
109 lines (92 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { writeFileSync } from "fs"
import { compileFile, devsFactory } from "./build"
import { BINDIR, fatal, log, verboseLog } from "./command"
import {
SRV_DEVICE_SCRIPT_MANAGER,
SRV_SETTINGS,
delay,
isTimeoutError,
} from "jacdac-ts"
import { devtools } from "./devtools"
import { devtoolsIface } from "./sidedata"
import { deployToService } from "./deploy"
import { BuildOptions } from "./sideprotocol"
import { FlashOptions, fetchFW, resolveBoard } from "./flash"
import { patchFstorToBoard } from "./binpatch"
import { writeFile } from "fs/promises"
export interface BundleOptions {
flashSize?: string
flashFile?: string
}
export async function bundle(
filename: string | undefined,
options: BundleOptions & BuildOptions & FlashOptions
) {
const { board, arch } = await resolveBoard("", options)
await devtools(undefined, {})
const inst = await devsFactory()
await inst.setupWebsocketTransport("ws://127.0.0.1:8081")
const pageSize = board.flashPageSize ?? arch.flashPageSize ?? 4096
if (options.flashSize) {
inst.flashSize = +options.flashSize * 1024
} else {
const pages = board.fstorPages ?? arch.fstorPages
if (!pages)
fatal(`fstorPages not specified for ${board.id} nor ${arch.id}`)
inst.flashSize = pages * pageSize
}
const flashKB = inst.flashSize / 1024
verboseLog(`board:${board.id}, arch:${arch.id}, flashSize:${flashKB}kB`)
if (inst.flashSize < pageSize * 2 || (inst.flashSize & (pageSize - 1)) != 0)
fatal("invalid flash size")
let fstor = new Uint8Array(0)
inst.flashLoad = () => {
return fstor.slice()
}
inst.flashSave = buf => {
verboseLog(`flash save ${buf.length}`)
fstor = new Uint8Array(buf)
}
inst.devsStart()
const res = await compileFile(filename, options)
if (!res.success) process.exit(1)
const RETRY_DELAY = 100
const bus = devtoolsIface.bus
for (let i = 0; i < 20; i++) {
const service = bus.services({
serviceClass: SRV_DEVICE_SCRIPT_MANAGER,
})[0]
if (service) {
const settingsService = service?.device?.services({
serviceClass: SRV_SETTINGS,
})?.[0]
try {
await deployToService(service, res.binary, {
noRun: true,
settingsService,
settings: res.settings,
})
} catch (e) {
if (isTimeoutError(e)) {
// reset?
// keep retrying
await delay(RETRY_DELAY)
continue
}
throw e
}
await delay(300)
const fwPath = await fetchFW(board, options)
const buf = await patchFstorToBoard(fwPath, board, arch, fstor)
const bn = fwPath.replace(/.*[\/\\]/, "")
const fn =
options.flashFile ||
(options.outDir || BINDIR) + "/bundle-" + bn
log(`writing ${buf.length} bytes to ${fn}`)
await writeFile(fn, buf)
process.exit(0)
}
await delay(RETRY_DELAY)
}
throw new Error("no service")
}