Forum: Mikrocontroller und Digitale Elektronik SRAM in C direkt auslesen


von Timm T. (Gast)


Lesenswert?

Es ist bestimmt ganz einfach, aber ich habe erst mit C angefangen und 
komme nicht drauf:

Wie kann ich den Inhalt des Sram auslesen und an der seriellen 
Schnittstelle ausgeben? Also angefangen an einer Startadresse jeweils 16 
Byte lesen und als Hexzahl senden. Das Senden ist kein Problem, aber wie 
adressiere ich den Sram?

In Asm hätte ich einfach XL,XH auf die Adresse gesetzt und dann mit LD 
r,X+ abgefragt. Aber in C?

Und dazu noch: Kann ich den Compiler anweisen, (globale) Variablen im 
Sram auf bestimmte Adressen zu legen, so daß ich die Variablen in meinem 
Sram-Dump wiederfinde?

Das GCC-Tut geht darauf leider auch nicht ein.

von Michael K. (Gast)


Lesenswert?


von Codix (Gast)


Lesenswert?

Ich würde es bspw. so machen:
1
    uint8_t *memory_pointer;
2
    uint8_t inhalt_zum_senden;
3
4
    memory_pointer = start_adresse; // start_adresse als hexwert.
5
6
    inhalt_zum_senden = *memory_pointer;
7
  // Naechste Adresse
8
    memory_pointer++; // Aber auch mit Distanzen, ist besser, da sich
9
                      // die Basisadresse des Pointers nicht ändert!
10
    // mit Distanz
11
    inhalt_zum_send = *memory_pointer + 1; // wobei die 1 auch eine variable 
12
                                           //  sein kann

von Mark B. (markbrandis)


Lesenswert?

Timm T. schrieb:
> Und dazu noch: Kann ich den Compiler anweisen, (globale) Variablen im
> Sram auf bestimmte Adressen zu legen, so daß ich die Variablen in meinem
> Sram-Dump wiederfinde?

Du kannst einfach den Inhalt der Variablen, die Dich interessieren, über 
die serielle Schnittstelle versenden.

Was genau versprichst Du Dir von einem kompletten SRAM-Dump? Wie Deine 
Frage schon nahelegt, würdest Du darin die für Dich relevanten Daten 
schwerer wiederfinden als wenn Du einfach nur die Werte ausgibst, die 
Dich wirklich interessieren.

Abgesehen davon ist die Antwort auf Deine Frage abhängig von dem 
verwendeten Compiler bzw. Linker.

Siehe auch:
http://stackoverflow.com/questions/4067811/how-to-place-a-variable-at-a-given-absolute-address-in-memory-with-gcc

: Bearbeitet durch User
von Timm T. (Gast)


Lesenswert?

Mark B. schrieb:
> Du kannst einfach den Inhalt der Variablen, die Dich interessieren, über
> die serielle Schnittstelle versenden.

Mach ich doch schon. Für die Werte, die nach außen interessant sind.

Mark B. schrieb:
> Was genau versprichst Du Dir denn von einem kompletten SRAM-Dump?

Interne Variablen zu prüfen, die normalerweise nicht nach außen gehen, 
ohne jedesmal extra ein serielles Write festzulegen.

Zum Beispiel sollen eine Menge Parameter im Eeprom gespeichert und ins 
Sram übernommen werden, in Arrays. Übernommen deswegen, weil bei 
ungültigen Parametern stattdessen Standardwerte aus dem Flash verwendet 
werden sollen. Für die Kontrolle der korrekten Übernahme soll ein Dump 
des Eeprom und des Sram möglich sein.

Codix schrieb:
> Ich würde es bspw. so machen

Ach ja, die Pointer. Damit stehe ich noch auf Kriegsfuß.

Sorry, es ist ein ATmega32. Da müßte der Pointer ein uint_16 sein, um 
den gesamten Ram zu adressieren, oder?

von Mark B. (markbrandis)


Lesenswert?

Timm T. schrieb:
> Sorry, es ist ein ATmega32. Da müßte der Pointer ein uint_16 sein, um
> den gesamten Ram zu adressieren, oder?

Ein Zeiger wird danach deklariert, worauf er zeigt. Wenn er also auf ein 
Byte im Speicher zeigen soll, wird er mit uint8_t* deklariert.

Die Größe der Zeigervariablen selbst hängt vom Prozessor ab.

von Timm T. (Gast)


Lesenswert?

Mark B. schrieb:
> Ein Zeiger wird danach deklariert, worauf er zeigt. Wenn er also auf ein
> Byte im Speicher zeigen soll, wird er mit uint8_t* deklariert.

Ähm, der Pointer bekommt die Adresse, an der ausgelesen werden soll.

Ich hab das jetzt mal so zusammengeklöppelt:
1
void  send_mem_sram(uint16_t addr) {
2
  uint8_t    k;
3
  uint16_t  *memptr;
4
  
5
  serial_write(Cssram);    // Frame Sram senden
6
  serial_hex4(addr);    // Start Adresse senden
7
  
8
  memptr = (uint16_t*)addr;
9
  for (k = 0; k < 8; k++) {
10
    serial_write(',');
11
    serial_hex4(*memptr);  // Sram Wert
12
    memptr += 2;
13
  }
14
  serial_write('\n');
15
}

von Mark B. (markbrandis)


Lesenswert?

Timm T. schrieb:
> Mark B. schrieb:
>> Ein Zeiger wird danach deklariert, worauf er zeigt. Wenn er also auf ein
>> Byte im Speicher zeigen soll, wird er mit uint8_t* deklariert.
>
> Ähm, der Pointer bekommt die Adresse, an der ausgelesen werden soll.

Wenn Du ein Byte lesen willst, dann dereferenzierst Du einen Zeiger, 
der auf ein Byte zeigt. Nicht auf zwei Byte.

Beispielcode am PC mit Ausgabe:
1
#include <stdint.h>
2
#include <stdio.h>
3
4
int main()
5
{
6
    uint8_t zu_lesender_bytewert = 0x6F;
7
    
8
    uint8_t * zeiger;
9
    
10
    zeiger = &zu_lesender_bytewert;
11
    
12
    printf("Preisfrage: Wie gross ist die Zeigervariable selbst? Antwort: %d Bytes\n", sizeof(zeiger));
13
    printf("Und nicht etwa 1 Byte.\n");
14
    
15
    return 0;
16
}
1
Preisfrage: Wie gross ist die Zeigervariable selbst? Antwort: 4 Bytes
2
Und nicht etwa 1 Byte.

Wenn Du verstehen willst warum, dann mache Dir klar dass der Datenbus 
und der Adressbus unterschiedliche Breiten haben können.

von Timm T. (Gast)


Lesenswert?

Mark B. schrieb:
> Wenn Du ein Byte lesen willst, dann dereferenzierst Du einen Zeiger,
> der auf ein Byte zeigt.

Ok, verstanden. Nun lese ich ein Word aus dem Sram und übergebe es an 
serial_hex4(), um es als $FFFF zu senden. Sollte also so stimmen.

Oder gibts in meinem Codebeispiel Unstimmigkeiten? Irgendwas, wo ein 
erfahrener C-Programmierer sagt: Das macht man aber anders?

von Markus F. (mfro)


Lesenswert?

Timm T. schrieb:
> Das macht man aber anders?

Durchaus.
1
  memptr = (uint16_t*)addr;
2
  for (k = 0; k < 8; k++) {
3
    serial_write(',');
4
    serial_hex4(*memptr);  // Sram Wert
5
    memptr += 2;
6
  }
7
  serial_write('\n');

Wenn Du byteweise lesen willst, solltest Du auch Bytes lesen:
1
    memptr = (uint8_t *) addr;

C inkrementiert oder dekrementiert Zeiger abhängig davon, worauf sie 
zeigen, "von alleine" richtig. Das
1
    memptr += 2;
ist deshalb hier jedenfalls verkehrt (damit überspringst Du ein Wort).
Wenn Du einen Zeiger auf ein 16 Bit-Wort um eins inkrementierst, zeigt 
er auf das nächste Wort, nicht auf das nächste Byte. Wenn Du einen 
Zeiger auf ein Byte (uint8_t *) um eins inkrementierst, zeit er auf das 
nächste Byte.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Timm Thaler (timm-thaler)

>Wie kann ich den Inhalt des Sram auslesen und an der seriellen
>Schnittstelle ausgeben?

Über einen Pointer, wie hier schon mehrfach beschrieben.

>In Asm hätte ich einfach XL,XH auf die Adresse gesetzt und dann mit LD
>r,X+ abgefragt. Aber in C?

Nahezu identisch.

>Und dazu noch: Kann ich den Compiler anweisen, (globale) Variablen im
>Sram auf bestimmte Adressen zu legen, so daß ich die Variablen in meinem
>Sram-Dump wiederfinde?

Vergiss diesen Unsinn, sonst kannst du gleich bei ASM bleiben. In C 
verwaltet der Compiler die Adressen der Variablen, und das ist gut so. 
Wenn du wissen willst, welche Variable an welcher Adresse steht, schau 
ins .map File.

von Timm T. (Gast)


Lesenswert?

Markus F. schrieb:
> Wenn Du byteweise lesen willst, solltest Du auch Bytes lesen:

Nope, ich will ein Word übergeben. Funktioniert jetzt auch.

Markus F. schrieb:
> memptr += 2;
> ist deshalb hier jedenfalls verkehrt (damit überspringst Du ein Wort).

Das hab ich auch gemerkt. Zu schlau, der Compiler.

Falk B. schrieb:
> In C
> verwaltet der Compiler die Adressen der Variablen, und das ist gut so.

Ja, das fliegt mir nur gerade um die Ohren: Die Eeprom-Arrays werden 
auch nach Lust und Laune platziert, und wenn ich ein Array ändere oder 
Eeprom-Variablen zufüge, liegen die zuvor im Eeprom gespeicherten Daten 
am falschen Platz.

Das muß besser gehen, ich will nicht jedesmal, wenn ich den Code neu 
compiliere befürchten müssen, daß meine ganzen Eeprom-Parameter im Eimer 
sind und ich das Ding neu parametrieren muß.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Tim, in der Regel gibt es ein Tx Buffer, bzw legt den so an:

uint8_t byBuffTx [16];

Wo das im Ram liegt ist doch egal. Mit einer For Schleife sendet man das 
dann:

uint8_t i;
for (i=0; i <sizeof (byBuffTx); i++) {
  while (!Uart frei...){};
  Uart Tx Register = byBuffTx [i];
}

: Bearbeitet durch User
von Timm T. (Gast)


Lesenswert?

Häh? Was willst Du jetzt mit dem Buffer? Natürlich gibt es einen Buffer 
für die RS232, aber das ist nicht meine Frage.

Das Problem Speicherzugriff ist ja auch gelöst, mir geht es noch darum, 
die Variablen im Eeprom festzupinnen, damit sie immer an der gleichen 
Stelle stehen.

Allerdings habe ich im Forum schon gesehen, daß das wohl nicht ohne 
größere Klimmzüge geht.

von Markus F. (mfro)


Lesenswert?

Du solltest dir überlegen, die Variablen, die Du da immer in der 
gleichen Reihenfolge (und am liebsten immer an der gleichen Adresse) 
vorfinden willst, in eine struct zu stecken.

Dann wird der Compiler die für dich zusammenhalten und Du tust dir 
insgesamt leichter.

Dann könntest Du - wenn's denn unbedingt sein muß (was ich aber nicht 
empfehlen würde), im Linkerscript einfacher dafür sorgen, daß die struct 
immer an der gleichen Stelle steht.

Eleganter fände ich, die struct im ersten Wort mit einem eindeutigen 
Kenner zu versehen:
1
struct globals
2
{
3
    const uint32_t marker;
4
    const size_t size;
5
    /* ab hier die nach außen interessanten Variablen */
6
    uint8_t var1;
7
    uint8_t var2;  
8
};
9
10
static struct globals my_vars =
11
{
12
   .marker = 0xaffeaffe,
13
   .size = sizeof(struct globals),
14
   .var1 = ... 
15
};

und bei der Ausgabe das Datensegment nach diesem Kenner zu durchsuchen.

Dann ist egal, wo die struct steht und Du mußt das Ding nie wieder 
anfassen, außer um neue Variablen einzubauen:
1
uint8_t *addr = _data_start;
2
struct globals *glbls = NULL;
3
do
4
{
5
    if ((uint32_t *)addr == 0xaffeaffe)
6
    {
7
        glbls = (struct globals *) addr;
8
        if (glbls->size == sizeof(struct globals))
9
            break;
10
        glbls = NULL;
11
    }
12
} while (addr++ != _data_end);
13
14
if (glbls != NULL)
15
{
16
    ...
17
}

Besonders effektiv ist das natürlich nicht (muß es aber wohl auch 
nicht), aber einigermaßen robust.

von Falk B. (falk)


Lesenswert?

@ Timm Thaler (timm-thaler)

>> In C
>> verwaltet der Compiler die Adressen der Variablen, und das ist gut so.

>Ja, das fliegt mir nur gerade um die Ohren: Die Eeprom-Arrays werden
>auch nach Lust und Laune platziert, und wenn ich ein Array ändere oder
>Eeprom-Variablen zufüge, liegen die zuvor im Eeprom gespeicherten Daten
>am falschen Platz.

Tja, bisher war davon auch keine Rede! Man sollte die Netiquette 
beherzigen und das eigentliche Problem ansprechen und nicht 
vermeintliche Lösungen.

>Das muß besser gehen, ich will nicht jedesmal, wenn ich den Code neu
>compiliere befürchten müssen, daß meine ganzen Eeprom-Parameter im Eimer
>sind und ich das Ding neu parametrieren muß.

Sicher. Man muss nur die richtige Frage stellen. Pack alle EEPROM 
Variablen in ein Struct, dort ist die Reihenfolge fest. Und da es nur 
eine "Variable" im EEPROM gibt, nämlich das Struct, liegt das immer an 
der gleichen Adresse, meist 0.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Und ändere dann nicht die Reihenfolge der Struktur und auch nicht die 
Datentypen von z.b. 8 > 16 Bit. Dann fliegt dir das auch um die Ohren.

Ps: Für neue Fragen solltest du auch ein neuen Tread auf machen und 
nicht mich anmachen weil ich zum eigentlichen Thema geantwortet habe.

von Falk B. (falk)


Lesenswert?

@ Markus Müller (mmvisual)

>Und ändere dann nicht die Reihenfolge der Struktur und auch nicht die
>Datentypen von z.b. 8 > 16 Bit. Dann fliegt dir das auch um die Ohren.

Wem DAS nicht klar ist, der sollte besser mit Murmeln spielen!

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Mark B. schrieb:
> Preisfrage: Wie gross ist die Zeigervariable selbst? Antwort: 4 Bytes
> Und nicht etwa 1 Byte.

auf dem AVR sicher nicht ;-)

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Falk B. schrieb:
> Sicher. Man muss nur die richtige Frage stellen. Pack alle EEPROM
> Variablen in ein Struct, dort ist die Reihenfolge fest. Und da es nur
> eine "Variable" im EEPROM gibt, nämlich das Struct, liegt das immer an
> der gleichen Adresse, meist 0.

Evtl noch als "packed" deklarieren, damit kein sinnloses Padding 
eingebaut wird ...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Mampf F. schrieb:
> Evtl noch als "packed" deklarieren, damit kein sinnloses Padding
> eingebaut wird ...

Auf AVRs ist bereits alles packed. Noch "packender" geht nicht ;-)

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

"packed" wirkt doch nur auf CPUs mit >8Bit. Trotzdem wird dem GCC ein 
Compilerschalter direkt mitgegeben, zumindest beim alten AVR-Studio 
4.18. Warum?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mit avr-gcc kannst du ganz einfach aufs SRAM zugreifen:
1
#include <stdint.h>
2
3
extern uint8_t __data_start[];
Wenn du das 3. Byte des SRAM willst, dann ist das __data_start[2].

Falls du in 16-Bit Happen lesen willst, dann:
1
extern uint16_t __data_start[];

Das Symbol __data_start wird im Linker-Description-File definiert.

von Frank M. (ukw) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Falk B. schrieb:
> "packed" wirkt doch nur auf CPUs mit >8Bit.

Jepp.

> Trotzdem wird dem GCC ein
> Compilerschalter direkt mitgegeben, zumindest beim alten AVR-Studio
> 4.18.

Ja, sehe ich bei mir auch im AVR-Studio 4.18. Scheint tatsächlich 
Default beim Anlegen eines AVR-Projekts zu sein, denn ich habs da 
bestimmt nicht hinzugefügt.

(Interessanter fand ich allerdings Deine uralte gcc-Version :-P )

> Warum?

Vielleicht Dummheit? Solls auch bei Atmel geben.

: Bearbeitet durch Moderator
von Falk B. (falk)


Lesenswert?

@ Frank M. (ukw) Benutzerseite

>(Interessanter fand ich allerdings Deine uralte gcc-Version :-P )

Das ist der letzte offizielle winavr, der direkt mit AVR-Studio 
zusammenspielt. Es gibt zwar eine Anleitung, den aktuellen avr gcc ins 
alte AVR-Studio einzuklinken, das hat aber beim 1. VErsuch nicht 
funktioniert, dann hab ich es gelassen. Für meine Zwecke ist auch der 
alte avr gcc ausreichend. Die neuen ATXmegas kann man so oder so nicht 
im 4.x AVR Studio programmieren.

>> Warum?

>Vielleicht Dummheit? Solls auch bei Atmel geben.

Vorsicht mit solchen vorschnellen Anschuldigungen! Der GCC, das 
Grundgerüst des avr gcc, ist ein ausgewachsener Compiler, der für 
"richtige" CPUs mit 16/32 Bit gemacht ist. Es wäre möglich, daß der ohne 
den -packed Compilerschalter IMMER von 16 Bit Alignment ausgeht, auch 
auf 8 Bit Maschinen. Schließlich macht er auch Integer-Promotion auf 16 
Bit Ints, auch wenn das manchmal nicht nötig ist.

von Mark B. (markbrandis)


Lesenswert?

Mampf F. schrieb:
> Mark B. schrieb:
>> Preisfrage: Wie gross ist die Zeigervariable selbst? Antwort: 4 Bytes
>> Und nicht etwa 1 Byte.
>
> auf dem AVR sicher nicht ;-)

Deswegen steht ja auch "Beispielcode am PC" dabei :-)

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Falk B. schrieb:
> Das ist der letzte offizielle winavr, der direkt mit AVR-Studio
> zusammenspielt.

Weiß ich. Hatte ich auch mal drauf.

Aber es spielt auch jeder neuere avr-gcc mit AVR-Studio zusammen, s.u.

> Es gibt zwar eine Anleitung, den aktuellen avr gcc ins
> alte AVR-Studio einzuklinken, das hat aber beim 1. VErsuch nicht
> funktioniert, dann hab ich es gelassen.

Man muss die Toolchain nur irgendwo in einem Pfad ohne Leerzeichen 
entpacken und dann einen einzigen Registry-Eintrag ändern und schon wird 
jeder neuere avr-gcc zum Standard-Compiler für AVR-Studio. Schau mal in 
mein Bild. Da ist "Use WinAVR" angehakt :-)

Ich mag nämlich das alte AVR-Studio auch lieber. Läuft viel flotter als 
jede Version, die danach kam.

> Vorsicht mit solchen vorschnellen Anschuldigungen! Der GCC, das
> Grundgerüst des avr gcc, ist ein ausgewachsener Compiler, der für
> "richtige" CPUs mit 16/32 Bit gemacht ist.

Ja, aber der avr-gcc ist NICHT direkt von Atmel. Jedoch die 
Default-Settings im AVR-Studio ;-)

Ich kenne gcc seit Ende der Achtziger, habe ihn damals selbst für einige 
UNIX-68k-Derivate portiert. Du musst also nicht denken, dass ich hier 
das Blaue vom Himmel erzähle.

> Es wäre möglich, daß der ohne
> den -packed Compilerschalter IMMER von 16 Bit Alignment ausgeht, auch
> auf 8 Bit Maschinen. Schließlich macht er auch Integer-Promotion auf 16
> Bit Ints, auch wenn das manchmal nicht nötig ist.

Nein, es ist definitiv so: Bei ATmega/ATtiny ist alles packed. Kann Dir 
Johann auch so bestätigen, er muss es ja wissen :-)

P.S.
Im Anhang der Registry-Patch für avr-gcc 4.7.2, den man von
  http://sourceforge.net/projects/mobilechessboar/files/avr-gcc%20snapshots%20%28Win32%29/

herunterladen kann. Ist für mich die derzeit stabilste Version. Soviel 
ich weiß, hat diese Johann höchstpersönlich dort abgelegt. Du kannst 
also der Software dort vertrauen.

: Bearbeitet durch Moderator
von Falk B. (falk)


Lesenswert?

@Frank M. (ukw) Benutzerseite

>Man muss die Toolchain nur irgendwo in einem Pfad ohne Leerzeichen
>entpacken und dann einen einzigen Registry-Eintrag ändern und schon wird
>jeder neuere avr-gcc zum Standard-Compiler für AVR-Studio. Schau mal in
>mein Bild. Da ist "Use WinAVR" angehakt :-)

Ok, werd ich mal probieren.

>Ich mag nämlich das alte AVR-Studio auch lieber. Läuft viel flotter als
>jede Version, die danach kam.

Eben.

>Ich kenne gcc seit Ende der Achtziger, habe ihn damals selbst für einige
>UNIX-68k-Derivate portiert. Du musst also nicht denken, dass ich hier
>das Blaue vom Himmel erzähle.

Ohh, ein Insider!

>Nein, es ist definitiv so: Bei ATmega/ATtiny ist alles packed. Kann Dir
>Johann auch so bestätigen, er muss es ja wissen :-)

Das glaub ich dir schon.

>P.S.
>Im Anhang der Registry-Patch für avr-gcc 4.7.2, den man von
>  http://sourceforge.net/projects/mobilechessboar/fi...

>herunterladen kann. Ist für mich die derzeit stabilste Version. Soviel
>ich weiß, hat diese Johann höchstpersönlich dort abgelegt. Du kannst
>also der Software dort vertrauen.

Danke, werde ich demnächst mal machen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Falk B. schrieb:
> Ok, werd ich mal probieren.

Das klappt schon. Allerdings fehlen in der Toolchain make & Co.

Das ist aber kein Problem: Einfach nach dem Auspacken den Ordner utils 
aus Deinem alten WinAVR20100110-Ordner in den neuen avr-gcc-4.7.2-Ordner 
kopieren.

Wenn ich es richtig in Erinnerung habe, arbeitet auch avr-size.exe in 
späteren Versionen nicht mehr so wie früher. Wenn das bei Dir auch der 
Fall sein sollte, kopiere dann:

  C:\WinAVR20100110\bin\avr-size.exe

nach

  C:\avr-gcc-4.7.2\bin\avr-size.exe

Dann sollte alles so "wie früher sein", nachdem Du die REG-Datei 
ausgeführt hast. Die müsstest Du aber vielleicht vorher noch bearbeiten, 
denn da steht bei mir als Pfad drin:
1
"UninstallString"="C:\\WinAVR\\avr-gcc-4.7.2\\WinAVR-20100110-uninstall.exe"

Hintergrund ist der, dass ich für jede avr-gcc-Version (4.3.3, 4.7.2, 
4.8.1, 4.9.2) einen eigenen Unterordner unter C:\WinAVR habe - und 
natürlich für jede Compiler-Version eine eigene REG-Datei. So kann ich 
bequem zwischen den verschiedenen Compilern per Doppelklick auf die 
REG-Datei umschalten. ;-)

Ist aber nur was für Spezialisten, die sich den erzeugten Code unter 
verschiedenen Versionen anschauen wollen. Ich habe mich mittlerweile 
komplett auf den 4.7.2 eingeschossen und schon lange nicht mehr 
gewechselt. 4.8.1 hat leider eine Macke, dass es fälschlicherweise 
Meldungen über falsch geschriebene ISR-Vektornamen ausgibt (das übrigens 
Johann damals höchstpersönlich "verbockt hatte ;-) ), 4.9.2 hat auch 
irgendeine andere blöde Eigenheit, kann sein, dass es mit/ohne(?) LTO 
schlechteren Code als 4.7.2 erzeugte... weiß ich nicht mehr so genau. 
5.2.1 ist relativ frisch, damit habe ich mich noch nicht näher 
beschäftigt.

Fazit: Mit der 4.7.2 machst Du nichts falsch.

Also mit der auf Sourceforge:

   avr-gcc-4.7.2-mingw32.zip  2012-09-25

Da liegt nämlich überflüssigerweise auch noch ein Release-Candidate 
(rc1) älteren Datums rum.

Wenn Du fertig bist, kannst Du Dich freuen, dass die Compilate Deiner 
bisherigen Projekte nachher alle viel viel kleiner sind :-)

Wenn Du es noch ganz perfekt machen willst, kannst Du auch noch die 
Umgebungsvariable PATH über die Systemsteuerung an den neuen 
avr-gcc-Pfad anpassen, dann kannst Du den neuen avr-gcc auch in einer 
Windows-Eingabeaufforderung ohne weitere Pfad-Angabe starten. Da wird 
nämlich sonst noch der alte von 2010 genommen.

Achja: Falls Du Dich wunderst, dass diese in der REG-Datei angegebene 
WinAVR-20100110-uninstall.exe ja gar nicht existiert: Muss sie auch 
nicht!

Denn das Magische daran ist: AVRStudio sucht nach dem Programmstart nach 
genau diesem Uninstall-String in der Registry und wählt als Kriterium, 
wo es den avr-gcc usw. findet, den Pfad davor(!) aus!

Ist das nicht krank? Aber es funktioniert perfekt. :-)

P.S.
Ich habe schon öfters überlegt, ob ich diese Anleitung nicht mal im Wiki 
als Artikel anlgen sollte. Habs aber nicht gemacht, weil ich dachte, 
dass so viele Leute nicht mehr mit dem alten AVR-Studio arbeiten. 
Vielleicht lohnt es sich doch?

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Frank M. schrieb:
> 5.2.1 ist relativ frisch, damit habe ich mich noch nicht näher
> beschäftigt

Ich habe es gerade mal runtergeladen und exakt nach meiner obigen 
Anleitung installert - klappt. Mal schnell ein paar Projekte durchgejagt 
und verglichen: ca. 3-4% an Code-Ersparnis gegenüber 4.7.2.

Die 5.2.1 werde ich mir in den nächsten Tagen wohl doch mal näher 
anschauen... könnte evtl. mein neuer Favorit werden.

: Bearbeitet durch Moderator
von Falk B. (falk)


Lesenswert?

@  Frank M. (ukw) Benutzerseite

>> Ok, werd ich mal probieren.

>Das klappt schon. Allerdings fehlen in der Toolchain make & Co.

>Das ist aber kein Problem: Einfach nach dem Auspacken den Ordner utils
>aus Deinem alten WinAVR20100110-Ordner in den neuen avr-gcc-4.7.2-Ordner
>kopieren.

Hier fangen meine Fußnägel langsam an, sich aufzurollen 8-0
Die alten Utils mit dem neuen Compiler? Sowas schreit immer nach 
Problemen. Darum greife ich hier immer nur auf Komplettpakete zurück, 
die (hoffentlich) von Profis getestet sind.

>Wenn ich es richtig in Erinnerung habe, arbeitet auch avr-size.exe in
>späteren Versionen nicht mehr so wie früher. Wenn das bei Dir auch der
>Fall sein sollte, kopiere dann:

>  C:\WinAVR20100110\bin\avr-size.exe

>nach

>  C:\avr-gcc-4.7.2\bin\avr-size.exe

>Dann sollte alles so "wie früher sein", nachdem Du die REG-Datei
>ausgeführt hast. Die müsstest Du aber vielleicht vorher noch bearbeiten,
>denn da steht bei mir als Pfad drin:

GENAU DAS MEINE ICH!

"UninstallString"="C:\\WinAVR\\avr-gcc-4.7.2\\WinAVR-20100110-uninstall. 
exe"

>Ist aber nur was für Spezialisten, die sich den erzeugten Code unter
>verschiedenen Versionen anschauen wollen.

Eben. Und das bin ich nicht. Es gibt beim 2010er winAVR keine 
Funktionen, die ich wirklich vermisse. __flash und andere Spielrein sind 
entbehrlich.
Alles neuere läuft bei mir im Atmelstudio 6.2 (die lahme Ente!)

> Ich habe mich mittlerweile
>komplett auf den 4.7.2 eingeschossen und schon lange nicht mehr
>gewechselt. 4.8.1 hat leider eine Macke, dass es fälschlicherweise
>Meldungen über falsch geschriebene ISR-Vektornamen ausgibt (das übrigens
>Johann damals höchstpersönlich "verbockt hatte ;-) ), 4.9.2 hat auch
>irgendeine andere blöde Eigenheit, kann sein, dass es mit/ohne(?) LTO
>schlechteren Code als 4.7.2 erzeugte... weiß ich nicht mehr so genau.
>5.2.1 ist relativ frisch, damit habe ich mich noch nicht näher
>beschäftigt.

Never change a running system ;-)

>Fazit: Mit der 4.7.2 machst Du nichts falsch.

OK.

>Wenn Du fertig bist, kannst Du Dich freuen, dass die Compilate Deiner
>bisherigen Projekte nachher alle viel viel kleiner sind :-)

Ich bin nich Moby.

>Wenn Du es noch ganz perfekt machen willst, kannst Du auch noch die
>Umgebungsvariable PATH über die Systemsteuerung an den neuen
>avr-gcc-Pfad anpassen, dann kannst Du den neuen avr-gcc auch in einer
>Windows-Eingabeaufforderung ohne weitere Pfad-Angabe starten.

Mach ich so oder so nie. Ich bin nur ein Normaluser. Trotzdem Danke für 
die Tips.

>Denn das Magische daran ist: AVRStudio sucht nach dem Programmstart nach
>genau diesem Uninstall-String in der Registry und wählt als Kriterium,
>wo es den avr-gcc usw. findet, den Pfad davor(!) aus!

AUA!!!!

>Ich habe schon öfters überlegt, ob ich diese Anleitung nicht mal im Wiki
>als Artikel anlgen sollte. Habs aber nicht gemacht, weil ich dachte,
>dass so viele Leute nicht mehr mit dem alten AVR-Studio arbeiten.
>Vielleicht lohnt es sich doch?

Keine Ahnung, tendentiell eher nicht. Du hast ja schon mehrere Beiträge 
dazu verfaßt.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Falk B. schrieb:
> Hier fangen meine Fußnägel langsam an, sich aufzurollen 8-0
> Die alten Utils mit dem neuen Compiler?

Wenn sie bisher ihren Dienst taten, dann tun sie es auch mit neuem 
Compiler. make macht auch nix anderes als vorher und hat auf das 
Compiler-Ergebnis keinen Einfluss :-)

> Keine Ahnung, tendentiell eher nicht. Du hast ja schon mehrere Beiträge
> dazu verfaßt.

Okay. Ich nehme auch an, dass das AVR-Studio 4.18 sowieso wegen neueren 
Windows-Versionen irgendwann ausstirbt. Oder läuft das noch unter 
Windows 8 oder 10?

von Sven L. (svenl)


Lesenswert?

Um noch einmnal zum eigentlichen Problem des TE zurück zu kommen:

Er hat das Problem seine Variablen im EEPROM nicht wieder zu finden. :) 
Der Ansatz einen Struct zu verwenden ist das vernünftigste.

Ich baue meine Software immer so auf:
- alle Konfigurationsdaten in eine struct (Padding erst einmal egal, 
i.d.R. hat man genügend EEPROM-SPeicher)
- int EEPROM_read(uint16 addr) und int EEPROM_write(uint16 
addr)-Funktionen programmieren, welche die Struktur unter der Adresse 
addr abspeichern
- EEPROM_read() und EEPROM_write() nutzen zum Feststellen der 
Dateninegrität zum Beispiel einen CRC16 und lesen bzw. schreiben in 
diesem Falle 2 Bytes mehr

EEPROM_write() speichert, und man liest die Daten mit EEPROM_read() 
zurück. Der Rückgabewert von EEPROM_read() signalisiert dann, ob der 
CRC-Check erfolgreich war. War er es nicht, werden entsprechende 
Defaults geladen.

Den SRAM-Dump braucht man dafür nicht. Mit ein wenig Nachdenken hätte 
man aber schon auf so eine Lösung kommen können, wenn man davon ausgeht, 
dass sämtliche E/A-Daten auch vollkommener Müll sein können.

Viele Grüße!

Sven

von ausverkauft (Gast)


Lesenswert?

Johann L. schrieb:
> Mit avr-gcc kannst du ganz einfach aufs SRAM zugreifen:#include
> <stdint.h>
>
> extern uint8_t __data_start[];
> Wenn du das 3. Byte des SRAM willst, dann ist das __data_start[2].
>
> Falls du in 16-Bit Happen lesen willst, dann:extern uint16_t
> __data_start[];
>
> Das Symbol __data_start wird im Linker-Description-File definiert.

Da sollte der Linker aber meckern! Zwei oder mehr Symbole auf die 
gleiche Adresse? Oder gibt es keine anderen Variablen im RAM?

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.