-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathMainLoader_chip.spin2
382 lines (324 loc) · 9.12 KB
/
MainLoader_chip.spin2
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
''
'' fast loader for CHIP mode
'' this small loader is downloaded by the usual ROM loader, and can
'' then do more sophisticated and slightly faster loading (using binary
'' rather than hex or base64) of the main binary, which is typically much
'' larger
''
' for debug use, look for #ifdef DEBUG
'#define DEBUG 1
CON
R_READBURST = $B << 28
R_WRITEBURST = $F << 28
tx_pin = 62
rx_pin = 63
dbg_pin = 56
FLAGBIT_ZERO = $1 ' if set, zero HUB memory
FLAGBIT_PATCHED = $2 ' if set, clock frequency was patched into binary
'' smart pin modes
ser_txmode = %0000_0000_000_0000000000000_01_11110_0 'async tx mode, output enabled for smart output
ser_rxmode = %0000_0000_000_0000000000000_00_11111_0 'async rx mode, input enabled for smart input
DAT org
begin
mov mailbox, #0
test flagbits, #FLAGBIT_ZERO wz
if_z jmp #skipzero
'' zero out memory
mov pb, ##$7c000/16 - 1
mov ptrb, #0
setq pb
wrlong #0, ptrb
skipzero
restart
'' set up uart smart pins
'' we don't know for sure what the frequency is, so use
'' auto baud rate detection for this
dirl #rx_pin
dirl #tx_pin
call #autobaud
mov pa, waitbit ' autobaud set waitbit
shl pa, #13
or pa, #7 ' set for 8 bits
wrpin ##ser_txmode, #tx_pin
wxpin pa, #tx_pin
dirh #tx_pin
wrpin ##ser_rxmode, #rx_pin
wxpin pa, #rx_pin
dirh #rx_pin
'' try to receive a $55
'' if it works, autobaud is OK, otherwise re-try
.space
testp #rx_pin wc
if_nc jmp #.space
rdpin rxbyte, #rx_pin
shr rxbyte, #24
cmp rxbyte, #$80 wz
if_nz jmp #restart
#ifdef DEBUG
drvl #dbg_pin
#endif
'' send 0 to host to indicate we are ready
setup
mov chksum, #0
call #send_chksum
next_request
'' get request from host
'' the requests we're aware of:
'' = address size : download "size" bytes to address
'' F address size : copy "size" bytes from hub to flash
'' ! : execute the last download blob, then wait for more
'' - : terminate downloads then execute
''
call #ser_rx
cmp rxbyte, #"=" wz
if_z jmp #read_file
cmp rxbyte, #"!" wz
if_z jmp #call_last
cmp rxbyte, #"F" wz
if_z jmp #copy_hub_to_flash
cmp rxbyte, #"-" wz
if_z jmp #done_and_exec
'' bad request
'' set an LED high and loop
drvh #56
drvl #57
error
waitx ##10_000_000
drvnot #56
drvnot #57
jmp #error
read_file
mov chksum, #0
'' read file address
call #ser_rx_long
mov loadaddr, rxlong
'' if first time through, set starting address
cmp startaddr, ##-1 wz
if_z mov startaddr, loadaddr
'' read file size
call #ser_rx_long
mov filesize, rxlong
'' check for himem (bit 31 of address set)
testb loadaddr, #31 wc
if_c jmp #use_himem
'' respond that we are ready to stream data in
mov temp, #"s"
call #ser_tx
'' and get the data
wrfast #0,loadaddr 'ready to write entire memory starting at address
nop ' give time to settle
.mainloop
call #ser_rx
wfbyte rxbyte 'write to hub
add chksum, rxbyte
djnz filesize,#.mainloop 'loop until all bytes received
rdfast #0,#0 'wait for last byte to be written
done_file
'' respond to host
call #send_chksum
jmp #next_request
call_last
call startaddr
'' response is in ptra (a mailbox)
mov mailbox, ptra
neg startaddr, #1
jmp #next_request
done_and_exec
waitx ##80_000_000/10 ' short pause to ensure sync
'' shut down auxiliary cog
tjz mailbox, #.no_mbox
neg mailinfo+0, #1 ' send all 1's for shutdown
call #send_mbox
.no_mbox
'' shut down smart pins
dirl #tx_pin
dirl #rx_pin
wrpin #0, #tx_pin
wrpin #0, #rx_pin
' switch to new clock mode, maybe
' if the binary was patched with -PATCH then we
' set the clock mode to clkmode_
test flagbits, #FLAGBIT_PATCHED wz
if_z jmp #start_cog ' not patched, so start right now
' set clock to clkmode_
' do this in two steps, first clkmode_ & ~3 for rcfast
mov pa, clkmode_ wz
' clkmode_ == 0 means RCFAST, and we're already in that mode
if_z jmp #start_cog
andn pa, clkmode_
hubset pa ' set up oscillator
waitx ##25_000_000/100 ' wait 10 ms
test clkmode_, #3 wz ' does clkmode include a crystal mode?
if_z or clkmode_, #3 ' if not, set it
hubset clkmode_
start_cog
waitx ##25_000_000/10
coginit #0,startaddr 'launch cog 0 from starting address
'' never returns
'' send mailbox info to the other COG
send_mbox
'' make sure himem cog is free
.wait_himem
rdlong resp, mailbox wcz
if_c jmp #.wait_himem ' negative -> still executing command
if_nz jmp #himem_error ' positive -> error message
'' write out the mailbox info (4 longs)
setq #3
wrlong mailinfo, mailbox
ret
''
'' routine to copy HUB memory to flash
'' the host will send us how much to copy (a 32 bit value)
''
copy_hub_to_flash
call #ser_rx_long ' get the length
'' set up mailbox data
mov mailinfo+0, ##R_WRITEBURST ' starting hub address
mov mailinfo+1, ##$8000_0400 ' starting flash address
mov mailinfo+2, rxlong ' length sent to us by the host
'' send it to the mailbox
call #send_mbox
'' and now go
jmp #done_and_exec
''
'' routine to load code into high memory
'' via the mailbox set up earlier
''
use_himem
tjz mailbox, #no_himem
'' set up to receive ping-pong data in the upper 2K of memory
'' the R_WRITEBURST command goes in the upper nybble and makes
'' the whole address negative, which we use to test results
mov pingpong, ##$7FC00 | R_WRITEBURST
next_buffer
xor pingpong, onek
mov bufsiz, onek
cmp filesize, onek wcz ' if filesize < 1K
if_c mov bufsiz, filesize ' use that as the buffer size
'' set up mailbox data for this buffer
mov mailinfo+0, pingpong ' hub address
mov mailinfo+1, loadaddr ' flash address
mov mailinfo+2, bufsiz ' current size
'' tell the host to send us the next data
mov temp, #"k"
call #ser_tx
'' and now receive the data
mov ptrb, pingpong
mov pb, bufsiz
.buf_lp
call #ser_rx
wrbyte rxbyte, ptrb++
add chksum, rxbyte
djnz pb, #.buf_lp
'' chunk received
'' send the next mailbox command to the himem cog
call #send_mbox
'' now move on to the next chunk
add loadaddr, bufsiz
sub filesize, bufsiz wcz
if_nz jmp #next_buffer
chunks_done
'' all done file
'' wait for the final chunk to be processed
.wait_himem
rdlong resp, mailbox wcz
if_c jmp #.wait_himem ' negative -> still executing command
if_nz jmp #himem_error ' positive -> error message
'' and go do the next file
jmp #done_file
'' no mailbox set up, return an error for himem
no_himem
mov temp, #"h" ' no himem kernel loaded
call #ser_tx
jmp #read_file
' relay an error message from the himem kernel
' the error message is a non-zero HUB memory address
himem_error
mov temp, #"e"
call #ser_tx
mov ptrb, resp
.eloop
rdbyte temp, ptrb++ wz
if_z jmp #read_file
call #ser_tx
jmp #.eloop
' send the current checksum back to the host
send_chksum
mov temp, chksum
shr temp, #4
and temp, #$f
add temp, #"@"
call #ser_tx
mov temp, chksum
and temp, #$f
add temp, #"@"
call #ser_tx
mov temp, #" "
jmp #ser_tx
ser_tx
wypin temp, #tx_pin
waitx #20
.txflush
testp #tx_pin wc
if_nc jmp #.txflush
ret
' receive a byte from serial
ser_rx
testp #rx_pin wc
if_nc jmp #ser_rx
rdpin rxbyte, #rx_pin
_ret_ shr rxbyte, #24
' receive a long from serial
ser_rx_long
call #ser_rx
mov rxlong, rxbyte
call #ser_rx
shl rxbyte, #8
or rxlong, rxbyte
call #ser_rx
shl rxbyte, #16
or rxlong, rxbyte
call #ser_rx
shl rxbyte, #24
_ret_ or rxlong, rxbyte
' automatically detect baud rate
' based on length of shortest 1 or 0
' we see next
autobaud
dirl #rx_pin
waitx ##1000
mov mask, ##(1<<(rx_pin-32))
mov port, #1
test port, #1 wc ' set C to distinguish INA/OUTA
test port, #2 wz ' set Z (match on =)
setpat mask, #0 ' wait for pin lo (start bit)
waitpat
getct a
setpat mask, mask ' wait for pin hi (first 1)
waitpat
getct waitbit
_ret_ sub waitbit, a
startaddr long -1 'starting address
waitbit long 99999
onek long 1024
orgf $100
'' the first two values here are set up by loadp2
'' (it sends a additional longs of data representing
'' these values as part of the load process)
clkmode_ res 1 'clock mode
flagbits res 1 'flag bits, see definitions above
loadaddr res 1 'address for load
filesize res 1 'binary file size in bytes
count res 1
rxbyte res 1 'received byte
rxlong res 1 'received longword
temp res 1
chksum res 1
mask res 1
port res 1
a res 1
mailbox res 1 ' address of himem mailbox
pingpong res 1 ' ping pong buffer address
bufsiz res 1 ' current size of ping pong buffer
mailinfo res 4 ' info to store in himem mailbox
resp res 1 ' space for response from himem