Tags

arm64 bit blacklistd bluepill bluetooth cu dns dovecot elf envsubst esp8266 filter freebsd ipfw lets_encrypt openocd opensmtpd perl python shell ssh ssl stm32 template tls unbound yubikey

Powered by

blOg
maRkdown
awK
shEll

10/12/2023

[ stm32 openocd ]

202312100800 stm32 openocd

Faire clignoter une LED avec openocd

J'utilise openocd pour communiquer avec mes cartes stm32. N'utilisant ni tcl ni gdb (désolé pour les afficionados valencians j'ai ajouté ces lignes dans mon fichier de configuration:

gdb_port disabled
tcl_port disabled

Il ne me reste donc plus que le telnet en écoute sur le port 4444 pour dialoguer avec mes bestioles, ce que je fais à l'aide de nc:

$ echo 'reset halt' | nc -N 127.0.0.1 4444
$ echo "flash write_image erase ${PWD}/main.bin 0x8000000" | nc -N 127.0.0.1 4444
$ echo 'reset run' | nc -N 127.0.0.1 4444

Pris d'une inspiration aussi divine que soudaine j'ai dernièrement tenté un:

$ echo help | nc -N 127.0.0.1 4444

et quelle ne fût pas ma surprise devant cette avalanche de commandes ! Je suis loin d'en avoir fait le tour mais les suivantes ont attiré mon attention:

mdb ['phys'] address [count]
      display memory bytes
mdd ['phys'] address [count]
      display memory double-words
mdh ['phys'] address [count]
      display memory half-words
mdw ['phys'] address [count]
      display memory words
mwb ['phys'] address value [count]
      write memory byte
mwd ['phys'] address value [count]
      write memory double-word
mwh ['phys'] address value [count]
      write memory half-word
mww ['phys'] address value [count]
      write memory word
reset [run|halt|init]

Le manuel de référence indique, page 172, que la valeur initiale du Port configuration register high vaut 0x4444 4444. Du fait qu'elle soit facilement reconnaissable, c'est cette valeur que je vais tenter d'afficher. Autre information sur cette page, le décalage à appliquer depuis l'adresse de base du GPIO:

Address offset: 0x04

Page 51, on peut lire que l'adresse de base du GPIO Port C se trouve en 0x4001 1000, le registre de configuration se trouve donc en 0x4001 1004. Je vérifie:

$ echo 'reset halt' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> reset halt
target halted due to debug-request, current mode: Thread 
xPSR: 00000000 pc: 00000000 msp: 00000000

$ echo 'reset init' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> reset init
target halted due to debug-request, current mode: Thread 
xPSR: 00000000 pc: 00000000 msp: 00000000

$ echo 'mdw 0x40011004' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> mdw 0x40011004
0x40011004: 44444444

Comme on dit du côté de Valence: Rodriguez ! Autre valeur particulière, page 1087, le DBGMCU_IDCODE à l'adresse 0xE004 2000:

$ echo 'mdw 0xE0042000' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> mdw 0xE0042000
0xe0042000: 20036410

Il s'agit d'une révision 3 (2003) d'un "medium-density device" (0x410). La taille de la mémoire flash (page 1076) sur 16 bits (half-words):

$ echo 'mdh 0x1FFFF7E0' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> mdh 0x1FFFF7E0
0x1ffff7e0: 0080

Et bien sur l'identifiant de la carte, page (1077-1078), 2 x 16 bits + 2 * 32 bits:

$ echo 'mdh 0x1FFFF7E8 2' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> mdh 0x1FFFF7E8 2
0x1ffff7e8: 0048 0024

$ echo 'mdw 0x1FFFF7EC 2' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> mdw 0x1FFFF7EC 2
0x1ffff7ec: 31333911 41373931

La LED PC13

Pour contrôler la PIN 13 du GPIO C je dois d'abord activer ce dernier. Page 106, dans le "APB2 peripheral reset register", on peut voir que le GPIO C correspond au bit 4. Ce registre se situe à 0x18 de l'adresse de base de RCC (Reset and Clock Control) qui se trouve en 0x4002 1000 (page 50). Je commence par vérifier la valeur initiale puis j'active le GPIO:

$ echo 'mdw 0x40021018' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> mdw 0x40021018
0x40021018: 00000000

$ echo 'mww 0x40021018 0x00000010' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> mww 0x40021018 0x00000010

$ echo 'mdw 0x40021018' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> mdw 0x40021018
0x40021018: 00000010

Maintenant que le GPIO est activé, je peux passer la PIN 13 en sortie (Output) depuis le registre de configuration (0x4001 1004, vu plus haut). Pour se faire, les bits 21 et 20 (le "mode") devront avoir pour valeur respective 1 et 0:

$ echo 'mww 0x40011004 0x44644444' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> mww 0x40011004 0x44644444

A ce moment la LED devrait être allumée. Pour changer l'état de la PIN j'utilise les bits 13 et 29 du registre "Port bit set/reset register", page 173, dont le décalage vaut 0x10:

# bit 13 à 1, état haut, LED éteinte
$ echo 'mww 0x40011010 8192' | nc -N 127.0.0.1 4444

# bit 29 à 1, état bas, LED allumée
$ echo 'mww 0x40011010 536870912' | nc -N 127.0.0.1 4444

Pour conclure

Manipuler les bits et les adresses d'un micro-contrôleur reste pour moi une source d'émerveillement dont je doute me lasser un jour. Il existe un lien naturel entre ce monde et celui de l'informatique "générale" qu'illustre parfaitement cette (célèbre ?) sentence:

Fonctions, variables ? Mensonges ! Tout n'est qu'adresse -- iMil

Il ne me reste plus qu'à lire tranquillement la documentation officielle, la partie concernant Tcl me faisant de l'oeil ...

Commentaires: https://github.com/bsdsx/blog_posts/issues/19


Lien vers ce billet