Forum: Mikrocontroller und Digitale Elektronik STM32F401 C-ISR durch Assembler-ISR ersetzen


von Tycho B. (asellus)


Lesenswert?

Ich arbeite mit System Workbench und habe eine funktionierende ISR für 
USART DMA in C geschrieben. Der passende Ausschnitt aus dem LST-File:
1
 8000084:  08004b7d   stmdaeq  r0, {r0, r2, r3, r4, r5, r6, r8, r9, fp, lr}
2
3
[...]
4
5
08004b7c <USART2_DMA1_Stream6_IRQHandler>:
6
 8004b7c:  4b1d        ldr  r3, [pc, #116]  ; (8004bf4 <USART2_DMA1_Stream6_IRQHandler+0x78>)
7
 8004b7e:  685a        ldr  r2, [r3, #4]
8
 8004b80:  0292        lsls  r2, r2, #10
9
 8004b82:  d51f        bpl.n  8004bc4 <USART2_DMA1_Stream6_IRQHandler+0x48>
10
 8004b84:  68da        ldr  r2, [r3, #12]
11
 8004b86:  491c        ldr  r1, [pc, #112]  ; (8004bf8 <USART2_DMA1_Stream6_IRQHandler+0x7c>)
12
 8004b88:  481c        ldr  r0, [pc, #112]  ; (8004bfc <USART2_DMA1_Stream6_IRQHandler+0x80>)
13
 8004b8a:  f442 1200   orr.w  r2, r2, #2097152  ; 0x200000
14
 8004b8e:  b410        push  {r4}
15
 8004b90:  60da        str  r2, [r3, #12]
16
 8004b92:  680a        ldr  r2, [r1, #0]
17
 8004b94:  1c53        adds  r3, r2, #1
18
 8004b96:  600b        str  r3, [r1, #0]
19
 8004b98:  680c        ldr  r4, [r1, #0]
20
 8004b9a:  23ac        movs  r3, #172  ; 0xac
21
 8004b9c:  fb03 f302   mul.w  r3, r3, r2
22
 8004ba0:  2c14        cmp  r4, #20
23
 8004ba2:  f04f 0200   mov.w  r2, #0
24
 8004ba6:  bf08        it  eq
25
 8004ba8:  600a        streq  r2, [r1, #0]
26
 8004baa:  50c2        str  r2, [r0, r3]
27
 8004bac:  4a14        ldr  r2, [pc, #80]  ; (8004c00 <USART2_DMA1_Stream6_IRQHandler+0x84>)
28
 8004bae:  680b        ldr  r3, [r1, #0]
29
 8004bb0:  6812        ldr  r2, [r2, #0]
30
 8004bb2:  429a        cmp  r2, r3
31
 8004bb4:  4a13        ldr  r2, [pc, #76]  ; (8004c04 <USART2_DMA1_Stream6_IRQHandler+0x88>)
32
 8004bb6:  6813        ldr  r3, [r2, #0]
33
 8004bb8:  d107        bne.n  8004bca <USART2_DMA1_Stream6_IRQHandler+0x4e>
34
 8004bba:  f023 0301   bic.w  r3, r3, #1
35
 8004bbe:  f85d 4b04   ldr.w  r4, [sp], #4
36
 8004bc2:  6013        str  r3, [r2, #0]
37
 8004bc4:  4770        bx  lr
38
 8004bc6:  bf00        nop
39
 8004bc8:  6813        ldr  r3, [r2, #0]
40
 8004bca:  07db        lsls  r3, r3, #31
41
 8004bcc:  d4fb        bmi.n  8004bc6 <USART2_DMA1_Stream6_IRQHandler+0x4a>
42
 8004bce:  680b        ldr  r3, [r1, #0]
43
 8004bd0:  4a0c        ldr  r2, [pc, #48]  ; (8004c04 <USART2_DMA1_Stream6_IRQHandler+0x88>)
44
 8004bd2:  24ac        movs  r4, #172  ; 0xac
45
 8004bd4:  fb04 0303   mla  r3, r4, r3, r0
46
 8004bd8:  3304        adds  r3, #4
47
 8004bda:  60d3        str  r3, [r2, #12]
48
 8004bdc:  680b        ldr  r3, [r1, #0]
49
 8004bde:  fb04 f403   mul.w  r4, r4, r3
50
 8004be2:  5903        ldr  r3, [r0, r4]
51
 8004be4:  6053        str  r3, [r2, #4]
52
 8004be6:  6813        ldr  r3, [r2, #0]
53
 8004be8:  f85d 4b04   ldr.w  r4, [sp], #4
54
 8004bec:  f043 0301   orr.w  r3, r3, #1
55
 8004bf0:  6013        str  r3, [r2, #0]
56
 8004bf2:  4770        bx  lr
57
 8004bf4:  40026000   andmi  r6, r2, r0
58
 8004bf8:  2000ab80   andcs  sl, r0, r0, lsl #23
59
 8004bfc:  2000acdc   ldrdcs  sl, [r0], -ip
60
 8004c00:  2000ac90   mulcs  r0, r0, ip
61
 8004c04:  400260a0   andmi  r6, r2, r0, lsr #1

Diesen Code habe ich in eine .S-Datei geschrieben und in das Projekt 
eingebunden, um einen Anfang für eine Assembler-ISR zu haben, die später 
optimiert werden soll.
Die C-ISR habe ich auskommentiert. Das Ergebnis im LST-File:
1
8000084:  080001e4   stmdaeq  r0, {r2, r5, r6, r7, r8}
2
3
[...]
4
5
080001e4 <USART2_DMA1_Stream6_IRQHandler>:
6
 80001e4:  4b1d        ldr  r3, [pc, #116]  ; (800025c <USART2_DMA1_Stream6_IRQHandler+0x78>)
7
 80001e6:  685a        ldr  r2, [r3, #4]
8
 80001e8:  0292        lsls  r2, r2, #10
9
 80001ea:  d51f        bpl.n  800022c <USART2_DMA1_Stream6_IRQHandler+0x48>
10
 80001ec:  68da        ldr  r2, [r3, #12]
11
 80001ee:  491d        ldr  r1, [pc, #116]  ; (8000264 <USART2_DMA1_Stream6_IRQHandler+0x80>)
12
 80001f0:  481d        ldr  r0, [pc, #116]  ; (8000268 <USART2_DMA1_Stream6_IRQHandler+0x84>)
13
 80001f2:  f442 1200   orr.w  r2, r2, #2097152  ; 0x200000
14
 80001f6:  b410        push  {r4}
15
 80001f8:  60da        str  r2, [r3, #12]
16
 80001fa:  680a        ldr  r2, [r1, #0]
17
 80001fc:  1c53        adds  r3, r2, #1
18
 80001fe:  600b        str  r3, [r1, #0]
19
 8000200:  680c        ldr  r4, [r1, #0]
20
 8000202:  23ac        movs  r3, #172  ; 0xac
21
 8000204:  fb03 f302   mul.w  r3, r3, r2
22
 8000208:  2c14        cmp  r4, #20
23
 800020a:  f04f 0200   mov.w  r2, #0
24
 800020e:  bf08        it  eq
25
 8000210:  600a        streq  r2, [r1, #0]
26
 8000212:  50c2        str  r2, [r0, r3]
27
 8000214:  4a15        ldr  r2, [pc, #84]  ; (800026c <USART2_DMA1_Stream6_IRQHandler+0x88>)
28
 8000216:  680b        ldr  r3, [r1, #0]
29
 8000218:  6812        ldr  r2, [r2, #0]
30
 800021a:  429a        cmp  r2, r3
31
 800021c:  4a10        ldr  r2, [pc, #64]  ; (8000260 <USART2_DMA1_Stream6_IRQHandler+0x7c>)
32
 800021e:  6813        ldr  r3, [r2, #0]
33
 8000220:  d107        bne.n  8000232 <USART2_DMA1_Stream6_IRQHandler+0x4e>
34
 8000222:  f023 0301   bic.w  r3, r3, #1
35
 8000226:  f85d 4b04   ldr.w  r4, [sp], #4
36
 800022a:  6013        str  r3, [r2, #0]
37
 800022c:  4770        bx  lr
38
 800022e:  bf00        nop
39
 8000230:  6813        ldr  r3, [r2, #0]
40
 8000232:  07db        lsls  r3, r3, #31
41
 8000234:  d4fb        bmi.n  800022e <USART2_DMA1_Stream6_IRQHandler+0x4a>
42
 8000236:  680b        ldr  r3, [r1, #0]
43
 8000238:  4a09        ldr  r2, [pc, #36]  ; (8000260 <USART2_DMA1_Stream6_IRQHandler+0x7c>)
44
 800023a:  24ac        movs  r4, #172  ; 0xac
45
 800023c:  fb04 0303   mla  r3, r4, r3, r0
46
 8000240:  3304        adds  r3, #4
47
 8000242:  60d3        str  r3, [r2, #12]
48
 8000244:  680b        ldr  r3, [r1, #0]
49
 8000246:  fb04 f403   mul.w  r4, r4, r3
50
 800024a:  5903        ldr  r3, [r0, r4]
51
 800024c:  6053        str  r3, [r2, #4]
52
 800024e:  6813        ldr  r3, [r2, #0]
53
 8000250:  f85d 4b04   ldr.w  r4, [sp], #4
54
 8000254:  f043 0301   orr.w  r3, r3, #1
55
 8000258:  6013        str  r3, [r2, #0]
56
 800025a:  4770        bx  lr
57
 800025c:  40026000   andmi  r6, r2, r0
58
 8000260:  400260a0   andmi  r6, r2, r0, lsr #1
59
 8000264:  2000ab80   andcs  sl, r0, r0, lsl #23
60
 8000268:  2000acdc   ldrdcs  sl, [r0], -ip
61
 800026c:  2000ac90   mulcs  r0, r0, ip

Bis auf die neue Adresse der ISR und eine andere Verteilung der 
Konstanten am Ende sind sie identisch. Das Problem: wenn ich die 
Variante mit der .S-Datei flashe, dann lande ich im Hard Fault. Ich sehe 
nicht woran es liegen könnte.
Was noch auffällt: die Sprungadresse in der Tabelle im 
funktionierenden Code, 08004b7d, stimmt nicht mit dem Anfang der ISR 
überein. Trotzdem funktioniert es. Die zweite Variante mit der .S-Datei 
funktioniert nicht...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Tycho B. schrieb:
> Der passende Ausschnitt aus dem LST-File:
> [...]
> Diesen Code habe ich in eine .S-Datei geschrieben und in das Projekt
> eingebunden,

Umständlich.

Einfacher ist, mit etwas anzufangen, das assemblierbar ist; etwa mit 
-save-temps compilieren und das temporäre s-File als Startpunkt 
hernehmen.

von Dr. Sommer (Gast)


Lesenswert?

Tycho B. schrieb:
> Was noch auffällt: die Sprungadresse in der Tabelle im
> funktionierenden Code, 08004b7d, stimmt nicht mit dem Anfang der ISR
> überein.

Das muss so. Beim ARM gibt das unterste Bit einer Sprung-Adresse an, ob 
im Thumb-Mode (1) oder ARM-Mode (0) ausgeführt werden soll. Die Cortex-M 
haben nur den Thumb-Mode, daher muss beim Springen das unterste Bit 
immer 1 sein. Die tatsächliche Adresse muss onehin immer ein Vielfaches 
von 2 sein, weswegen das unterste Bit keine Auswirkung auf die 
tatsächliche Adresse hat. Wenn bei der nicht funktionierenden Variante 
das unterste Bit der Adresse 0 ist, funktionierts nicht. Schreibe mal 
".thumb" an den Anfang der Assembler-Datei, dann macht der Compiler das 
vermutlich automatisch richtig.

von Christopher J. (christopher_j23)


Lesenswert?

Tycho B. schrieb:
> Was noch auffällt: die Sprungadresse in der Tabelle im
> funktionierenden Code, 08004b7d, stimmt nicht mit dem Anfang der ISR
> überein.

Die Adresse ist absichtlich "falsch" und deswegen funktioniert es :D

Das liegt daran, dass die ARM CPUs zwei verschiedene Modi besitzen: ARM 
oder Thumb. Ist die Sprungadresse einer Funktion gerade, d.h. das LSB 
ist 0, wird im ARM-Modus ausgeführt, ist die Sprungadresse ungerade 
(LSB==1) wird im Thumb-Modus ausgeführt. Im Flash selbst liegen die 
Funktionen in beiden Fällen an geraden Adressen, d.h. das LSB der 
Sprungadresse wird für den eigentlichen Sprung ignoriert und ist 
lediglich für die Unterscheidung der Modi da.

An deiner funktionierenden Variante sieht man schön, dass zwar die 
Funktion selbst an einer geraden Adresse liegt aber der Vektor auf eine 
ungerade Adresse zeigt. In der nicht funktionierenden Variante sind 
sowohl Adresse im Flash, als auch der Vektor gerade.

Damit der Linker den Vektor richtigerweise auf eine ungerade Adresse 
zeigen lässt musst du dem die passende Information mit auf den Weg 
geben. Dafür ist das
1
.thumb_func
 da, was du im Listing deiner C-Variante sicher finden dürftest und was 
sehr wahrscheinlich in deiner Assembler-Variante fehlt.

Edit: Dr. Sommer war schneller. Hinzufügen würde ich noch, das .thumb 
und .thumb_func nicht das gleiche bezwecken. Man benötigt beides, wobei 
durch .thumb_func implizit auch .thumb gesetzt wird.

: Bearbeitet durch User
von Tycho B. (asellus)


Lesenswert?

Christopher J. schrieb:
> Edit: Dr. Sommer war schneller. Hinzufügen würde ich noch, das .thumb
> und .thumb_func nicht das gleiche bezwecken. Man benötigt beides, wobei
> durch .thumb_func implizit auch .thumb gesetzt wird.

Da hat mir ja nur ganz wenig an Info gefehlt, um selbst drauf zu kommen)
.thumb hatte ich schon drin, allerdings nicht .thumb_func.
Damit funktioniert es. Danke)

von Dr. Sommer (Gast)


Lesenswert?

Na sowas. In den Startup-Codes von ST steht das nur so (und das 
funktioniert auch):
1
  .syntax unified
2
  .cpu cortex-m3
3
  .fpu softvfp
4
  .thumb
5
6
  .section  .text.Reset_Handler
7
  .weak  Reset_Handler
8
  .type  Reset_Handler, %function
9
Reset_Handler:
10
  movs  r1, #0
Ich vermute mal dass ".thumb" und ".type  Reset_Handler, %function" in 
Kombination das gleiche bewirken wie .thumb_func?

von Christopher J. (christopher_j23)


Lesenswert?

Ich gehe mal schwer davon aus.
Das
1
.type  Reset_Handler, %function
ist soweit ich das verstehe die Anweisung an den Linker, dass es sich 
bei Reset_Handler um eine Funktion handelt und
1
.thumb
ist dann die Anweisung an den Assembler, das er das im Thumb-Modus 
assembliert. Zusammen ergibt das dann scheinbar .thumb_func.

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.