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.

369 lines
7.6 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. anl PCA0MD, #NOT(40h) ; Clear watchdog enable bit
  40. ; Initialize stack
  41. mov SP, #0c0h ; Stack = 64 upper bytes of RAM
  42. ; Initialize clock
  43. orl OSCICN, #03h ; Set clock divider to 1
  44. ; Initialize VDD monitor
  45. orl VDM0CN, #080h ; Enable the VDD monitor
  46. mov Baudl, #38h ; Wait 100us
  47. mov Baudh, #03h
  48. acall waitf
  49. mov RSTSRC, #02h ; Set VDD monitor as a reset source (PORSF)
  50. ; Initialize ports
  51. mov XBR1, #40h; ; Enable crossbar
  52. orl RTX_MDIN, #(1 SHL RTX_PIN) ; Set digital
  53. anl RTX_MDOUT, #NOT(1 SHL RTX_PIN) ; Disable pushpull
  54. setb RTX_PORT.RTX_PIN ; Set data high
  55. ; Identifier scanning
  56. abd: mov Xl, #(low(BOOT_DELAY / 6)+1)
  57. mov Xh, #(high(BOOT_DELAY / 6)+1)
  58. mov Cmdl, #(high((BOOT_DELAY / 6) SHR 8)+1)
  59. mov Crcl, #0
  60. mov Crch, #0
  61. mov DPTR, #BOOT_SIGN
  62. mov Parah, #(BOOT_MSG - BOOT_SIGN)
  63. mov Baudl, #low(BAUDTIME)
  64. mov Baudh, #high(BAUDTIME)
  65. wait_for_low:
  66. jnb RTX_PORT.RTX_PIN, ($+5)
  67. ajmp wait_for_low
  68. ; Identifier (BOOT_SIGN) scanning with timeout and checksum
  69. id1: jb RTX_PORT.RTX_PIN, id3 ; Look for high
  70. djnz Xl, id1 ; Subtract 1 from X (BOOT_DELAY)
  71. djnz Xh, id1
  72. djnz Cmdl, id1
  73. ajmp exit
  74. id3: jnb RTX_PORT.RTX_PIN, id4 ; Look for low
  75. djnz Xl, id3 ; Subtract 1 from X (BOOT_DELAY)
  76. djnz Xh, id3
  77. djnz Cmdl, id3
  78. ajmp exit
  79. id4: acall getx ; Read character
  80. clr A
  81. movc A, @A+DPTR ; Load BOOT_SIGN character
  82. inc DPTR
  83. clr C
  84. subb A, Paral ; Compare with read character
  85. jz ($+4)
  86. ajmp abd
  87. djnz Parah, id1
  88. acall getw ; Read CRC
  89. jz ($+4) ; Check CRC
  90. ajmp abd
  91. ; Send info about chip/bootloader (BOOT_MSG + BOOT_INFO)
  92. mov Parah, #((BOOT_INFO - BOOT_MSG) + 4)
  93. in1: clr A
  94. movc A, @A+DPTR ; Load character
  95. mov Paral, A
  96. inc DPTR
  97. acall putc
  98. djnz Parah, in1
  99. ; Main commandloop
  100. ; 0=Run/restart
  101. ; 1=Program flash, 2=Erase flash, 3=Read flash
  102. ; 0xFF=Set address, 0xFE=Set buffer, 0xFD=Keep alive
  103. main:mov Paral, #SUCCESS
  104. mai1:acall putc
  105. mov Crcl, #0 ; Reset CRC
  106. mov Crch, #0
  107. acall getw ; Get command
  108. mov A, Paral
  109. mov Cmdl, A
  110. mov A, Parah
  111. mov Cmdh, A
  112. clr C
  113. mov A, Cmdh
  114. subb A, #0FEh
  115. jc mai2 ; Jump if not set address or set buffer
  116. acall getw ; Address or number of bytes
  117. mov Byte_Cntl, Paral ; Store number of bytes for set buffer
  118. mov Byte_Cnth, Parah
  119. mov A, Cmdh
  120. jnb ACC.0, mai2 ; Jump if set buffer
  121. mov DPL, Paral ; Store flash address (for set address)
  122. mov DPH, Parah
  123. mai2:acall getw ; Get CRC
  124. mov Paral, #ERRORCRC
  125. jnz mai1
  126. clr C
  127. mov A, Cmdh
  128. subb A, #0FEh
  129. jz setbuf ; If command is set buffer, receive data
  130. jnc main
  131. cjne Cmdh, #0, mai4 ; Jump if command != 0 (and not set buffer)
  132. ; Run application/restart bootloader
  133. mov A, Cmdl
  134. jz rst
  135. exit:mov Bit_Access, #0 ; Clear variable used by flash lock detect
  136. ljmp 0000h
  137. rst: ajmp init
  138. ; Set buffer
  139. setbuf:mov Xl, Byte_Cntl ; Set number of bytes
  140. mov Xh, Byte_Cnth
  141. inc Xl
  142. inc Xh
  143. set4:djnz Xl, set5
  144. djnz Xh, set5
  145. ajmp set6
  146. set5:acall getc ; Receive data
  147. mov A, Paral
  148. mov EMI0CN, Xh
  149. movx @Xl, A ; Store data in XRAM
  150. ajmp set4
  151. set6:inc Cmdh
  152. ajmp mai2
  153. mai4:clr C
  154. mov A, Cmdh
  155. subb A, #3
  156. jnc mai5 ; Jump if command >= 3
  157. ; Program/erase
  158. mov A, Cmdh
  159. mov C, ACC.0
  160. mov Bit_Reg.0, C
  161. mov Paral, #ERRORPROG
  162. clr C
  163. mov A, DPL
  164. subb A, #low(BOOT_START)
  165. mov A, DPH
  166. subb A, #high(BOOT_START)
  167. jnc mai1 ; Jump if in bootloader segment
  168. jb Bit_Reg.0, pro3 ; Jump if program command
  169. ; Erase flash
  170. orl PSCTL, #02h ; Set the PSEE bit
  171. orl PSCTL, #01h ; Set the PSWE bit
  172. mov FLKEY, #0A5h ; First key code
  173. mov FLKEY, #0F1h ; Second key code
  174. movx @DPTR, A
  175. jnb Bit_Reg.0, pro6 ; Jump if erase command
  176. ; Program flash
  177. pro3:mov Xl, Byte_Cntl ; Set number of bytes
  178. mov Xh, Byte_Cnth
  179. inc Xl
  180. inc Xh
  181. orl PSCTL, #01h ; Set the PSWE bit
  182. anl PSCTL, #0FDh ; Clear the PSEE bit
  183. pro4:djnz Xl, pro5
  184. djnz Xh, pro5
  185. ajmp pro6
  186. pro5:mov EMI0CN, Xh
  187. movx A, @Xl ; Read from XRAM
  188. mov FLKEY, #0A5h ; First key code
  189. mov FLKEY, #0F1h ; Second key code
  190. movx @DPTR, A ; Write to flash
  191. inc DPTR ; Increment flash address
  192. ajmp pro4
  193. pro6:anl PSCTL, #0FCh ; Clear the PSEE and PSWE bits
  194. ajmp main ; Successfully done erase or program
  195. ; Read flash
  196. mai5:mov Paral, #ERRORCOMMAND ; Illegal command
  197. cjne Cmdh, #3, mai6 ; Jump if not read flash command
  198. rd1: clr A
  199. movc A, @A+DPTR ; Read from flash
  200. inc DPTR ; Increment flash address
  201. mov Paral, A
  202. acall putp
  203. djnz Cmdl, rd1 ; Decrement bytes to read
  204. acall putw ; CRC
  205. ajmp main
  206. mai6:ajmp mai1
  207. ; Send char with crc
  208. putw:mov Paral, Crcl
  209. mov Parah, Crch
  210. acall putc
  211. mov A, Parah
  212. mov Paral, A
  213. putp:mov A, Paral
  214. xrl Crcl, A
  215. mov Bit_Cnt, #8
  216. put1:clr C
  217. mov A, Crch
  218. rrc A
  219. mov Crch, A
  220. mov A, Crcl
  221. rrc A
  222. mov Crcl, A
  223. jnc put2
  224. xrl Crch, #high(POLYNOM)
  225. xrl Crcl, #low(POLYNOM)
  226. put2:djnz Bit_Cnt, put1
  227. ; Send char
  228. putc:acall waitf
  229. acall waitf
  230. mov Bit_Cnt, #10
  231. mov A, Paral
  232. cpl A
  233. put3:jb Bit_Reg.1, ($+5)
  234. setb RTX_PORT.RTX_PIN ; Set pin high
  235. jnb Bit_Reg.1, ($+5)
  236. clr RTX_PORT.RTX_PIN ; Set pin low
  237. acall waitf
  238. clr C
  239. rrc A
  240. jc put4
  241. clr Bit_Reg.1
  242. put4:djnz Bit_Cnt, put3
  243. ret
  244. ; Receive char/word
  245. getw:acall getc
  246. mov A, Paral
  247. mov Parah, A
  248. getc:jb RTX_PORT.RTX_PIN, ($+5) ; Wait for high
  249. ajmp getc
  250. get1:jnb RTX_PORT.RTX_PIN, ($+5) ; Wait for low
  251. ajmp get1
  252. getx:mov Bit_Cnt, #8
  253. mov Cntl, Baudl
  254. mov Cnth, Baudh
  255. clr C
  256. mov A, Cnth ; Wait half a baud
  257. rrc A
  258. mov Cnth, A
  259. mov A, Cntl
  260. rrc A
  261. mov Cntl, A
  262. acall waith
  263. get2:acall waitf ; Wait one baud
  264. clr C
  265. mov A, Paral
  266. rrc A
  267. jnb RTX_PORT.RTX_PIN, ($+5)
  268. orl A, #080h
  269. mov Paral, A
  270. jnb ACC.7, ($+6)
  271. xrl Crcl, #low(POLYNOM)
  272. clr C
  273. mov A, Crch
  274. rrc A
  275. mov Crch, A
  276. mov A, Crcl
  277. rrc A
  278. mov Crcl, A
  279. jnc get3
  280. xrl Crch, #high(POLYNOM)
  281. xrl Crcl, #low(POLYNOM)
  282. get3:djnz Bit_Cnt, get2
  283. mov A, Crcl
  284. xrl A, Crch
  285. xrl A, Crch
  286. mov Crcl, A
  287. ret
  288. ; UART delays
  289. waitf:mov Cntl, Baudl
  290. mov Cnth, Baudh
  291. waith:inc Cntl
  292. inc Cnth
  293. wait1:djnz Cntl, wait1
  294. djnz Cnth, wait1
  295. setb Bit_Reg.1
  296. ret
  297. BOOT_SIGN: DB "BLHeli"
  298. IF WAIT_START_ON_RX_HIGH
  299. BOOT_MSG: DB "471a" ; Interface-MCU_BootlaoderRevision
  300. ELSE
  301. BOOT_MSG: DB "4712" ; Interface-MCU_BootlaoderRevision
  302. ENDIF
  303. BOOT_INFO: DB SIGNATURE_001, SIGNATURE_002, BOOT_VERSION, BOOT_PAGES