Comment compresser le chargeur de démarrage pour STM8 à une taille de 8 octets dans la mémoire FLASH

Depuis la rédaction de l'article précédent, «Comment compresser le chargeur de démarrage STM8 à 18 octets dans la mémoire FLASH» , deux versions du chargeur de démarrage STM8uLoader sont apparues . La version $ 36 du chargeur de démarrage STM8uLoader a appris à transférer le contrôle d'un programme d'application à n'importe quelle adresse en mémoire RAM sans la participation d'un programme hôte. La taille de 18 octets du chargeur de démarrage dans la mémoire FLASH n'a pas changé; dans la zone OPTION Bytes, la taille est passée à 53 octets (il occupait tout l'espace disponible).

Une branche distincte du chargeur de démarrage $ 0D a été allouée. La principale exigence de cette version est de compresser le code autant que possible. À ce jour, la taille du code dans la mémoire FLASH est de 8 octets dans la mémoire EEPROM de 35 octets.

Permettez-moi de vous rappeler l'architecture du chargeur de démarrage STM8uLoader. Le chargeur de démarrage se compose du programme hôte boot_PC et du code du chargeur de démarrage boot_uC dans la mémoire STM8. Ce dernier est divisé en le code de copie initiale boot_FLASH situé dans la mémoire FLASH et le code de chargeur de démarrage boot_EEPROM (ou boot_OPTION) situé dans la mémoire EEPROM (ou zone OPTION Bytes).

Après l'événement RESET, le copieur initial boot_FLASH est lancé, transfère l'image du code du chargeur de démarrage boot_EEPROM (ou boot_OPTION) dans la mémoire RAM et transfère le contrôle à celle-ci. Le chargeur de démarrage configure l'UART transfère l'octet hôte au programme avec son numéro de version et, s'il ne reçoit pas d'informations du programme hôte pendant le délai d'expiration, transfère le contrôle au programme d'application dans la mémoire FLASH. Ou transfère le code d'application de la mémoire EEPROM (ou de la zone OPTION Bytes) vers la mémoire RAM et y transfère le contrôle.

Si, après avoir envoyé l'octet avec le numéro de version au programme hôte, le chargeur de démarrage reçoit un vidage avec un code via UART, il le place dans la mémoire RAM et transfère le contrôle. Le vidage accepté avec le code remplit sa tâche actuelle: lire / copier / effacer / écrire des cellules STM8, transférer le contrôle à l'adresse spécifiée avec l'initialisation préliminaire des registres du noyau STM8, transférer le contrôle au chargeur de démarrage pour modifier le vidage actuel dans la mémoire RAM par le programme hôte.

Copieur initial boot_FLASH rev. $ 0D est situé aux adresses $ 8000 ... $ 8007 et occupe complètement les vecteurs RESET et TRAP (interruption logicielle). Le reste de l'espace $ 8008 ... $ 9FFF de mémoire FLASH est entièrement accessible au programme d'application. La table des vecteurs d'interruption est également en place.

Considérez le code copiste:

;   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 

Le code de deux commandes se croise ici: les commandes ldw X, # $ 4088 (ldw X, # $ 4188) et le push A. . Cette solution a économisé un octet, mais a conduit à un rétrécissement de la zone de stockage de la table avec l'image du code du chargeur de démarrage. L'octet bas de 88 $ de l'adresse de la table ne permet pas de la placer dans la zone OPTION Bytes. Pour le modèle STM8S103F3, seules les adresses $ 4088 et $ 4188 sont disponibles dans la mémoire EEPROM pour accueillir la table spécifiée. Pour les propriétaires de STM8S003F3 avec mémoire EEPROM 128 octets (4000 $ ... 407F $) et ces adresses ne sont pas disponibles. Il y a encore une faille pour eux.

Il vous suffit d'échanger les commandes push A et decw X:

 ;   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 


Ici, lorsque vous entrez pour la première fois dans la boucle, la commande ldw X, # $ 405A ($ 415A, $ 425A) est exécutée et la commande decw X n'est pas exécutée.

Rappelez-vous qu'avec l'événement RESET, le pointeur supérieur de la pile SP est initialisé par le matériel avec la valeur $ 03FF. La pile se développe dans le sens des adresses décroissantes. Pour remplir la pile à partir de la queue, nous lirons également le tableau avec le code du chargeur de démarrage de la queue, d'où la commande decw X. L'image du code de chargeur de démarrage dans la mémoire EEPROM se trouve en conséquence.
Pour économiser de l'argent, ils ont abandonné le compteur de boucles. Nous avons convenu que l'image de code du chargeur de démarrage aura un octet zéro uniquement au début de la table, et nous déplacerons l'adresse de transfert de contrôle vers le programme d'application (qui peut avoir zéro octet) en dehors de la table. À chaque itération, nous lisons l'octet de la table et s'il n'est pas nul, le poussons sur la pile. Lire zéro octet - condition de sortie de la boucle.

La commande ret signifie ici passer le contrôle à l'adresse contenue dans les deux derniers octets de la pile. Considérez maintenant le code du chargeur de démarrage:

 ;   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] 


Les adresses du code après la copie dans la pile sont indiquées entre parenthèses. Le premier est un octet zéro, la RAM n'est pas copiée. Voici l'adresse du transfert de contrôle au chargeur de démarrage, en fait, c'est l'adresse de la cellule suivante dans la mémoire RAM. Cette paire pénètre dans la pile, mais elle est alors remplacée par le code du prochain vidage du programme hôte comme inutile. Tout le code suivant est également copié sur la pile, à l'exception d'une paire avec l'adresse de transfert de contrôle de l'application
Voici l'initialisation de l'UART. Ici, dans les trois registres, le même numéro $ 0D est placé. Dans le premier cas, il s'agit de la vitesse UART (16000000/8/9600/16 = 13). Dans le second cas, il s'agit de l'autorisation de transmission / réception, ici une locomotive à vapeur a capturé une génération unique de l'événement BREAK. Dans ce dernier cas, cela envoie la version hôte du chargeur au programme. En fait, le programme hôte recevra deux octets $ 00 (événement BREAK) et $ 0D (numéro de version du chargeur de démarrage) - c'est un signal que vous pouvez envoyer un vidage avec un code.

Le registre A avec le contenu de $ 0D remplit alors les fonctions d'un compteur d'octets reçus et il les compte avec un incrément à zéro, ce qui équivaut à 243 octets reçus. C'est avec cette taille que le programme hôte doit envoyer des vidages avec du code.

Le registre d'index X dans le copiste initial comptait jusqu'à 4068 $. Maintenant, il augmentera également à zéro (il reste 49048), en comptant le temps alloué au chargeur de démarrage. Pendant ce temps, le chargeur de démarrage devrait avoir le temps d'accepter un vidage avec un code de 243 octets et de le placer plus loin sur la pile et de lui transférer le contrôle. Sinon, le contrôle sera transféré au programme d'application et vous devrez appuyer à nouveau sur le bouton de réinitialisation et redémarrer le programme hôte.

Après avoir transféré le contrôle au vidage reçu, le code du chargeur de démarrage reste sur la pile et reprend le contrôle lorsque le programme hôte décide de remplacer le vidage par le code. Tout vidage reçu avec un code se trouve sur la pile aux adresses $ 02ED ... $ 03DF et prend le contrôle à l'adresse $ 02F0. Le code du chargeur de démarrage est situé sur la pile aux adresses $ 03E0 ... $ 03FF, initialement il prend le contrôle à l'adresse $ 03E0, et si nécessaire, le vidage avec le code est appelé à l'adresse $ 03E8.
La commande de transfert de contrôle vers l'application se trouve sur la pile à $ 03FB.
Une cellule avec l'adresse $ 03FF peut être utilisée par le vidage en cours.

Le code source complet du copieur et chargeur de démarrage initial en version STM8 $ 0D avec une table en mémoire EEPROM aux adresses $ 4039 ... $ 405C ($ 4139 ... $ 415C, $ 4239 ... $ 425C).

Fichier 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 



Le code source complet du copiste et chargeur de démarrage initial dans la version STM8 $ 0D avec une table en mémoire EEPROM aux adresses $ 4065 ... $ 4088 ($ 4165 ... $ 4188).

Fichier 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 



Nous décrivons le programme d'application le plus simple à exécuter dans la mémoire FLASH de STM8.

Fichier 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 



Coudre le chargeur de démarrage du programmeur dans STM8. Nous connectons la carte à l'adaptateur USB-TTL (UART). Exécutez le fichier de commandes runSTM8uLoader.bat . Appuyez sur le bouton de réinitialisation sur la carte. On observe le résultat:



Le code d'application est flashé par le chargeur dans la mémoire FLASH, l'appareil redémarre. La LED commence à clignoter.

Exemples de codes source de vidage que le programme hôte envoie au chargeur pour exécution dans la mémoire RAM:

Fichier 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 



Fichier 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 



Fichier 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 



Dans le code source du programme hôte, ces mêmes vidages sont présents sous la forme suivante:

  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 }; 


Article précédent: "Comment compresser le chargeur de démarrage pour STM8 à une taille de 18 octets dans la mémoire FLASH . "
Site Web avec le projet http://nflic.ru/STM8/STM8uLoader/000.html .
Projet sur https://sourceforge.net/projects/ovsp .
Projet sur https://github.com/ovsp/STM8uLoader .

Je demande aux lecteurs des critiques ciblées et des suggestions pour une réduction supplémentaire du code.

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


All Articles