STM32L152 uint64_t wird nicht richtig verarbeitet

OP #4236107
Lesenswert?
• ▲
▼
Hallo, habe ich was grob falsch gemacht?
Wenn ich meinen Code debugge, änder sich der Wert von "rom_adress" 
unerwartet und falsch, selbst die Deklaration mit  = 0 hat kein Effekt 
auf den Wert. Die Funktion "one_wire_read" liefert uint8_t.

1
uint64_t onewire_read_rom(void)
2
{  
3
  uint64_t rom_adress = 0;  
4
  uint8_t shift =48;
5
  uint8_t data = 0;
6
  
7
  onewire_reset();
8
  
9
  one_wire_putc(0x33);
10
  
11
  one_wire_read(); // Family 
12
  
13
  while(shift)
14
  {
15
    data=one_wire_read(); 
16
    rom_adress|=(data<<shift);
17
    shift-=8;
18
  };
19

20
  one_wire_read(); // CRC
21

22
    
23
return rom_adress;
24
};
Gast #4236131
Lesenswert?
• ▲
▼
Was ist genau falsch?
Wie sollte es deiner Meinung nach richtig sein?


Meiner Meinung nach muss data erst auf uint64_t erweitert werden, bevor 
der shift stattfinden darf.

Also sowas wie
rom_adress|=( (( unint64_t)data)<<shift);


Da ich aber deine falsch/richtig-Bewertung nicht kenne, sind das nur 
Vermutungen.
#4236139
Lesenswert?
• ▲
▼
versuche es mal statt
1
  while(shift)
2
  {
3
    data=one_wire_read(); 
4
    rom_adress|=(data<<shift);
5
    shift-=8;
6
  };

so:
1
    rom_adress =   one_wire_read(); 
2
    rom_adress <<= 8;
3
    rom_adress |=  one_wire_read(); 
4
    rom_adress <<= 8;
5
    rom_adress |=  one_wire_read(); 
6
    rom_adress <<= 8;
7
    rom_adress |=  one_wire_read();

kann man natürlich auch in einer schleife machen...
1
    rom_adress = 0;
2
    for (i=0; i<4; i++) {
3
        rom_adress <<= 8;
4
        rom_adress |=  one_wire_read(); 
5
    }
#4236161
Lesenswert?
• ▲
▼
Peter F. schrieb:
> Wenn ich deine Methode mache ist der Wert während der Schleife
> 0x800000000.

Das verstehe ich dann auch nicht.
Denn wenn in den obersten 8 bit 0x80 steht, heisst das dass im ersten 
Schleifendurchlauf korrekterweise 0x80 mit rom_address ver-odert wurde.
Wenn in den nächsten Schleifendurchläufen dann jeweils 0x00 ver-odert 
wurde, heisst das für mich, dass one_wire_read() 0x00 zurückgeliefert 
hat.
Den cast auf uint64_t beim verodern müsste der Compiler eigentlich 
automatisch machen.

Kannst ja mal ausprobieren, ob ein expliziter cast

rom_adress |=  (uint64_t)(one_wire_read());

innerhalb der Schleife etwas verbessert.
#4236397
Lesenswert?
• ▲
▼
PittyJ schrieb:
> Meiner Meinung nach muss data erst auf uint64_t erweitert werden, bevor
> der shift stattfinden darf.
>
> Also sowas wie
> rom_adress|=( (( unint64_t)data)<<shift);

Ja, richtig.

> Da ich aber deine falsch/richtig-Bewertung nicht kenne, sind das nur
> Vermutungen.

Ich tendiere dazu, nicht gleich die fertige Lösung zu präsentieren, 
sondern einen Hinweis auf den Fehler, damit der Fragesteller die 
Möglichkeit hat, selbst auf die Lösung zu kommem und zu verstehen, warum 
sie nötig ist.

Peter F. schrieb:
> Vielen Dank noch mal. Aber leider Funktioniert das nicht so recht.
> @(easylife)

Dann ist wahrscheinlich wirklich was am Compiler.

> Wenn ich deine Methode mache ist der Wert während der Schleife
> 0x800000000.

Während, oder danach?

Joe F. schrieb:
> Das verstehe ich dann auch nicht.
> Denn wenn in den obersten 8 bit 0x80 steht, heisst das dass im ersten
> Schleifendurchlauf korrekterweise 0x80 mit rom_address ver-odert wurde.

Nein, denn so weit wird bei deinem Code gar nicht geshiftet, daß da 
überhaupt irgendwas ankommen darf. Im Originalcode wird maximal um 48 
Bits geshiftet, aber dein Code shiftet nur um maximal 24 Bits und 
beschreibt damit nur die unteren 32 Bits. 0x800000000 heißt aber, daß 
Bit 35 das einzige ist, das gesetzt wurde.
#4236411
Lesenswert?
• ▲
▼
Rolf M. schrieb:
> Joe F. schrieb:
>> Das verstehe ich dann auch nicht.
>> Denn wenn in den obersten 8 bit 0x80 steht, heisst das dass im ersten
>> Schleifendurchlauf korrekterweise 0x80 mit rom_address ver-odert wurde.
>
> Nein, denn so weit wird bei deinem Code gar nicht geshiftet, daß da
> überhaupt irgendwas ankommen darf. Im Originalcode wird maximal um 48
> Bits geshiftet, aber dein Code shiftet nur um maximal 24 Bits und
> beschreibt damit nur die unteren 32 Bits. 0x800000000 heißt aber, daß
> Bit 35 das einzige ist, das gesetzt wurde.

Oops, richtig. Die Schleife müsste korrekterweise 8x durchlaufen werden.
Umso unerklärlicher, dass Bit 35 gesetzt ist.

rom_adress = 0L;

eventuell...
OP #4237325
Lesenswert?
• ▲
▼
Also da haut irgendwas gewaltig nicht hin.
1
uint64_t onewire_read_rom(void)
2
{  
3
  uint64_t rom_adress = 0;
4
  uint8_t i = 0;
5

6
  
7
  onewire_reset();
8
  
9
  one_wire_putc(0x33);
10
  
11
  one_wire_read(); // Family 
12
  
13
    for (i=0; i<4; i++) {
14
        rom_adress <<= 8;
15
        rom_adress |=  one_wire_read(); 
16
    }
17

18
  one_wire_read(); // CRC
19

20
    
21
return rom_adress;
22
};

Die Werte der Schleife von links nach rechts.
1
i                 0x53         0x37           0x37          0x06
2
rom_adress  0x800000053  0x800000037  0x800000037  0x800000006

Software: Keil Arm
Debugger: J-Link EDU
#4237347
Lesenswert?
• ▲
▼
Naja, in deiner Ausgabe kann ja auch was nicht stimmen.
i läuft von 0 bis 3, und hat nicht den Wert, den one_wire_read() 
zurückliefert.

Die Schleife sollte auch von 0..7 laufen (den Fehler hat Rolf Magnus ja 
bereits erwähnt).

Es sieht so aus, als ob der Compiler die Anweisung den 64-bit Wert zu 
shiften einfach ignoriert.
Bzw. evtl. mit 64-bit Werten sehr schlecht bis gar nicht umgehen kann.

Du könntest mal nachgucken, wie der Assemblercode aussieht, den der 
Compiler aus den Anweisungen in der Schleife erzeugt.
Vielleicht bringt einen das ja weiter.

Und du solltest mal ausprobieren bei allen 64-bit Operationen long-werte 
zu verwenden. Also

uint64_t rom_adress = 0L;

und

rom_adress <<= 8L;


Ausserdem:
Benötigst du überhaupt eine 64-Bit Adresse?
Mit 32-bit kannst du bereits 4 Gigabytes adressieren...
#4237499
Lesenswert?
• ▲
▼
Schade, dass du den Beitrag wieder gelöscht hast.
War interessant.

z.B.

25:                         x=0;
0x080001F0 BF00      NOP

Klares Compilerproblem.


Dann probiere doch auch nochmal den anderen code aus...
1
    rom_adress = 0LL;
2
    for (i=0; i<8; i++) {
3
        rom_adress <<= 8LL;
4
        rom_adress |=  (unsigned long long)(one_wire_read()); 
5
    }
#4238120
Lesenswert?
• ▲
▼
Joe F. schrieb:
> Dann probiere doch auch nochmal den anderen code aus...
>     rom_adress = 0LL;
>     for (i=0; i<8; i++) {
>         rom_adress <<= 8LL;
>         rom_adress |=  (unsigned long long)(one_wire_read());
>     }

An sich dürfte das alles nicht nötig sein, also alle "LL" und der Cast 
haben nach C-Definition keine Wirkung. Mag natürlich sein, daß es durch 
einen Compiler-Bug irgendwo notwendig wird.

Nur irgendwie ist der ja auch nicht so was exotisches:

Peter F. schrieb:
> Software: Keil Arm

Ich kann mir nicht so recht vorstellen, daß der so einfache Sachen wie 
Integer Promotion oder Bit-Shifts nicht hinkriegt.

Peter F. schrieb:
> Die Werte der Schleife von links nach rechts.
> i                 0x53          0x37           0x37          0x06
> rom_adress  0x800000053  0x800000037  0x800000037  0x800000006

Bist du dir sicher, daß das die Werte von i sind? Die wären dann nämlich 
völliger Blödsinn.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.