So komprimieren Sie den Bootloader für STM8 auf eine Größe von 8 Byte im FLASH-Speicher

Seit dem Schreiben des vorherigen Artikels Komprimieren des STM8- Bootloaders auf 18 Byte im FLASH-Speicher“ sind zwei Versionen des STM8uLoader- Bootloaders erschienen . Der STM8uLoader-Bootloader, Version 36, hat gelernt, wie die Steuerung eines Anwendungsprogramms ohne Teilnahme eines Host-Programms an eine beliebige Adresse im RAM-Speicher übertragen werden kann. Die Größe von 18 Bytes des Bootloaders im FLASH-Speicher hat sich nicht geändert. Im Bereich OPTION Bytes wurde die Größe auf 53 Byte erhöht (es wurde der gesamte verfügbare Speicherplatz belegt).

Ein separater Zweig des $ 0D- Bootloaders wurde zugewiesen. Die Hauptanforderung für diese Version besteht darin, den Code so weit wie möglich zu komprimieren. Bisher beträgt die Codegröße im FLASH-Speicher 8 Byte im EEPROM-Speicher von 35 Byte.

Ich möchte Sie an die Architektur des STM8uLoader-Bootloaders erinnern. Der Bootloader besteht aus dem Boot_PC-Hostprogramm und dem Boot_uC-Bootloader-Code im STM8-Speicher. Letzteres ist unterteilt in den anfänglichen Kopiercode boot_FLASH im FLASH-Speicher und den Bootloader-Code boot_EEPROM (oder boot_OPTION) im EEPROM-Speicher (oder im Bereich OPTION Bytes).

Nach dem RESET-Ereignis wird der anfängliche Kopierer boot_FLASH gestartet, das Bootloader-Code-Image boot_EEPROM (oder boot_OPTION) in den RAM-Speicher übertragen und die Steuerung an diesen übertragen. Der Bootloader konfiguriert, dass der UART das Hostprogrammbyte mit seiner Versionsnummer überträgt. Wenn er während des Timeouts keine Informationen vom Hostprogramm empfängt, überträgt er die Steuerung an das Anwendungsprogramm im FLASH-Speicher. Oder überträgt den Anwendungscode vom EEPROM-Speicher (oder dem Bereich OPTION Bytes) in den RAM-Speicher und überträgt die Steuerung an diesen.

Wenn der Bootloader nach dem Senden des Bytes mit der Versionsnummer an das Host-Programm einen Speicherauszug mit einem Code über UART empfängt, legt er diesen im RAM-Speicher ab und überträgt die Steuerung. Der akzeptierte Speicherauszug mit dem Code führt seine aktuelle Aufgabe aus: Lesen / Kopieren / Löschen / Schreiben von STM8-Zellen, Übertragen der Steuerung an die angegebene Adresse mit vorläufiger Initialisierung der STM8-Kernelregister, Übertragen der Steuerung an den Bootloader, um den aktuellen Speicherauszug im RAM-Speicher durch das Hostprogramm zu ändern.

Erstkopierer boot_FLASH rev. $ 0D befindet sich an den Adressen $ 8000 ... $ 8007 und belegt die Vektoren RESET und TRAP (Software Interrupt) vollständig. Der Rest des Speicherplatzes $ 8008 ... $ 9FFF des FLASH-Speichers ist für das Anwendungsprogramm vollständig zugänglich. Die Interrupt-Vektortabelle ist ebenfalls vorhanden.

Betrachten Sie den Kopistencode:

;   boot_FLASH  $0D($88) ;       $4087($4187) ;       $00 ;     segment byte at 8000-8007 'bootF_rev0D' ; $8000 RESET Reset vector dc.b $AE, $40 ; [AE 40 88] ldw X,#$4088 ; dc.b $AE, $41 ; [AE 41 88] ldw X,#$4188 cycle: ;      ;  push A   ldw X,#$4088($4188) push A ; [88] decw X ; [5A] ; $8004 TRAP Software interrupt ld A, (X) ; [F6] jrne cycle ; [26 FB] ret ; [81] ; $8008 TLI IRQ0 External top level interrupt 

Der Code von zwei Befehlen schneidet sich hier: die Befehle ldw X, # $ 4088 (ldw X, # $ 4188) und der Push A. . Diese Lösung sparte ein Byte, führte jedoch zu einer Verengung des Tabellenspeicherbereichs mit dem Image des Bootloader-Codes. Das niedrige Byte von $ 88 der Adresse der Tabelle erlaubt es nicht, sie im Bereich OPTION Bytes zu platzieren. Für das Modell STM8S103F3 sind im EEPROM-Speicher nur Adressen im Wert von 4088 USD und 4188 USD verfügbar, um die angegebene Tabelle aufzunehmen. Für Besitzer von STM8S003F3 mit EEPROM-Speicher 128 Bytes ($ 4000 ... $ 407F) und diese Adressen sind nicht verfügbar. Es gibt immer noch eine Lücke für sie.

Sie müssen nur die Befehle push A und decw X austauschen:

 ;   boot_FLASH  $0D($5A) ;       $405A($415A, $425A) ;       $00 ;     segment byte at 8000-8007 'bootF_rev0D' ; $8000 RESET Reset vector dc.b $AE, $40 ; [AE 40 5A] ldw X,#$405A  STM8S003F3 ; dc.b $AE, $41 ; [AE 41 5A] ldw X,#$415A ; dc.b $AE, $41 ; [AE 42 5A] ldw X,#$425A cycle: ;      ;  decw X   ldw X,#$405A($415A, $425A) decw X ; [5A] push A ; [88] ; $8004 TRAP Software interrupt ld A, (X) ; [F6] jrne cycle ; [26 FB] ret ; [81] ; $8008 TLI IRQ0 External top level interrupt 


Hier wird beim ersten Betreten der Schleife der Befehl ldw X, # $ 405A ($ 415A, $ 425A) ausgeführt, und der Befehl decw X wird nicht ausgeführt.

Denken Sie daran, dass beim RESET-Ereignis der oberste Zeiger des SP-Stapels mit dem Wert $ 03FF hardwareinitialisiert wird. Der Stapel wächst in Richtung abnehmender Adressen. Um den Stapel vom Ende aus zu füllen, lesen wir auch die Tabelle mit dem Bootloader-Code vom Ende, daher der Befehl decw X. Das Image des Bootloader-Codes im EEPROM-Speicher befindet sich entsprechend.
Um Geld zu sparen, gaben sie den Schleifenzähler auf. Wir haben vereinbart, dass das Code-Image des Bootloaders nur am Anfang der Tabelle ein Null-Byte hat, und wir werden die Steuerübertragungsadresse in das Anwendungsprogramm (das möglicherweise ein Null-Byte enthält) außerhalb der Tabelle verschieben. Bei jeder Iteration lesen wir das Byte aus der Tabelle und schieben es auf den Stapel, wenn es nicht Null ist. Lesen Sie die Null-Byte-Bedingung für das Verlassen der Schleife.

Der Befehl ret bedeutet hier, die Kontrolle an die Adresse zu übergeben, die in den beiden Bytes enthalten ist, die zuletzt auf dem Stapel waren. Betrachten Sie nun den Bootloader-Code:

 ;   boot_EEPROM  $0D($88) segment byte at 4067-4089 'bootE_rev0D_88' ; segment byte at 417B-4189 'bootE_rev0D_88' ; $4067 terminator    RAM dc.b $00 ; [00] ; $4068 ($03E0) {RAM END - 31} ; {$0400 - (bootE_go_adr - bootE_start) } dc.w $03E2 ; [03 E2] $4067 - $3C85 = $03E2 ;  UART 96001N8 ;  BREAK    $0D bootE_start: ; $406A ($03E2) {RAM END - 29} ld A, #%00001101 ; [A6 0D] ld UART1_BRR1, A ; [C7 52 32] ld UART1_CR2, A ; [C7 52 35] ld UART1_DR, A ; [C7 52 31] ;     243  ;  n    ; $4075 ($03ED) {RAM END - 18} bootE_rx_byte: incw X ; [5C] jreq bootE_exit ; [27 0C] btjf UART1_SR, #5, bootE_rx_byte ; [72 0B 52 30 F8] push UART1_DR ; [3B 52 31] ; clrw X ; [5F] inc A ; [4C] jrne bootE_rx_byte ; [26 F2] ;     ;   $02F1 (     $FE $02) ret ; [81] ; $4084 ($03FC) {RAM END - 3} bootE_exit: jp [bootE_go_adr] ; [72 CC 40 88] RAM END ;      ; $4088    RAM bootE_go_adr: dc.w main_flash ; [80 08] 


Die Adressen des Codes nach dem Kopieren auf den Stapel werden in Klammern angezeigt. Das erste ist ein Null-Byte, RAM wird nicht in den Speicher kopiert. Es folgt die Adresse der Übertragung der Steuerung an den Bootloader. Tatsächlich ist dies die Adresse der nächsten Zelle im RAM. Dieses Paar wird in den Stapel aufgenommen, aber dann wird es durch den Code des nächsten Speicherauszugs aus dem Host-Programm als unnötig überschrieben. Der gesamte nachfolgende Code wird ebenfalls auf den Stapel kopiert, mit Ausnahme eines Paares mit der Steuerübertragungsadresse der Anwendung
Es folgt die Initialisierung von UART. Hier in allen drei Registern wird die gleiche Nummer $ 0D platziert. Im ersten Fall ist dies die UART-Geschwindigkeit (16000000/8/9600/16 = 13). Im zweiten Fall ist dies die Erlaubnis zum Senden / Empfangen, hier hat eine Dampflokomotive eine einmalige Generation des BREAK-Ereignisses gefangen. Im letzteren Fall wird die Host-Version des Loaders an das Programm gesendet. Tatsächlich empfängt das Host-Programm zwei Bytes $ 00 (Ereignis BREAK) und $ 0D (Versionsnummer des Bootloaders) - dies ist ein Signal, dass Sie einen Speicherauszug mit einem Code senden können.

Register A mit dem Inhalt von $ 0D führt dann die Funktionen eines Zählers empfangener Bytes aus und zählt sie mit einem Inkrement auf Null, was 243 empfangenen Bytes entspricht. Bei dieser Größe sollte das Host-Programm Dumps mit Code senden.

Das Indexregister X im ursprünglichen Kopierer zählte bis zu 4068 USD. Jetzt wird es auch auf Null erhöht (49048 verbleiben noch) und die dem Bootloader zugewiesene Zeit gezählt. Während dieser Zeit sollte der Bootloader Zeit haben, einen Speicherauszug mit einem Code von 243 Byte zu akzeptieren, ihn weiter auf dem Stapel zu platzieren und die Steuerung darauf zu übertragen. Andernfalls wird die Steuerung an das Anwendungsprogramm übertragen und Sie müssen die Reset-Taste erneut drücken und das Host-Programm neu starten.

Nach der Übertragung der Kontrolle auf den empfangenen Speicherauszug verbleibt der Bootloader-Code auf dem Stapel und übernimmt erneut die Kontrolle, wenn das Host-Programm beschließt, den Speicherauszug durch den Code zu ersetzen. Jeder empfangene Speicherauszug mit einem Code befindet sich auf dem Stapel unter den Adressen $ 02ED ... $ 03DF und übernimmt die Kontrolle unter der Adresse $ 02F0. Der Bootloader-Code befindet sich auf dem Stapel unter den Adressen $ 03E0 ... $ 03FF, zunächst übernimmt er die Kontrolle unter der Adresse $ 03E0, und bei Bedarf wird der Speicherauszug mit dem Code unter der Adresse $ 03E8 aufgerufen.
Der Steuerübertragungsbefehl an die Anwendung befindet sich auf dem Stapel bei $ 03FB.
Eine Zelle mit der Adresse $ 03FF kann vom aktuellen Speicherauszug verwendet werden.

Der gesamte Quellcode des ersten Kopierers und Bootloaders in STM8-Version $ 0D mit einer Tabelle im EEPROM-Speicher unter den Adressen $ 4039 ... $ 405C ($ 4139 ... $ 415C, $ 4239 ... $ 425C).

Datei bootF_rev0D_5A.asm:
 stm8/ TITLE “bootF_rev0D_5A.asm” MOTOROLA WORDS .NOLIST ; #include "STM8S003F.inc" #include "STM8S103F.inc" .LIST ;   boot_EEPROM  $0D($5A) segment byte at 4039-405C 'bootE_rev0D_405A' ; STM8S003F ; segment byte at 4139-415C 'bootE_rev0D_415A' ; segment byte at 4239-425C 'bootE_rev0D_425A' ; $403A9 ($03DD) {RAM END - 34} terminator   RAM ????? dc.b $00 ; [00] ; $403A ($03DE) {RAM END - 33} ; {$0400 - (bootE_go_adr - bootE_start - 1) } dc.w $03E0 ; [03 E0] ;  UART 96001N8 ;  BREAK    $0D bootE_start: ; $403C ($03E0) {RAM END - 31} ld A, #%00001101 ; [A6 0D] ld UART1_BRR1, A ; [C7 52 32] ld UART1_CR2, A ; [C7 52 35] ; $4044 ($03E8) {RAM END - 23} ld UART1_DR, A ; [C7 52 31] ;    243  ;  n    ; $40487 ($03EB) {RAM END - 20} bootE_rx_byte: incw X ; [5C] jreq bootE_exit ; [27 0C] btjf UART1_SR, #5, bootE_rx_byte ; [72 0B 52 30 F8] push UART1_DR ; [3B 52 31] clrw X ; [5F] inc A ; [4C] jrne bootE_rx_byte ; [26 F2] ;     ;   $02EF (     $EF $02) ; $4056 ($03FA) {RAM END - 5} ret ; [81] ; $4057 ($03FB) {RAM END - 4} bootE_exit: jp [bootE_go_adr] ; [72 CC 40 5B] {RAM END - 1} ; ($03FF) RAM END     ;      ; $405B    RAM bootE_go_adr: dc.w main_flash ; [80 08] ;   boot_FLASH  $0D($5A) ;       $405A($415A,$425A) ;       $00 ;     segment byte at 8000-8007 'bootF_rev0D' ; $8000 RESET Reset vector dc.b $AE, $40 ; [AE 40 5A] ldw X,#$405A ; STM8S003F ; dc.b $AE, $41 ; [AE 41 5A] ldw X,#$415A ; dc.b $AE, $42 ; [AE 42 5A] ldw X,#$425A cycle: ;      ;  dec X   ldw X,#$405A($415A,$425A) decw X ; [5A] push A ; [88] ; $8004 TRAP Software interrupt ld A, (X) ; [F6] jrne cycle ; [26 FB] ret ; [81] ; $8008 TLI IRQ0 External top level interrupt ;   segment byte at 8008 'main_flash' main_flash: jra * ; [20 FE] ; end ; bootF_rev0D_5A.asm 



Der gesamte Quellcode des ersten Kopisten und Bootloaders in der STM8-Version $ 0D mit einer Tabelle im EEPROM-Speicher unter den Adressen $ 4065 ... $ 4088 ($ 4165 ... $ 4188).

Datei bootF_rev0D_88.asm:
 stm8/ TITLE “bootF_rev0D_88.asm” MOTOROLA WORDS .NOLIST ; #include "STM8S003F.inc" #include "STM8S103F.inc" .LIST ;   boot_EEPROM  $0D($88) segment byte at 4065-4088 'bootE_rev0D_88' ; segment byte at 4165-4188 'bootE_rev0D_88' ; $4065 terminator    RAM dc.b $00 ; [00] ; $4066 ($03DE) {RAM END - 33} ; {$0400 - (bootE_go_adr - bootE_start) } dc.w $03E0 ; [03 E0] ;  UART 9600 1N8 ;  BREAK    $0D bootE_start: ; $4068 ($03E0) {RAM END - 31} ld A, #%00001101 ; [A6 0D] ld UART1_BRR1, A ; [C7 52 32] ld UART1_CR2, A ; [C7 52 35] ; $4070 ($03E8) {RAM END - 23} ld UART1_DR, A ; [C7 52 31] ;    243  ;  n    ; $4073 ($03EB) {RAM END - 20} bootE_rx_byte: incw X ; [5C] jreq bootE_exit ; [27 0C] btjf UART1_SR, #5, bootE_rx_byte ; [72 0B 52 30 F8] push UART1_DR ; [3B 52 31] clrw X ; [5F] inc A ; [4C] jrne bootE_rx_byte ; [26 F2] ;     ;   $02EF (     $EF $02) ; $4082 ($03FA) {RAM END - 5} ret ; [81] ; $4083 ($03FB) {RAM END - 4} bootE_exit: jp [bootE_go_adr] ; [72 CC 40 87] {RAM END - 1} ; ($03FF) RAM END     ;      ; $4087 ($4088 )   RAM bootE_go_adr: dc.w main_flash ; [80 08] ;   boot_FLASH  $0D($88) ;       $4087($4187) ;       $00 ;     segment byte at 8000-8007 'bootF_rev0D' ; $8000 RESET Reset vector dc.b $AE, $40 ; [AE 40] ldw X,#$4088 ; dc.b $AE, $41 ; [AE 41] ldw X,#$4188 cycle: ;      ;  push A   ldw X,#$4088($4188) push A ; [88] decw X ; [5A] ; $8004 TRAP Software interrupt ld A, (X) ; [F6] jrne cycle ; [26 FB] ret ; [81] ; $8008 TLI IRQ0 External top level interrupt ;   segment byte at 8008 'main_flash' main_flash: jra * ; [20 FE] end ; bootF_rev0D_88.asm 



Wir beschreiben das einfachste Anwendungsprogramm für die Ausführung im FLASH-Speicher von STM8.

Datei main_rev0D.asm:
 stm8/ TITLE “main_rev0D.asm” MOTOROLA WORDS .NOLIST #include "STM8S103F.inc" .LIST ;   segment byte at 8008-9FFF 'main_flash' main_flash: main_cycle: ;   bset PB_DDR,#5 ; bset PB_CR1,#5 ; callr flash_delay ;   bres PB_DDR,#5 ; bres PB_CR1,#5 ; callr flash_delay jra main_cycle flash_delay: ldw X, #35000 flash_delay_cycle: decw X jrne flash_delay_cycle ret end ; main_rev0D.asm 



Nähen Sie den Programmierer-Bootloader in STM8. Wir verbinden die Karte mit dem USB-TTL-Adapter (UART). Führen Sie die Batchdatei runSTM8uLoader.bat aus . Drücken Sie die Reset-Taste auf der Karte. Wir beobachten das Ergebnis:



Der Anwendungscode wird vom Loader in den FLASH-Speicher geflasht, das Gerät wird neu gestartet. Die LED beginnt zu blinken.

Beispiele für Dump-Quellcodes, die das Host-Programm zur Ausführung im RAM-Speicher an den Loader sendet:

Datei Read_128000v0D.asm:
 stm8/ TITLE "Read_128000v0D.asm" MOTOROLA WORDS .NOLIST #include "STM8S103F3P.inc" .LIST ;     243  ;        $02EE...$03DF ; (  $03DF:$03E0      ) ;     $02F0 ;        $03E1...$03FE ;        $03E1 (   9600,  A<=$0D SP<=$03E0 X<=$0000) ;    $03E9 (  ,  A<=$0D SP<=$03E8 X<=$0000) ;       $03FB segment byte at 0000-00F2 'ram0' dc.w $02F0 start: ;  UART1  /   9600,     (8 ,   , 1  ) mov UART1_BRR2, #0 ; [35 00 52 33]  Fmaster=16/8=2  128000 mov UART1_BRR1, #1 ; [35 0D 52 32]  Fmaster=16/8=2  128000 mov UART1_CR2, #%00001100 ; [35 0C 52 35] UART1_CR2.TEN <- 1 UART1_CR2.REN <- 1  / main_cycle: wait_byte_adrH_cmnd: btjf UART1_SR, #5, wait_byte_adrH_cmnd ld A, UART1_DR cp A, #$EF JRUGT wait_byte_cmd_test ; Relative jump if Unsigned Greater Than ld XH, A ;     XH ld UART1_DR, A ;     tx_echo_adrH: btjf UART1_SR, #7, tx_echo_adrH ; skip if UART1_SR.TXE = 0 TXE: Transmit data register empty wait_byte_adrL: btjf UART1_SR, #5, wait_byte_adrL ld A, UART1_DR ld XL, A ;     XL wait_byte_cntr: btjf UART1_SR, #5, wait_byte_cntr ld A, #$00 ld YH, A ; ld A, UART1_DR ld YL, A ;  ;   bset PB_DDR,#5 ; bset PB_CR1,#5 ; ; read_block_cycle: ld A, (X) ld UART1_DR, A wait_tx: btjf UART1_SR, #7, wait_tx ; skip if UART1_SR.TXE = 0 TXE: Transmit data register empty incw X decw Y jrne read_block_cycle ;   bres PB_DDR,#5 ; bres PB_CR1,#5 ; jra main_cycle ;    $F0   wait_byte_cmd_test: cp A, #$F5 ;   jreq echo_F5cmd wait_tx_err: mov UART1_DR, #$F1 ;   btjf UART1_SR, #7, wait_tx_err ; skip if UART1_SR.TXE = 0 TXE: Transmit data register empty jra main_cycle echo_F5cmd: ld UART1_DR, A ;    wait_tx_echo_F5cmd: btjf UART1_SR, #7, wait_tx_echo_F5cmd ; skip if UART1_SR.TXE = 0 TXE: Transmit data register empty ; GoAdr wait_byte_adrH_toM; btjf UART1_SR, #5, wait_byte_adrH_toM mov $03E7, UART1_DR wait_byte_adrL_toM; btjf UART1_SR, #5, wait_byte_adrL_toM mov $03E8, UART1_DR ; SP wait_byte_adrH_toSP; btjf UART1_SR, #5, wait_byte_adrH_toSP ld A, UART1_DR ld XH, A wait_byte_adrL_toSP; btjf UART1_SR, #5, wait_byte_adrL_toSP ld A, UART1_DR ld XL, A ldw SP, X ; Y wait_byte_adrH_toY; ; btjf UART1_SR, #5, wait_byte_adrH_toY ; ld A, UART1_DR ; ld YH, A wait_byte_adrL_toY; ; btjf UART1_SR, #5, wait_byte_adrL_toY ; ld A, UART1_DR ; ld YL, A ; X wait_byte_adrH_toX; btjf UART1_SR, #5, wait_byte_adrH_toX ld A, UART1_DR ld XH, A wait_byte_adrL_toX; btjf UART1_SR, #5, wait_byte_adrL_toX ld A, UART1_DR ld XL, A ; A wait_byte_cntr_toA; btjf UART1_SR, #5, wait_byte_cntr_toA ld A, UART1_DR jp [$03E7.w] SKIP 59, $00 ;     dc.b $00 dc.b $00 end ; Read_128000v0D.asm 



Datei WriteBlocks_FLASH_128000v0D.asm:
 stm8/ TITLE "WriteBlocks_FLASH_128000v0D.asm" MOTOROLA WORDS .NOLIST #include "STM8S103F3P.inc" .LIST ;     243  ;        $02EE...$03DF ; (  $03DF:$03E0      ) ;     $02F0 ;        $03E1...$03FE ;        $03E1 (   9600,  A<=$0D SP<=$03E0 X<=$0000) ;    $03E9 (  ,  A<=$0D SP<=$03E8 X<=$0000) ;       $03FB segment byte at 0000-00F2 'ram0' dc.w $02F0 start: ;  UART1  /   9600,     (8 ,   , 1  ) mov UART1_BRR2, #0 ; [35 00 52 33]  Fmaster=16/8=2  128000 mov UART1_BRR1, #1 ; [35 0D 52 32]  Fmaster=16/8=2  128000 mov UART1_CR2, #%00001100 ; [35 0C 52 35] UART1_CR2.TEN <- 1 UART1_CR2.REN <- 1  / main_cycle: wait_byte_adrH_cmnd: btjf UART1_SR, #5, wait_byte_adrH_cmnd ld A, UART1_DR cp A, #$F0 JRUGE wait_byte_cmd_test ; Relative jump if Unsigned Greater or Equal ld XH, A ;     XH ld UART1_DR, A ;     tx_echo_adrH: btjf UART1_SR, #7, tx_echo_adrH ; skip if UART1_SR.TXE = 0 TXE: Transmit data register empty wait_byte_adrL: btjf UART1_SR, #5, wait_byte_adrL ld A, UART1_DR ld XL, A ;     XL wait_byte_cntr: btjf UART1_SR, #5, wait_byte_cntr ;   mov $03FF, UART1_DR write_block_cycle: ldw Y, #64 ;   ; unlock FLASH memory (writing the correct MASS keys) mov FLASH_PUKR, #$56 ; Write $56 then $AE in FLASH_PUKR($5062) mov FLASH_PUKR, #$AE ; If wrong keys have been entered, another key programming sequence can be issued without resetting the device. ; FLASH Block programming mode       mov FLASH_CR2, #$01 mov FLASH_NCR2, #$FE ; ; FLASH Word programming mode       ; mov FLASH_CR2, #$40 ; mov FLASH_NCR2, #$BF ; else FLASH byte programming ;   bset PB_DDR,#5 ; bset PB_CR1,#5 ; ;        ;          wait_rx_byte: btjf UART1_SR, #5, wait_rx_byte ld A, UART1_DR ld (X), A incw X decw Y jrne wait_rx_byte mov UART1_DR, #$FA ; OK wait_tx_OK_FA: btjf UART1_SR, #7, wait_tx_OK_FA ; skip if UART1_SR.TXE = 0 TXE: Transmit data register empty ;   bres PB_DDR,#5 ; bres PB_CR1,#5 ; dec $03FF jrne write_block_cycle jra main_cycle ;    $F0   wait_byte_cmd_test: cp A, #$F5 ;    boot_OPTION jreq echo_F5cmd wait_tx_err: mov UART1_DR, #$F1 ;   wait_tx_err_F1: btjf UART1_SR, #7, wait_tx_err_F1 ; skip if UART1_SR.TXE = 0 TXE: Transmit data register empty jra main_cycle echo_F5cmd: ld UART1_DR, A ;     boot_OPTION wait_tx_echo_F5cmd: btjf UART1_SR, #7, wait_tx_echo_F5cmd ; skip if UART1_SR.TXE = 0 TXE: Transmit data register empty ; GoAdr wait_byte_adrH_toM; btjf UART1_SR, #5, wait_byte_adrH_toM mov $03E7, UART1_DR wait_byte_adrL_toM; btjf UART1_SR, #5, wait_byte_adrL_toM mov $03E8, UART1_DR ; SP wait_byte_adrH_toSP; btjf UART1_SR, #5, wait_byte_adrH_toSP ld A, UART1_DR ld XH, A wait_byte_adrL_toSP; btjf UART1_SR, #5, wait_byte_adrL_toSP ld A, UART1_DR ld XL, A ldw SP, X ; Y wait_byte_adrH_toY; ; btjf UART1_SR, #5, wait_byte_adrH_toY ; ld A, UART1_DR ; ld YH, A wait_byte_adrL_toY; ; btjf UART1_SR, #5, wait_byte_adrL_toY ; ld A, UART1_DR ; ld YL, A ; X wait_byte_adrH_toX; btjf UART1_SR, #5, wait_byte_adrH_toX ld A, UART1_DR ld XH, A wait_byte_adrL_toX; btjf UART1_SR, #5, wait_byte_adrL_toX ld A, UART1_DR ld XL, A ; A wait_byte_cntr_toA; btjf UART1_SR, #5, wait_byte_cntr_toA ld A, UART1_DR jp [$03E7.w] SKIP 28, $00 ;     dc.b $00 dc.b $00 end ; WriteBlocks_FLASH_128000v0D.asm 



Datei Reset_128000v0D.asm:
 stm8/ TITLE "Reset_128000v0D.asm" MOTOROLA WORDS .NOLIST #include "STM8S103F3P.inc" .LIST ;     243  ;        $02EE...$03DF ; (  $03DF:$03E0      ) ;     $02F0 ;        $03E1...$03FE ;        $03E1 (   9600,  A<=$0D SP<=$03E0 X<=$0000) ;    $03E9 (  ,  A<=$0D SP<=$03E8 X<=$0000) ;       $03FB segment byte at 0000-00F2 'ram0' dc.w $02F0 start: ;        RESET ldw X, #$03FF ldw SP, X clrw X clrw Y clr A jp $8000 SKIP 230, $00 end ; Reset_128000v0D.asm 



Im Quellcode des Host-Programms sind dieselben Speicherauszüge in der folgenden Form vorhanden:

  public readonly static byte[] Read_128000v0D = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x03, 0xCC, 0x72, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x97, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x95, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x94, 0x97, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x95, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0xE8, 0x03, 0x31, 0x52, 0x55, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0xE7, 0x03, 0x31, 0x52, 0x55, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0xFB, 0x30, 0x52, 0x0F, 0x72, 0x31, 0x52, 0xC7, 0xA5, 0x20, 0xF7, 0x30, 0x52, 0x0F, 0x72, 0x31, 0x52, 0xF1, 0x35, 0x0B, 0x27, 0xF5, 0xA1, 0xB4, 0x20, 0x08, 0x50, 0x1B, 0x72, 0x07, 0x50, 0x1B, 0x72, 0xF2, 0x26, 0x5A, 0x90, 0x5C, 0xFB, 0x30, 0x52, 0x0F, 0x72, 0x31, 0x52, 0xC7, 0xF6, 0x08, 0x50, 0x1A, 0x72, 0x07, 0x50, 0x1A, 0x72, 0x97, 0x90, 0x31, 0x52, 0xC6, 0x95, 0x90, 0x00, 0xA6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x97, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0xFB, 0x30, 0x52, 0x0F, 0x72, 0x31, 0x52, 0xC7, 0x95, 0x40, 0x22, 0xEF, 0xA1, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x35, 0x52, 0x0C, 0x35, 0x32, 0x52, 0x01, 0x35, 0x33, 0x52, 0x00, 0x35, 0xF0, 0x02 }; 

  public readonly static byte[] WriteBlocks_FLASH_128000v0D = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x03, 0xCC, 0x72, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x97, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x95, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x94, 0x97, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x95, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0xE8, 0x03, 0x31, 0x52, 0x55, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0xE7, 0x03, 0x31, 0x52, 0x55, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0xFB, 0x30, 0x52, 0x0F, 0x72, 0x31, 0x52, 0xC7, 0x86, 0x20, 0xFB, 0x30, 0x52, 0x0F, 0x72, 0x31, 0x52, 0xF1, 0x35, 0x0B, 0x27, 0xF5, 0xA1, 0x95, 0x20, 0xBF, 0x26, 0xFF, 0x03, 0x5A, 0x72, 0x08, 0x50, 0x1B, 0x72, 0x07, 0x50, 0x1B, 0x72, 0xFB, 0x30, 0x52, 0x0F, 0x72, 0x31, 0x52, 0xFA, 0x35, 0xF2, 0x26, 0x5A, 0x90, 0x5C, 0xF7, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x08, 0x50, 0x1A, 0x72, 0x07, 0x50, 0x1A, 0x72, 0x5C, 0x50, 0xFE, 0x35, 0x5B, 0x50, 0x01, 0x35, 0x62, 0x50, 0xAE, 0x35, 0x62, 0x50, 0x56, 0x35, 0x40, 0x00, 0xAE, 0x90, 0xFF, 0x03, 0x31, 0x52, 0x55, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x97, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0xFB, 0x30, 0x52, 0x0F, 0x72, 0x31, 0x52, 0xC7, 0x95, 0x5F, 0x24, 0xF0, 0xA1, 0x31, 0x52, 0xC6, 0xFB, 0x30, 0x52, 0x0B, 0x72, 0x35, 0x52, 0x0C, 0x35, 0x32, 0x52, 0x01, 0x35, 0x33, 0x52, 0x00, 0x35, 0xF0, 0x02 }; 

  public readonly static byte[] Reset_128000v0D = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCC, 0x4F, 0x5F, 0x90, 0x5F, 0x94, 0xFF, 0x03, 0xAE, 0xF0, 0x02 }; 


Vorheriger Artikel: "So komprimieren Sie den Bootloader für STM8 auf eine Größe von 18 Byte im FLASH-Speicher . "
Website mit dem Projekt http://nflic.ru/STM8/STM8uLoader/000.html .
Projekt unter https://sourceforge.net/projects/ovsp .
Projekt unter https://github.com/ovsp/STM8uLoader .

Ich bitte die Leser um gezielte Kritik und Vorschläge zur weiteren Code-Reduzierung.

Source: https://habr.com/ru/post/de418483/


All Articles