forked from mathiasvr/bluejay
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BLHeliBootLoad.inc
385 lines (317 loc) · 7.9 KB
/
BLHeliBootLoad.inc
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
383
384
; BLHeli bootloader for SiLabs MCUs. Based upon AVRootloader (copyright HR)
XTAL EQU 25000000
BOOT_START EQU 1C00h ; Bootloader segment address
BOOT_DELAY EQU XTAL/4 ; About 250ms (don't set to fast to avoid connection problems)
BOOT_BAUDRATE EQU 19200 ; Only used if no baudrate detection activated, XTAL is than important
BOOT_VERSION EQU 6 ; Version 6 (must be not changed)
BOOT_PAGES EQU 1 ; Number of flash segments for bootloader
UART_LOOP EQU 26 ; Depends upon timing of putc, getc
BAUDTIME EQU ((XTAL/BOOT_BAUDRATE)/3)-UART_LOOP
SUCCESS EQU 030h
ERRORVERIFY EQU 0C0h
ERRORCOMMAND EQU 0C1h
ERRORCRC EQU 0C2h
ERRORPROG EQU 0C5h
POLYNOM EQU 0A001h ; CRC Polynom
Xl EQU R0 ; Temporary X
Xh EQU R1
Paral EQU R2 ; Params for UART
Parah EQU R3
Cmdl EQU R4 ; Commands
Cmdh EQU R5
Cntl EQU R6 ; Baudtime
Cnth EQU R7
DSEG AT 20h
Bit_Reg: DS 1 ; Bit storage register
Byte_Reg: DS 1 ; Byte storage register
Crcl: DS 1 ; CRC 16Bit
Crch: DS 1
Baudl: DS 1 ; Baudtime
Baudh: DS 1
Bit_Cnt: DS 1 ; Counter in UART loops
Byte_Cntl: DS 1 ; Generic counter
Byte_Cnth: DS 1
BL_Flash_Key_1: DS 1 ; Flash keys
BL_Flash_Key_2: DS 1
CSEG AT BOOT_START ; Bootloader start
init:clr IE_EA
; Select register bank 0 for main program routines
clr PSW.3 ; Select register bank 0 for main program routines
; Disable the WDT.
mov WDTCN, #0DEh ; Disable watchdog
mov WDTCN, #0ADh
; Initialize stack
mov SP, #0c0h ; Stack = 64 upper bytes of RAM
; Initialize clock
mov CLKSEL, #00h ; Set clock divider to 1
; Initialize VDD monitor
orl VDM0CN, #080h ; Enable the VDD monitor
mov Baudl, #38h ; Wait 100us
mov Baudh, #03h
acall waitf
; Initialize flash keys
mov BL_Flash_Key_1, #0A5h ; First key code
mov BL_Flash_Key_2, #0F1h ; Second key code
; Initialize ports
orl RTX_MDIN, #(1 SHL RTX_PIN) ; Set digital
anl RTX_MDOUT, #NOT(1 SHL RTX_PIN) ; Disable pushpull
setb RTX_PORT.RTX_PIN ; Set data high
mov RTX_SKIP, #0FFh
mov XBR2, #40h; ; Enable crossbar
; Set number of connect attempts before exiting bootloader
mov Cmdh, #250
; Identifier scanning
abd: mov Xl, #(low(BOOT_DELAY / 6)+1)
mov Xh, #(high(BOOT_DELAY / 6)+1)
mov Cmdl, #(high((BOOT_DELAY / 6) SHR 8)+1)
mov Crcl, #0
mov Crch, #0
mov DPTR, #BOOT_SIGN
mov Parah, #(BOOT_MSG - BOOT_SIGN)
mov Baudl, #low(BAUDTIME)
mov Baudh, #high(BAUDTIME)
wait_for_low:
jnb RTX_PORT.RTX_PIN, ($+5)
ajmp wait_for_low
; Identifier (BOOT_SIGN) scanning with timeout and checksum
id1: jb RTX_PORT.RTX_PIN, id3 ; Look for high
djnz Xl, id1 ; Subtract 1 from X (BOOT_DELAY)
djnz Xh, id1
djnz Cmdl, id1
ajmp exit
id3: jnb RTX_PORT.RTX_PIN, id4 ; Look for low
djnz Xl, id3 ; Subtract 1 from X (BOOT_DELAY)
djnz Xh, id3
djnz Cmdl, id3
ajmp exit
id4: acall getx ; Read character
clr A
movc A, @A+DPTR ; Load BOOT_SIGN character
inc DPTR
clr C
subb A, Paral ; Compare with read character
jz id5
djnz Cmdh, abd ; Retry if not last connect attempt
ajmp exit
id5:
djnz Parah, id1
acall getw ; Read CRC
jz ($+4) ; Check CRC
ajmp abd
; Send info about chip/bootloader (BOOT_MSG + BOOT_INFO)
mov Parah, #((BOOT_INFO - BOOT_MSG) + 4)
in1: clr A
movc A, @A+DPTR ; Load character
mov Paral, A
inc DPTR
acall putc
djnz Parah, in1
; Main commandloop
; 0=Run/restart
; 1=Program flash, 2=Erase flash, 3=Read flash
; 0xFF=Set address, 0xFE=Set buffer, 0xFD=Keep alive
main:mov Paral, #SUCCESS
mai1:acall putc
mov Crcl, #0 ; Reset CRC
mov Crch, #0
acall getw ; Get command
mov A, Paral
mov Cmdl, A
mov A, Parah
mov Cmdh, A
clr C
mov A, Cmdh
subb A, #0FEh
jc mai2 ; Jump if not set address or set buffer
acall getw ; Address or number of bytes
mov Byte_Cntl, Paral ; Store number of bytes for set buffer
mov Byte_Cnth, Parah
mov A, Cmdh
jnb ACC.0, mai2 ; Jump if set buffer
mov DPL, Paral ; Store flash address (for set address)
mov DPH, Parah
mai2:acall getw ; Get CRC
mov Paral, #ERRORCRC
jnz mai1
clr C
mov A, Cmdh
subb A, #0FEh
jz setbuf ; If command is set buffer, receive data
jnc main
cjne Cmdh, #0, mai4 ; Jump if command != 0 (and not set buffer)
; Run application/restart bootloader
mov A, Cmdl
jz rst
exit:mov Bit_Access, #0 ; Clear variable used by flash lock detect
mov Bit_Access_Int, #0FFh ; Set variable to indicate that program execution came from bootloader
mov BL_Flash_Key_1, #0 ; Set flash keys to invalid values
mov BL_Flash_Key_2, #0
ljmp 0000h
rst: ajmp init
; Set buffer
setbuf:mov Xl, Byte_Cntl ; Set number of bytes
mov Xh, Byte_Cnth
inc Xl
inc Xh
set4:djnz Xl, set5
djnz Xh, set5
ajmp set6
set5:acall getc ; Receive data
mov A, Paral
movx @Xl, A ; Store data in XRAM
ajmp set4
set6:inc Cmdh
ajmp mai2
mai4:clr C
mov A, Cmdh
subb A, #3
jnc mai5 ; Jump if command >= 3
; Program/erase
mov A, Cmdh
mov C, ACC.0
mov Bit_Reg.0, C
mov Paral, #ERRORPROG
clr C
mov A, DPL
subb A, #low(BOOT_START)
mov A, DPH
subb A, #high(BOOT_START)
jnc mai1 ; Jump if in bootloader segment
jb Bit_Reg.0, pro3 ; Jump if program command
; Erase flash
orl PSCTL, #02h ; Set the PSEE bit
orl PSCTL, #01h ; Set the PSWE bit
mov FLKEY, BL_Flash_Key_1 ; First key code
mov FLKEY, BL_Flash_Key_2 ; Second key code
movx @DPTR, A
jnb Bit_Reg.0, pro6 ; Jump if erase command
; Program flash
pro3:mov Xl, Byte_Cntl ; Set number of bytes
mov Xh, Byte_Cnth
inc Xl
inc Xh
orl PSCTL, #01h ; Set the PSWE bit
anl PSCTL, #0FDh ; Clear the PSEE bit
pro4:djnz Xl, pro5
djnz Xh, pro5
ajmp pro6
pro5:
clr C
mov A, DPH ; Check that address is not in bootloader area
subb A, #1Ch
jc ($+5)
inc DPTR ; Increment flash address
ajmp pro4
movx A, @Xl ; Read from XRAM
mov FLKEY, BL_Flash_Key_1 ; First key code
mov FLKEY, BL_Flash_Key_2 ; Second key code
movx @DPTR, A ; Write to flash
inc DPTR ; Increment flash address
ajmp pro4
pro6:anl PSCTL, #0FCh ; Clear the PSEE and PSWE bits
ajmp main ; Successfully done erase or program
; Read flash
mai5:mov Paral, #ERRORCOMMAND ; Illegal command
cjne Cmdh, #3, mai6 ; Jump if not read flash command
rd1: clr A
movc A, @A+DPTR ; Read from flash
inc DPTR ; Increment flash address
mov Paral, A
acall putp
djnz Cmdl, rd1 ; Decrement bytes to read
acall putw ; CRC
ajmp main
mai6:ajmp mai1
; Send char with crc
putw:mov Paral, Crcl
mov Parah, Crch
acall putc
mov A, Parah
mov Paral, A
putp:mov A, Paral
xrl Crcl, A
mov Bit_Cnt, #8
put1:clr C
mov A, Crch
rrc A
mov Crch, A
mov A, Crcl
rrc A
mov Crcl, A
jnc put2
xrl Crch, #high(POLYNOM)
xrl Crcl, #low(POLYNOM)
put2:djnz Bit_Cnt, put1
; Send char
putc:acall waitf
acall waitf
mov Bit_Cnt, #10
mov A, Paral
cpl A
put3:jb Bit_Reg.1, ($+5)
setb RTX_PORT.RTX_PIN ; Set pin high
jnb Bit_Reg.1, ($+5)
clr RTX_PORT.RTX_PIN ; Set pin low
acall waitf
clr C
rrc A
jc put4
clr Bit_Reg.1
put4:djnz Bit_Cnt, put3
ret
; Receive char/word
getw:acall getc
mov A, Paral
mov Parah, A
getc:jb RTX_PORT.RTX_PIN, ($+5) ; Wait for high
ajmp getc
get1:jnb RTX_PORT.RTX_PIN, ($+5) ; Wait for low
ajmp get1
getx:mov Bit_Cnt, #8
mov Cntl, Baudl
mov Cnth, Baudh
clr C
mov A, Cnth ; Wait half a baud
rrc A
mov Cnth, A
mov A, Cntl
rrc A
mov Cntl, A
acall waith
get2:acall waitf ; Wait one baud
clr C
mov A, Paral
rrc A
jnb RTX_PORT.RTX_PIN, ($+5)
orl A, #080h
mov Paral, A
jnb ACC.7, ($+6)
xrl Crcl, #low(POLYNOM)
clr C
mov A, Crch
rrc A
mov Crch, A
mov A, Crcl
rrc A
mov Crcl, A
jnc get3
xrl Crch, #high(POLYNOM)
xrl Crcl, #low(POLYNOM)
get3:djnz Bit_Cnt, get2
mov A, Crcl
xrl A, Crch
xrl A, Crch
mov Crcl, A
ret
; UART delays
waitf:mov Cntl, Baudl
mov Cnth, Baudh
waith:inc Cntl
inc Cnth
wait1:djnz Cntl, wait1
djnz Cnth, wait1
setb Bit_Reg.1
ret
BOOT_SIGN: DB "BLHeli"
BOOT_MSG: DB "471d" ; Interface-MCU_BootlaoderRevision
BOOT_INFO: DB SIGNATURE_001, SIGNATURE_002, BOOT_VERSION, BOOT_PAGES