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.

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