Forum: Compiler & IDEs Warum wird Variable wegoptimiert?


von Walter T. (nicolas)


Lesenswert?

Guten Morgen,
ich habe gerade ein Brett vorm Kopf und suche jemanden mit Kneifzange. 
Ich nutze den ARM-GCC und in einer Funktion wird die Variable "value" 
wegoptimiert - und ich sehe gerade nicht warum.
1
void glcd_putsth(char value,uint8_t RS) {
2
  // Neuimplementierung write-Zyklus gemaess Datenblatt S. 14
3
  
4
  #ifdef GLCD_NOBUSYFLAG
5
    delay_us(100);
6
  #else
7
    delay_us(100);
8
    //glcd_waitWhileBusy();
9
  #endif
10
  
11
  //GLCD_DATA_DDR = 0xFF;
12
  
13
  ClearBits(GLCD_CTRL_GPIO,GLCD_ECLK); //GLCD_CTRL_PORT &= ~(1 << GLCD_ECLK); // Enable Low
14
  ClearBits(GLCD_CTRL_GPIO,GLCD_RW);   //GLCD_CTRL_PORT &= ~(1 << GLCD_RW);   // Write
15
  if(RS)                               
16
    SetBits(GLCD_CTRL_GPIO,GLCD_DI);   //GLCD_CTRL_PORT |=  (1 << GLCD_DI); // Data
17
  else
18
    ClearBits(GLCD_CTRL_GPIO,GLCD_DI); //GLCD_CTRL_PORT &= ~(1 << GLCD_DI); // Instruction
19
  delay_us(0.450); // max(t_ASU,t_t_WL)
20
  SetBits(GLCD_CTRL_GPIO,GLCD_ECLK);   //GLCD_CTRL_PORT |=  (1 << GLCD_ECLK);
21
22
  // geht:
23
  //GPIO_ResetBits(GLCD_DATA_GPIO, 0xFF<<GLCD_DATA_OFFSET);
24
  //GPIO_SetBits(GLCD_DATA_GPIO,  value<<GLCD_DATA_OFFSET);
25
26
  // geht nicht:
27
  //ClearBits(GLCD_DATA_GPIO, ~value<<GLCD_DATA_OFFSET);
28
  //SetBits(GLCD_DATA_GPIO,  value<<GLCD_DATA_OFFSET);
29
30
  // geht nicht:
31
  uint32_t temp = ((((uint16_t) value)<<GLCD_DATA_OFFSET)& 0x0000FFFF) | ((0x000000FF<<(GLCD_DATA_OFFSET+0x10)) & 0xFFFF0000);
32
  GLCD_DATA_GPIO->BSRR = temp;
33
34
35
  delay_us(0.450);  // max(t_DSU, t_WH)
36
  ClearBits(GLCD_CTRL_GPIO,GLCD_ECLK); // GLCD_CTRL_PORT &= ~(1 << GLCD_ECLK); // Enable Low
37
}
Entsprechende Zeile aus dem Listing:
1
void glcd_putsth(char value,uint8_t RS) {
2
 8000ac2:  460e        mov  r6, r1
3
  // Neuimplementierung write-Zyklus gemaess Datenblatt S. 14
4
  
5
  #ifdef GLCD_NOBUSYFLAG
6
    delay_us(100);
7
  #else
8
    delay_us(100);
9
 8000ac4:  fbb4 f4f0   udiv  r4, r4, r0
10
 8000ac8:  2164        movs  r1, #100  ; 0x64
11
 8000aca:  4361        muls  r1, r4
12
 8000acc:  2203        movs  r2, #3
13
 8000ace:  fbb1 f0f2   udiv  r0, r1, r2
14
 8000ad2:  f000 f9a5   bl  8000e20 <__aeabi_ui2d>
15
 8000ad6:  a320        add  r3, pc, #128  ; (adr r3, 8000b58 <L_LOOPUS_203+0x14>)
16
 8000ad8:  e9d3 2300   ldrd  r2, r3, [r3]
17
 8000adc:  f000 fa16   bl  8000f0c <__aeabi_dmul>
18
 8000ae0:  f000 fc26   bl  8001330 <__aeabi_d2uiz>
19
20
08000ae4 <L_LOOPUS_161>:
21
 8000ae4:  3801        subs  r0, #1
22
 8000ae6:  f47f affd   bne.w  8000ae4 <L_LOOPUS_161>
23
    //glcd_waitWhileBusy();
24
  #endif
25
  
26
  //GLCD_DATA_DDR = 0xFF;
27
  
28
  ClearBits(GLCD_CTRL_GPIO,GLCD_ECLK); //GLCD_CTRL_PORT &= ~(1 << GLCD_ECLK); // Enable Low
29
 8000aea:  4b21        ldr  r3, [pc, #132]  ; (8000b70 <L_LOOPUS_203+0x2c>)
30
 8000aec:  f04f 7000   mov.w  r0, #33554432  ; 0x2000000
31
  ClearBits(GLCD_CTRL_GPIO,GLCD_RW);   //GLCD_CTRL_PORT &= ~(1 << GLCD_RW);   // Write
32
 8000af0:  f04f 7180   mov.w  r1, #16777216  ; 0x1000000
33
    //glcd_waitWhileBusy();
34
  #endif
35
  
36
  //GLCD_DATA_DDR = 0xFF;
37
  
38
  ClearBits(GLCD_CTRL_GPIO,GLCD_ECLK); //GLCD_CTRL_PORT &= ~(1 << GLCD_ECLK); // Enable Low
39
 8000af4:  6118        str  r0, [r3, #16]
40
  ClearBits(GLCD_CTRL_GPIO,GLCD_RW);   //GLCD_CTRL_PORT &= ~(1 << GLCD_RW);   // Write
41
 8000af6:  6119        str  r1, [r3, #16]
42
  if(RS)                               
43
 8000af8:  b10e        cbz  r6, 8000afe <L_LOOPUS_161+0x1a>
44
    SetBits(GLCD_CTRL_GPIO,GLCD_DI);   //GLCD_CTRL_PORT |=  (1 << GLCD_DI); // Data
45
 8000afa:  2280        movs  r2, #128  ; 0x80
46
 8000afc:  e001        b.n  8000b02 <L_LOOPUS_161+0x1e>
47
  else
48
    ClearBits(GLCD_CTRL_GPIO,GLCD_DI); //GLCD_CTRL_PORT &= ~(1 << GLCD_DI); // Instruction
49
 8000afe:  f44f 0200   mov.w  r2, #8388608  ; 0x800000
50
 8000b02:  611a        str  r2, [r3, #16]
51
  delay_us(0.450); // max(t_ASU,t_t_WL)
52
 8000b04:  4620        mov  r0, r4
53
 8000b06:  f000 f98b   bl  8000e20 <__aeabi_ui2d>
54
 8000b0a:  a315        add  r3, pc, #84  ; (adr r3, 8000b60 <L_LOOPUS_203+0x1c>)
55
 8000b0c:  e9d3 2300   ldrd  r2, r3, [r3]
56
 8000b10:  f000 f9fc   bl  8000f0c <__aeabi_dmul>
57
 8000b14:  2200        movs  r2, #0
58
 8000b16:  4b17        ldr  r3, [pc, #92]  ; (8000b74 <L_LOOPUS_203+0x30>)
59
 8000b18:  f000 fb22   bl  8001160 <__aeabi_ddiv>
60
 8000b1c:  a30e        add  r3, pc, #56  ; (adr r3, 8000b58 <L_LOOPUS_203+0x14>)
61
 8000b1e:  e9d3 2300   ldrd  r2, r3, [r3]
62
 8000b22:  f000 f9f3   bl  8000f0c <__aeabi_dmul>
63
 8000b26:  f000 fc03   bl  8001330 <__aeabi_d2uiz>
64
65
08000b2a <L_LOOPUS_194>:
66
 8000b2a:  3801        subs  r0, #1
67
 8000b2c:  f47f affd   bne.w  8000b2a <L_LOOPUS_194>
68
  SetBits(GLCD_CTRL_GPIO,GLCD_ECLK);   //GLCD_CTRL_PORT |=  (1 << GLCD_ECLK);
69
 8000b30:  490f        ldr  r1, [pc, #60]  ; (8000b70 <L_LOOPUS_203+0x2c>)
70
  // geht nicht:
71
  //ClearBits(GLCD_DATA_GPIO, ~value<<GLCD_DATA_OFFSET);
72
  //SetBits(GLCD_DATA_GPIO,  value<<GLCD_DATA_OFFSET);
73
74
  // geht nicht:
75
  uint32_t temp = ((((uint16_t) value)<<GLCD_DATA_OFFSET)& 0x0000FFFF) | ((0x000000FF<<(GLCD_DATA_OFFSET+0x10)) & 0xFFFF0000);
76
 8000b32:  022d        lsls  r5, r5, #8
77
  if(RS)                               
78
    SetBits(GLCD_CTRL_GPIO,GLCD_DI);   //GLCD_CTRL_PORT |=  (1 << GLCD_DI); // Data
79
  else
80
    ClearBits(GLCD_CTRL_GPIO,GLCD_DI); //GLCD_CTRL_PORT &= ~(1 << GLCD_DI); // Instruction
81
  delay_us(0.450); // max(t_ASU,t_t_WL)
82
  SetBits(GLCD_CTRL_GPIO,GLCD_ECLK);   //GLCD_CTRL_PORT |=  (1 << GLCD_ECLK);
83
 8000b34:  f44f 7300   mov.w  r3, #512  ; 0x200
84
  // geht nicht:
85
  //ClearBits(GLCD_DATA_GPIO, ~value<<GLCD_DATA_OFFSET);
86
  //SetBits(GLCD_DATA_GPIO,  value<<GLCD_DATA_OFFSET);
87
88
  // geht nicht:
89
  uint32_t temp = ((((uint16_t) value)<<GLCD_DATA_OFFSET)& 0x0000FFFF) | ((0x000000FF<<(GLCD_DATA_OFFSET+0x10)) & 0xFFFF0000);
90
 8000b38:  f045 457f   orr.w  r5, r5, #4278190080  ; 0xff000000
91
  // GLCD_DATA_OFFSET = 8
92
  GLCD_DATA_GPIO->BSRR = temp;
93
 8000b3c:  f5a1 6280   sub.w  r2, r1, #1024  ; 0x400
94
  if(RS)                               
95
    SetBits(GLCD_CTRL_GPIO,GLCD_DI);   //GLCD_CTRL_PORT |=  (1 << GLCD_DI); // Data
96
  else
97
    ClearBits(GLCD_CTRL_GPIO,GLCD_DI); //GLCD_CTRL_PORT &= ~(1 << GLCD_DI); // Instruction
98
  delay_us(0.450); // max(t_ASU,t_t_WL)
99
  SetBits(GLCD_CTRL_GPIO,GLCD_ECLK);   //GLCD_CTRL_PORT |=  (1 << GLCD_ECLK);
100
 8000b40:  610b        str  r3, [r1, #16]
101
102
  // geht nicht:
103
  uint32_t temp = ((((uint16_t) value)<<GLCD_DATA_OFFSET)& 0x0000FFFF) | ((0x000000FF<<(GLCD_DATA_OFFSET+0x10)) & 0xFFFF0000);
104
  // temp wird zu 0xff000000, d.h. value wird als 0 gesehen
105
  // GLCD_DATA_OFFSET = 8
106
  GLCD_DATA_GPIO->BSRR = temp;
107
 8000b42:  6115        str  r5, [r2, #16]
108
109
08000b44 <L_LOOPUS_203>:
110
111
112
  delay_us(0.450);  // max(t_DSU, t_WH)
113
 8000b44:  3801        subs  r0, #1
114
 8000b46:  f47f affd   bne.w  8000b44 <L_LOOPUS_203>
115
  ClearBits(GLCD_CTRL_GPIO,GLCD_ECLK); // GLCD_CTRL_PORT &= ~(1 << GLCD_ECLK); // Enable Low
116
 8000b4a:  4b09        ldr  r3, [pc, #36]  ; (8000b70 <L_LOOPUS_203+0x2c>)
117
 8000b4c:  f04f 7000   mov.w  r0, #33554432  ; 0x2000000
118
 8000b50:  6118        str  r0, [r3, #16]
119
 8000b52:  bd70        pop  {r4, r5, r6, pc}
120
 8000b54:  f3af 8000   nop.w
121
 8000b58:  88b97785   .word  0x88b97785
122
 8000b5c:  3feec4ef   .word  0x3feec4ef
123
 8000b60:  cccccccd   .word  0xcccccccd
124
 8000b64:  3fdccccc   .word  0x3fdccccc
125
 8000b68:  20000000   .word  0x20000000
126
 8000b6c:  000f4240   .word  0x000f4240
127
 8000b70:  40011000   .word  0x40011000
128
 8000b74:  40080000   .word  0x40080000
129
130
08000b78 <glcd_area>:
131
}
GLCD_DATA_OFFSET ist 8, Ergebnis ist, daß alle Pins ständig high sind.

So langsam setzt bei mir die Codeblindheit ein und ich sehe Fehler, wo 
keine sind. Kann mir jemand kurz helfen?

Viele Grüße
W.T.

von (prx) A. K. (prx)


Lesenswert?

Bring mal den ganzen Code zu der Funktion. Da fehlt was am Anfang. 
Verlass dich nicht darauf, dass die Quellcodezeilen immer an der 
richtigen Stelle eingefügr werden, das geht oft daneben.

von Ralf G. (ralg)


Lesenswert?

Welchen Wert hat denn 'GLCD_DATA_OFFSET'? Bist du dir mit '8' sicher. Im 
Code ist alles auskommentiert.

von (prx) A. K. (prx)


Lesenswert?

Lass das mit den Fliesskommazahlen bei delay_us lieber. Diese Funktion 
ist für so kurze Zeiten problematisch. Woher stammt die?

Bei dem Delay kommt mir noch was komisch vor:

08000b2a <L_LOOPUS_194>:
 8000b2a:  3801        subs  r0, #1
 8000b2c:  f47f affd   bne.w  8000b2a <L_LOOPUS_194>

R0 ist jetzt 0. Nirgendwo hier wird R0 verändert. R0 bleibt also 0.

08000b44 <L_LOOPUS_203>:
 8000b44:  3801        subs  r0, #1
 8000b46:  f47f affd   bne.w  8000b44 <L_LOOPUS_203>

Wenn dieser Code mit R0=0 anläuft, dann ist Geduld angesagt.

von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Danke für's Lesen.

Ich hoffe, ich habe jetzt alle Teile aus dem Listing richtig 
zusammengeklaubt (list.lss). Wer sich das wirklich antun will kann auch 
einen Blick ins komplette Listing werfen (lang_und_zaeh.lss).

Daß GLCD_DATA_OFFSET 8 ist bin ich mir sicher - daß mir da ein zweites 
Makro hineinfuhrwerkt war ja auch mein erster Gedanke. Und immerhin 
funktioniert ja noch die Variante mit der Standard-Peripheral-Library 
meines STM32, also muß die Pinzuordnung schon einmal stimmen.

von (prx) A. K. (prx)


Lesenswert?

Walter Tarpan schrieb:
> Daß GLCD_DATA_OFFSET 8 ist bin ich mir sicher

Der Code fürs BSSR passt dazu und ist auch völlig korrekt:

 8000b32:  022d        lsls  r5, r5, #8
 8000b38:  f045 457f   orr.w  r5, r5, #0xff000000
 8000b42:  6115        str  r5, [r2, #16]

Ich frage mich eher, ob das Timing stimmt. Einerseits die 
Delay-Funktion, wie beschrieben. Andererseits ist GPIO_xxxBits viel 
langsamer als die anderen nicht funktionierenden Varianten.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

A. K. schrieb:
> [...]
>
> Ich frage mich eher, ob das Timing stimmt. Einerseits die
> Delay-Funktion, wie beschrieben. Andererseits ist GPIO_xxxBits viel
> langsamer als die anderen nicht funktionierenden Varianten.

Das war auch mein erster Gedanke. Deswegen hatte ich bei Vorversuchen 
auch viele nops eingefügt.

A. K. schrieb:
> Lass das mit den Fliesskommazahlen bei delay_us lieber. Diese Funktion
> ist für so kurze Zeiten problematisch. Woher stammt die?

Damit hast Du mich auf den rechten Weg gebracht: Die delay-Routine habe 
ich in den Weiten des WWWs gesucht und in eine Makro-Form gebracht, weil 
ich ARM-Assembler nicht kann. Und sie ist so definiert:
1
#define delay_us(delayval) delay_us_( (uint32_t)( (SystemCoreClock) / 1000000 *delayval/3 * TUNE_FAC) )
2
3
#define delay_us_(delayval)  \
4
  asm volatile (\
5
    "L_LOOPUS_%=:     \n\t" \
6
    "subs %0, %0, #1  \n\t" \
7
    "bne  L_LOOPUS_%= \n\t" \
8
    :  /* no outputs */ : "r" (delayval) )
Wenn ich die letzte Zeile durch 9 "nop"s ersetze geht alles. Was auch 
erklärt, warum sich der Debugger ständig aufgehängt hat. Ich vermisse 
irgendwie die hervorragend funktionierenden _delay_xx vom AVR-GCC.

Vielen Dank für die hilfreichen Kommentare!

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Bei dieser Delay-Funktion sollte an Stelle der Variablen SystemCoreClock 
eine Konstante stehen. Andernfalls gibts, wie hier geschehen, eine 
Berechnung zur Laufzeit und kurze Delays werden grottenfalsch.

Ausserdem kann es je nach exaktem Typ des Controllers und dem jeweiligen 
Alignment der Schleife gewisse Schmutzeffekte geben, so dass das exakt 
gleiche Delay an verschiedenen Stellen im Programm deutlich 
unterschiedlich ausfällt.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Walter Tarpan schrieb:
> #define delay_us_(delayval)  \
>   asm volatile (\
>     "L_LOOPUS_%=:     \n\t" \
>     "subs %0, %0, #1  \n\t" \
>     "bne  L_LOOPUS_%= \n\t" \
>     :  /* no outputs */ : "r" (delayval) )
> [/c]

Das ist falsch, denn delayval wird verändert! Die Constraint könnte 
sein:

>     :  "=r" (delayval) : "0" (delayval)

Allerdings muß delayval dann ein LVALUE sein.  Anstatt des Makros würde 
ich eine inline-Funktion machen.

Ich kenn zwar kein ARM-Code, aber das schein nicht zu funktionieren wenn 
delayval = 0 ist.  Du könntest
1
static inline __attribute__((__always_inline__))
2
void delay_us (unsigned delayval)
3
{
4
   if (delayval)
5
       __asm volatile ("0:\n\t"
6
                       "subs %0, %0, #1  \n\t"
7
                       "bne  0b"
8
                       : "+r" (delayval));
9
}

: Bearbeitet durch User
von Carsten H. (blaubaer77)


Lesenswert?

Hallöchen,

in der Codezeile:
1
 uint32_t temp = ((((uint16_t) value)<<GLCD_DATA_OFFSET)& 0x0000FFFF) | ((0x000000FF<<(GLCD_DATA_OFFSET+0x10)) & 0xFFFF0000);

der Teil:
1
(((uint16_t) value)<<GLCD_DATA_OFFSET)& 0x0000FFFF)

ergibt doch immer 0.
Der Wert von Value wird um 8 Bit nach oben verschoben und dann werden 
die oberen Bits ausmaskiert. Damit kann der Compiler die Variable 
wegoptimieren.

Gruß Carsten.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Carsten H. schrieb:
> Der Wert von Value wird um 8 Bit nach oben verschoben und dann werden
> die oberen Bits ausmaskiert. Damit kann der Compiler die Variable
> wegoptimieren.

Also bei mir landet ein 8-Bit-Wert beim Verschieben um 8 Bit immer noch 
im 16-Bit-Bereich. Und auf meinen µP auch. Also läuft das alles 
problemlos seit ein paar Stunden.

Johann L. schrieb:
> Ich kenn zwar kein ARM-Code, aber das schein nicht zu funktionieren wenn
> delayval = 0 ist.  Du könntest
> static inline __attribute__((_always_inline_))
> void delay_us (unsigned delayval)
> {
>    if (delayval)
>        __asm volatile ("0:\n\t"
>                        "subs %0, %0, #1  \n\t"
>                        "bne  0b"
>                        : "+r" (delayval));
> }

Mit dem delay muß ich mal ausprobieren. Eine gute Delay-Funktion ist 
nämlich immer noch Mangelware.

von axel (Gast)


Lesenswert?

Das müssten schon 16 Bit sein, erst dann ist der Wert von value komplett 
durch die Maskierung weg.

von (prx) A. K. (prx)


Lesenswert?

Johann L. schrieb:
> Das ist falsch, denn delayval wird verändert!

Das ist der Grund, weshalb die zweite 0,450er Schleife stecken bleibt.

> Ich kenn zwar kein ARM-Code, aber das schein nicht zu funktionieren wenn
> delayval = 0 ist.

Korrekt.

von (prx) A. K. (prx)


Lesenswert?

Carsten H. schrieb:
> Der Wert von Value wird um 8 Bit nach oben verschoben und dann werden
> die oberen Bits ausmaskiert.

Wie ich oben schon schrieb ist dieser Code völlig korrekt.

Wenn dich das (uint16_t)value irritiert: Der Cast ist für'n A..... Ich 
würde aber empfehlen, als Parameter kein "char" zu verwenden. Das könnte 
negativ sein und dann geht es bei einem Offset < 8 den Bach runter.

axel schrieb:
> Das müssten schon 16 Bit sein, erst dann ist der Wert von value komplett
> durch die Maskierung weg.

Allerdings würde man dann vmtl. kein 32-Bit I/O-Register vorfinden.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

A. K. schrieb:
>
> Wenn dich das (uint16_t)value irritiert: Der Cast ist für'n A..... Ich
> würde aber empfehlen, als Parameter kein "char" zu verwenden. Das könnte
> negativ sein und dann geht es bei einem Offset < 8 den Bach runter.
>

Bitte den obigen Code nicht zu ernst nehmen: Der Cast ist wirklich 
Überflüssig. Es ist dieser Code, der entsteht, wenn man nicht mehr 
weiter weiß (Variante1 funktioniert, Variante2 nicht und beide sehen 
völlig gleich aus!) und das Assembler-Listing noch nicht richtig lesen 
kann und dann alles explizit und fix castet, damit ja keine merkwürdige 
Integer-Promotion-Regel mehr dazwischenpaßt.

von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Ich habe jetzt mal die Anregung bezüglich der Delay-Sachen umgesetzt. 
Meine delay.h sieht jetzt so aus:
1
#ifndef _delay_h_
2
#define _delay_h_
3
4
#define TUNE_FAC 0.96154
5
#define SYSCLK 24000000ULL
6
7
#include <stdint.h>
8
9
#define delay_us(delayval) delay_us_( (uint32_t)( (SYSCLK) / 3000000ULL *delayval * TUNE_FAC) )
10
11
static inline void delay_us_(uint64_t delayval) {
12
  if(delayval) {
13
    asm volatile (\
14
      "L_LOOPUS_%=:     \n\t" \
15
      "subs %0, %0, #1  \n\t" \
16
      "bne  L_LOOPUS_%= \n\t" \
17
      :  "+r" (delayval) );
18
   }
19
  else {
20
    asm volatile("nop");
21
  }
22
}
23
24
#endif
und zum Testen gibt es eine einfache Routine:
1
void delay_test(void) {
2
  GPIO_InitTypeDef GPIO_InitStructure;
3
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
4
5
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
6
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
7
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
8
  GPIO_Init(GPIOB, &GPIO_InitStructure);
9
10
  printf("Test delay \n PB2 Pulsabstand 3µs\n Beenden durch Knopfdruck\a");
11
12
  while(1) {
13
    GPIOB->BSRR = GPIO_Pin_2;
14
    delay_us(3);
15
    GPIOB->BSRR = GPIO_Pin_2<<16;
16
    delay_us(6);
17
    if(key_getstroke()) return; // Liest Tastendruck ein
18
  }
19
}
Wirft man einen Blick aufs Oszilloskop (sorry für den schlechten 
Screenshot, die sphärische Verzerrung bekomme ich nicht heraus) sieht 
man, daß der vorgeschlagene Delay sehr zuverlässig funktioniert (die 
Verschiedungen kommen vom SysTick, ist der aus sind alle schön gleich 
breit).

Das ist genau das, was ich gesucht habe. Vielen Danke für die Hilfe!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Walter Tarpan schrieb:
> Wirft man einen Blick aufs Oszilloskop (sorry für den schlechten
> Screenshot, die sphärische Verzerrung bekomme ich nicht heraus)

Das ist ein Witz, oder? Der Screenshot ist --abgesehen davon, daß 
eigentlich das Oszilloskop so etwas selbst anfertigen können sollte-- 
doch vollkommen in Ordnung.

von Walter T. (nicolas)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Das ist ein Witz, oder?

Ja.

von (prx) A. K. (prx)


Lesenswert?

Bis zum Cortex M51 mit 64-Bit Core ist es zwar noch ein Weilchen hin, 
aber der kluge Mann sorgt vor. ;-)

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.