Forum: Mikrocontroller und Digitale Elektronik SWV auf Assembler Level ansprechen


von Christoph K. (chriskuku)


Lesenswert?

Ich wollte ein Stück Software, das in Assembler vorliegt, tracen, 
möglichst über SWO, also Nachrichten im SWV-View des STM32CubeIDE.
Aus einem C-Beispielprogramm heraus lief es ja zuletzt. Die 
Tracefunktion ITM_SendChar(char); ist aber ein Stück aus einer 
C-Bibliothek, die dazugelinkt wird.
Die habe ich ja in Assembler nicht. Ich kann vielleicht ein bißchen 
Assemblercode noch dazupacken, der vielleicht das SWV-Protokoll 
implementiert, aber wo und wie?

: Bearbeitet durch User
von A. B. (Gast)


Lesenswert?

Also wirklich, das

__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
{
  if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) &&      /* ITM enabled */
      ((ITM->TER & 1UL               ) != 0UL)   )     /* ITM Port #0 
enabled */
  {
    while (ITM->PORT[0U].u32 == 0UL)
    {
      __NOP();
    }
    ITM->PORT[0U].u8 = (uint8_t)ch;
  }
  return (ch);
}

in Assembler zu schreiben, kann doch wohl kein Problem sein, oder? Im 
Prinzip ist das doch nur ein UART (zumindest die übliche Einstellung), 
man schreibt das Byte ins Sende-FIFO, wenn Platz ist. Die Abfrage, ob 
"ITM enabled", kann man sich ja auch ggf. noch sparen.

Für z. B. STM32H750 im RM0433, 60.6.3, ITM stimulus register 0, da ist 
die FIFO-Behandlung erklärt.

Der kompliziertere Teil sind die ganzen Einstellungen davor.

von Bauform B. (bauformb)


Lesenswert?

Christoph K. schrieb:
> ITM_SendChar(char); ist aber ein Stück aus einer C-Bibliothek,
> die dazugelinkt wird. Die habe ich ja in Assembler nicht.

Hast du ein Programm, in dem ITM_SendChar() in C funktioniert und in 
dem dein Stück Assembler auch drin ist? Dann könnte es mit 3 Zeilen 
Assembler funktionieren:
1
   .global  ITM_SendChar
2
   movs r0, #72
3
   bl   ITM_SendChar
72 ist der Anfang von "Hallo, Welt" ;)

von Christoph K. (chriskuku)


Lesenswert?

Bauform B. schrieb:
> Christoph K. schrieb:
>> ITM_SendChar(char); ist aber ein Stück aus einer C-Bibliothek,
>> die dazugelinkt wird. Die habe ich ja in Assembler nicht.
>
> Hast du ein Programm, in dem ITM_SendChar() in C funktioniert und in
> dem dein Stück Assembler auch drin ist? Dann könnte es mit 3 Zeilen
> Assembler funktionieren:
>
1
   .global  ITM_SendChar
2
>    movs r0, #72
3
>    bl   ITM_SendChar
> 72 ist der Anfang von "Hallo, Welt" ;)

Nein, die Konstellation liegt so nicht vor. Ich muß die 
C-Implementierung in Assemblercode einbinden.
Aber ich werde mich mal an das von A.B.(gast) Vorgeschlagene begeben.

: Bearbeitet durch User
von Christoph K. (chriskuku)


Angehängte Dateien:

Lesenswert?

Konnte jetzt ITM_SendString und ITM_SendChar in Assembler 
implementieren:
1
      .equ ITM             ,   0xE0000000
2
main:
3
       ldr r0,=hello
4
       bl ITM_SendString
5
       pop {r0,r1}
6
       b .
7
hello: .asciz "hi!"
8
.global ITM_SendChar,ITM_SendString
9
10
ITM_SendString:   @  r0 - address of null-terminated String
11
  push {r0-r1}
12
        mov r1,r0
13
1:  mov r0,#0
14
  ldrb r0,[r1]
15
  cbz r0,2f
16
  bl ITM_SendChar
17
  add r1,#1
18
  b 1b
19
2:  pop {r0-r1}
20
  bx lr  
21
putchar:
22
ITM_SendChar:
23
  push {r0-r1}
24
1:  ldr r1, = ITM
25
  ldr r1,[r1]
26
  cmp r1,#0
27
  beq 1b
28
  ldr r1, = ITM
29
  str r0,[r1]
30
  pop {r0-r1}
31
  bx lr

Aber der Debugger (STM32CubeIDE) verhält sich merkwürdig.
Es wird "hi!" in der SWV ITM Console ausgegeben, aber wenn ich durch 
ITM_SendSTring durchsteppe, findet die loop auch die terminierende 0, 
fällt durch auf Label 2: und steppe ich bis zum bx lr springt der 
Debugger zurück auf  `add r1,#1` (!?).

Auch seltsam sind die vielen (sehr vielen) blauen trace-messages Zeile 
590 in simple.s im Debug Window.
Modifiziere ich den Code etwas, so springt der Debugger auf die 
branch-Instruction zurück.
1
      .equ ITM             ,   0xE0000000
2
main:
3
       ldr r0,=hello
4
       bl ITM_SendString
5
       pop {r0,r1}
6
       b .
7
hello: .asciz "hi!"
8
.global ITM_SendChar,ITM_SendString
9
10
ITM_SendString:   @  r0 - address of null-terminated String
11
  push {r0-r1}
12
        mov r1,r0
13
1:  mov r0,#0
14
  ldrb r0,[r1],#1
15
  cbz r0,2f
16
  bl ITM_SendChar
17
  b 1b @ <<<<<<<<<\ 
18
2:  pop {r0-r1} @ | erratischer Rücksprung des Debuggers nach dem bx lr
19
  bx lr @ >>>>>>>/
20
putchar:
21
ITM_SendChar:
22
  push {r0-r1}
23
1:  ldr r1, = ITM
24
  ldr r1,[r1]
25
  cmp r1,#0
26
  beq 1b
27
  ldr r1, = ITM
28
  str r0,[r1]
29
  pop {r0-r1}
30
  bx lr

: Bearbeitet durch User
von Bauform B. (bauformb)


Lesenswert?

Kann es sein, dass du gerade die falschen Register rettest? Bei r0 
sollte klar sein, dass du das nicht retten musst. r1 bis r3 darfst du 
bei Bedarf auch "zerstören". Umgekehrt benutzt du das lr um 
ITM_SendChar() aufzurufen, aber das wird noch für die Rückkehr nach main 
gebraucht, sollte also gerettet werden.

Ganz nebenbei finde ich den Namen putchar schöner als ITM_SendChar. Bei 
letzterem denke ich, dass das eine CubeMX-Funktion ist.

von Christoph K. (chriskuku)


Lesenswert?

Bauform B. schrieb:
> Kann es sein, dass du gerade die falschen Register rettest? Bei r0
> sollte klar sein, dass du das nicht retten musst. r1 bis r3 darfst du
> bei Bedarf auch "zerstören". Umgekehrt benutzt du das lr um
> ITM_SendChar() aufzurufen, aber das wird noch für die Rückkehr nach main
> gebraucht, sollte also gerettet werden.
>
> Ganz nebenbei finde ich den Namen putchar schöner als ITM_SendChar. Bei
> letzterem denke ich, dass das eine CubeMX-Funktion ist.

Danke. Wertvoller Tipp. Ja klar, bei geschachtelten Subroutine Aufrufen 
muß man eingangs in der SR push {...,rl} und den return mit pop {...,pc}
machen. ARM hat ja keine "RET" Instruction, mit der die Returnadresse 
vom Stack geholt wird. Bereinige das gerade, aber Auprobieren kann ich 
es erst nach dem Fußballspiel.

Und ITM_SendChar wird durch putchar ersetzt. Hatte ich ja schon 
vorgesehen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.