You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

392 lines
8.2 KiB

  1. ; BLHeli bootloader for SiLabs MCUs. Based upon AVRootloader (copyright HR)
  2. XTAL EQU 25000000
  3. BOOT_START EQU 1C00h ; Bootloader segment address
  4. BOOT_DELAY EQU XTAL/4 ; About 250ms (don't set to fast to avoid connection problems)
  5. BOOT_BAUDRATE EQU 19200 ; Only used if no baudrate detection activated, XTAL is than important
  6. BOOT_VERSION EQU 6 ; Version 6 (must be not changed)
  7. BOOT_PAGES EQU 1 ; Number of flash segments for bootloader
  8. UART_LOOP EQU 26 ; Depends upon timing of putc, getc
  9. BAUDTIME EQU ((XTAL/BOOT_BAUDRATE)/3)-UART_LOOP
  10. SUCCESS EQU 030h
  11. ERRORVERIFY EQU 0C0h
  12. ERRORCOMMAND EQU 0C1h
  13. ERRORCRC EQU 0C2h
  14. ERRORPROG EQU 0C5h
  15. POLYNOM EQU 0A001h ; CRC Polynom
  16. Xl EQU R0 ; Temporary X
  17. Xh EQU R1
  18. Paral EQU R2 ; Params for UART
  19. Parah EQU R3
  20. Cmdl EQU R4 ; Commands
  21. Cmdh EQU R5
  22. Cntl EQU R6 ; Baudtime
  23. Cnth EQU R7
  24. DSEG AT 20h
  25. Bit_Reg: DS 1 ; Bit storage register
  26. Byte_Reg: DS 1 ; Byte storage register
  27. Crcl: DS 1 ; CRC 16Bit
  28. Crch: DS 1
  29. Baudl: DS 1 ; Baudtime
  30. Baudh: DS 1
  31. Bit_Cnt: DS 1 ; Counter in UART loops
  32. Byte_Cntl: DS 1 ; Generic counter
  33. Byte_Cnth: DS 1
  34. CSEG AT BOOT_START ; Bootloader start
  35. init:clr EA
  36. ; Select register bank 0 for main program routines
  37. clr PSW.3 ; Select register bank 0 for main program routines
  38. ; Disable the WDT.
  39. IF SIGNATURE_001 == 0f3h
  40. anl PCA0MD, #NOT(40h) ; Clear watchdog enable bit
  41. ENDIF
  42. IF SIGNATURE_001 == 0f8h
  43. mov WDTCN, #0DEh ; Disable watchdog
  44. mov WDTCN, #0ADh
  45. ENDIF
  46. ; Initialize stack
  47. mov SP, #0c0h ; Stack = 64 upper bytes of RAM
  48. ; Initialize clock
  49. IF SIGNATURE_001 == 0f3h
  50. orl OSCICN, #03h ; Set clock divider to 1 (not supported on 'f850)
  51. ENDIF
  52. IF SIGNATURE_001 == 0f8h
  53. mov CLKSEL, #00h ; Set clock divider to 1 (not supported on 'f3xx)
  54. ENDIF
  55. ; Initialize VDD monitor
  56. orl VDM0CN, #080h ; Enable the VDD monitor
  57. mov Baudl, #38h ; Wait 100us
  58. mov Baudh, #03h
  59. acall waitf
  60. mov RSTSRC, #02h ; Set VDD monitor as a reset source (PORSF)
  61. ; Initialize ports
  62. IF SIGNATURE_001 == 0f3h
  63. mov XBR1, #40h; ; Enable crossbar
  64. ENDIF
  65. IF SIGNATURE_001 == 0f8h
  66. mov XBR2, #40h; ; Enable crossbar
  67. ENDIF
  68. orl RTX_MDIN, #(1 SHL RTX_PIN) ; Set digital
  69. anl RTX_MDOUT, #NOT(1 SHL RTX_PIN) ; Disable pushpull
  70. mov RTX_SKIP, #0
  71. setb RTX_PORT.RTX_PIN ; Set data high
  72. ; Set number of connect attempts before exiting bootloader
  73. mov Cmdh, #250
  74. ; Identifier scanning
  75. abd: mov Xl, #(low(BOOT_DELAY / 6)+1)
  76. mov Xh, #(high(BOOT_DELAY / 6)+1)
  77. mov Cmdl, #(high((BOOT_DELAY / 6) SHR 8)+1)
  78. mov Crcl, #0
  79. mov Crch, #0
  80. mov DPTR, #BOOT_SIGN
  81. mov Parah, #(BOOT_MSG - BOOT_SIGN)
  82. mov Baudl, #low(BAUDTIME)
  83. mov Baudh, #high(BAUDTIME)
  84. wait_for_low:
  85. jnb RTX_PORT.RTX_PIN, ($+5)
  86. ajmp wait_for_low
  87. ; Identifier (BOOT_SIGN) scanning with timeout and checksum
  88. id1: jb RTX_PORT.RTX_PIN, id3 ; Look for high
  89. djnz Xl, id1 ; Subtract 1 from X (BOOT_DELAY)
  90. djnz Xh, id1
  91. djnz Cmdl, id1
  92. ajmp exit
  93. id3: jnb RTX_PORT.RTX_PIN, id4 ; Look for low
  94. djnz Xl, id3 ; Subtract 1 from X (BOOT_DELAY)
  95. djnz Xh, id3
  96. djnz Cmdl, id3
  97. ajmp exit
  98. id4: acall getx ; Read character
  99. clr A
  100. movc A, @A+DPTR ; Load BOOT_SIGN character
  101. inc DPTR
  102. clr C
  103. subb A, Paral ; Compare with read character
  104. jz id5
  105. djnz Cmdh, abd ; Retry if not last connect attempt
  106. ajmp exit
  107. id5:
  108. djnz Parah, id1
  109. acall getw ; Read CRC
  110. jz ($+4) ; Check CRC
  111. ajmp abd
  112. ; Send info about chip/bootloader (BOOT_MSG + BOOT_INFO)
  113. mov Parah, #((BOOT_INFO - BOOT_MSG) + 4)
  114. in1: clr A
  115. movc A, @A+DPTR ; Load character
  116. mov Paral, A
  117. inc DPTR
  118. acall putc
  119. djnz Parah, in1
  120. ; Main commandloop
  121. ; 0=Run/restart
  122. ; 1=Program flash, 2=Erase flash, 3=Read flash
  123. ; 0xFF=Set address, 0xFE=Set buffer, 0xFD=Keep alive
  124. main:mov Paral, #SUCCESS
  125. mai1:acall putc
  126. mov Crcl, #0 ; Reset CRC
  127. mov Crch, #0
  128. acall getw ; Get command
  129. mov A, Paral
  130. mov Cmdl, A
  131. mov A, Parah
  132. mov Cmdh, A
  133. clr C
  134. mov A, Cmdh
  135. subb A, #0FEh
  136. jc mai2 ; Jump if not set address or set buffer
  137. acall getw ; Address or number of bytes
  138. mov Byte_Cntl, Paral ; Store number of bytes for set buffer
  139. mov Byte_Cnth, Parah
  140. mov A, Cmdh
  141. jnb ACC.0, mai2 ; Jump if set buffer
  142. mov DPL, Paral ; Store flash address (for set address)
  143. mov DPH, Parah
  144. mai2:acall getw ; Get CRC
  145. mov Paral, #ERRORCRC
  146. jnz mai1
  147. clr C
  148. mov A, Cmdh
  149. subb A, #0FEh
  150. jz setbuf ; If command is set buffer, receive data
  151. jnc main
  152. cjne Cmdh, #0, mai4 ; Jump if command != 0 (and not set buffer)
  153. ; Run application/restart bootloader
  154. mov A, Cmdl
  155. jz rst
  156. exit:mov Bit_Access, #0 ; Clear variable used by flash lock detect
  157. mov Bit_Access_Int, #0FFh ; Set variable to indicate that program execution came from bootloader
  158. ljmp 0000h
  159. rst: ajmp init
  160. ; Set buffer
  161. setbuf:mov Xl, Byte_Cntl ; Set number of bytes
  162. mov Xh, Byte_Cnth
  163. inc Xl
  164. inc Xh
  165. set4:djnz Xl, set5
  166. djnz Xh, set5
  167. ajmp set6
  168. set5:acall getc ; Receive data
  169. mov A, Paral
  170. IF SIGNATURE_001 == 0f3h
  171. mov EMI0CN, Xh
  172. ENDIF
  173. movx @Xl, A ; Store data in XRAM
  174. ajmp set4
  175. set6:inc Cmdh
  176. ajmp mai2
  177. mai4:clr C
  178. mov A, Cmdh
  179. subb A, #3
  180. jnc mai5 ; Jump if command >= 3
  181. ; Program/erase
  182. mov A, Cmdh
  183. mov C, ACC.0
  184. mov Bit_Reg.0, C
  185. mov Paral, #ERRORPROG
  186. clr C
  187. mov A, DPL
  188. subb A, #low(BOOT_START)
  189. mov A, DPH
  190. subb A, #high(BOOT_START)
  191. jnc mai1 ; Jump if in bootloader segment
  192. jb Bit_Reg.0, pro3 ; Jump if program command
  193. ; Erase flash
  194. orl PSCTL, #02h ; Set the PSEE bit
  195. orl PSCTL, #01h ; Set the PSWE bit
  196. mov FLKEY, #0A5h ; First key code
  197. mov FLKEY, #0F1h ; Second key code
  198. movx @DPTR, A
  199. jnb Bit_Reg.0, pro6 ; Jump if erase command
  200. ; Program flash
  201. pro3:mov Xl, Byte_Cntl ; Set number of bytes
  202. mov Xh, Byte_Cnth
  203. inc Xl
  204. inc Xh
  205. orl PSCTL, #01h ; Set the PSWE bit
  206. anl PSCTL, #0FDh ; Clear the PSEE bit
  207. pro4:djnz Xl, pro5
  208. djnz Xh, pro5
  209. ajmp pro6
  210. pro5:
  211. IF SIGNATURE_001 == 0f3h
  212. mov EMI0CN, Xh
  213. ENDIF
  214. movx A, @Xl ; Read from XRAM
  215. mov FLKEY, #0A5h ; First key code
  216. mov FLKEY, #0F1h ; Second key code
  217. movx @DPTR, A ; Write to flash
  218. inc DPTR ; Increment flash address
  219. ajmp pro4
  220. pro6:anl PSCTL, #0FCh ; Clear the PSEE and PSWE bits
  221. ajmp main ; Successfully done erase or program
  222. ; Read flash
  223. mai5:mov Paral, #ERRORCOMMAND ; Illegal command
  224. cjne Cmdh, #3, mai6 ; Jump if not read flash command
  225. rd1: clr A
  226. movc A, @A+DPTR ; Read from flash
  227. inc DPTR ; Increment flash address
  228. mov Paral, A
  229. acall putp
  230. djnz Cmdl, rd1 ; Decrement bytes to read
  231. acall putw ; CRC
  232. ajmp main
  233. mai6:ajmp mai1
  234. ; Send char with crc
  235. putw:mov Paral, Crcl
  236. mov Parah, Crch
  237. acall putc
  238. mov A, Parah
  239. mov Paral, A
  240. putp:mov A, Paral
  241. xrl Crcl, A
  242. mov Bit_Cnt, #8
  243. put1:clr C
  244. mov A, Crch
  245. rrc A
  246. mov Crch, A
  247. mov A, Crcl
  248. rrc A
  249. mov Crcl, A
  250. jnc put2
  251. xrl Crch, #high(POLYNOM)
  252. xrl Crcl, #low(POLYNOM)
  253. put2:djnz Bit_Cnt, put1
  254. ; Send char
  255. putc:acall waitf
  256. acall waitf
  257. mov Bit_Cnt, #10
  258. mov A, Paral
  259. cpl A
  260. put3:jb Bit_Reg.1, ($+5)
  261. setb RTX_PORT.RTX_PIN ; Set pin high
  262. jnb Bit_Reg.1, ($+5)
  263. clr RTX_PORT.RTX_PIN ; Set pin low
  264. acall waitf
  265. clr C
  266. rrc A
  267. jc put4
  268. clr Bit_Reg.1
  269. put4:djnz Bit_Cnt, put3
  270. ret
  271. ; Receive char/word
  272. getw:acall getc
  273. mov A, Paral
  274. mov Parah, A
  275. getc:jb RTX_PORT.RTX_PIN, ($+5) ; Wait for high
  276. ajmp getc
  277. get1:jnb RTX_PORT.RTX_PIN, ($+5) ; Wait for low
  278. ajmp get1
  279. getx:mov Bit_Cnt, #8
  280. mov Cntl, Baudl
  281. mov Cnth, Baudh
  282. clr C
  283. mov A, Cnth ; Wait half a baud
  284. rrc A
  285. mov Cnth, A
  286. mov A, Cntl
  287. rrc A
  288. mov Cntl, A
  289. acall waith
  290. get2:acall waitf ; Wait one baud
  291. clr C
  292. mov A, Paral
  293. rrc A
  294. jnb RTX_PORT.RTX_PIN, ($+5)
  295. orl A, #080h
  296. mov Paral, A
  297. jnb ACC.7, ($+6)
  298. xrl Crcl, #low(POLYNOM)
  299. clr C
  300. mov A, Crch
  301. rrc A
  302. mov Crch, A
  303. mov A, Crcl
  304. rrc A
  305. mov Crcl, A
  306. jnc get3
  307. xrl Crch, #high(POLYNOM)
  308. xrl Crcl, #low(POLYNOM)
  309. get3:djnz Bit_Cnt, get2
  310. mov A, Crcl
  311. xrl A, Crch
  312. xrl A, Crch
  313. mov Crcl, A
  314. ret
  315. ; UART delays
  316. waitf:mov Cntl, Baudl
  317. mov Cnth, Baudh
  318. waith:inc Cntl
  319. inc Cnth
  320. wait1:djnz Cntl, wait1
  321. djnz Cnth, wait1
  322. setb Bit_Reg.1
  323. ret
  324. BOOT_SIGN: DB "BLHeli"
  325. BOOT_MSG: DB "471c" ; Interface-MCU_BootlaoderRevision
  326. BOOT_INFO: DB SIGNATURE_001, SIGNATURE_002, BOOT_VERSION, BOOT_PAGES