Forum: Mikrocontroller und Digitale Elektronik Frage zu SRAM-Testfunktion


von Frank (Gast)


Lesenswert?

Hallo,
ich habe gerade ein Programm geschrieben, mit welchem ich Werte auf dem 
internen SRAM des Mikrocontrollers, in meinem Fall dem Atmega8515, 
ablegen möchte. Die ganze Aufgabe soll eine Funktion sram_test 
übernehmen, welche als Parameter den SRAM-Bereich und die Anfangsadresse 
des internen SRAMs übergeben bekommt und als Rückgabe einen Pointer 
zurückgeben soll.

Hier ist mein vorläufiges Programm:
1
#include <avr/io.h>
2
#include <util/delay.h>  
3
#include "lcd-routines.h"
4
#include <stdbool.h>
5
#include <avr/interrupt.h>
6
#include <stdio.h>        //nötig zur Benutzung von sprintf-Funktion
7
8
9
10
11
uint8_t *ergebnis_ptr;
12
char buffer[20];
13
14
uint16_t sram_anfangsadresse= 0x0060;  //Anfangsadresse des internen SRAMs
15
uint16_t sram_bereich= 0x0200;      //interner SRAM-Bereich von 512 x 1Byte
16
uint16_t sram_endadresse= 0x025F;
17
uint16_t test;
18
19
20
    
21
22
23
uint8_t* sram_test(uint16_t, uint16_t);    //Definition der Funktion
24
25
26
27
void delay_ms(uint8_t ms)
28
{
29
  while(ms>0)
30
  {
31
    _delay_ms(1);
32
    ms--;
33
  }
34
}
35
36
37
38
39
uint8_t* sram_test(uint16_t anf_adresse, uint16_t bereich)
40
{
41
  uint8_t *ptr= (uint8_t*) anf_adresse;    //Pointer an Anfangsadresse von SRAM-Bereich stellen
42
  uint16_t lauf, inhalt_zelle;
43
44
45
  PORTB &= ~(1<<PB5);    //LED an
46
  
47
48
  for(lauf=0; lauf < bereich; lauf++)    //alle Speicherzellen des internen SRAMs löschen
49
  {
50
    *ptr = 0;
51
    inhalt_zelle= *ptr;
52
    PORTB ^=(1<<PB7);
53
    
54
    
55
    lcd_setcursor(0,1);    
56
    itoa(lauf,buffer,10);    
57
    lcd_string(buffer);      //Ausgabe der Speicherzellennummer des internen SRAMs
58
59
    lcd_setcursor(0,2);
60
    itoa(inhalt_zelle,buffer,10);
61
    lcd_string(buffer);      //Ausgabe des Inhalts der jeweiligen Speicherzelle
62
63
    delay_ms(100);
64
    ptr++;    //Pointer zur nächsten Zelle weiterschieben
65
  
66
  }
67
68
  return ptr;    //Adresse zurückgeben, auf die Pointer momentan zeigt
69
}
70
71
72
73
74
  
75
  
76
int main(void)
77
{
78
  lcd_init();
79
  DDRB |= 0xFF;  //alle Pins als Ausgang
80
  PORTB |= 0xFF;  //alle LEDs aus
81
  
82
  
83
  ergebnis_ptr= sram_test(sram_anfangsadresse, sram_bereich);
84
85
  test= (uint8_t*) ergebnis_ptr;
86
87
  
88
89
  while(1)
90
  {
91
  
92
  }
93
94
95
96
}


Mein bisheriges Problem ist die for-Schleife in der Funktion sram_test. 
Eigentlich möchte ich, dass diese 512 mal durchlaufen wird und 
anschließend die Adresse der letzten Speicherzelle mittels Pointer ptr 
an den Funktionsaufrufer übergeben wird und dort an ergebnis_ptr 
übergeben wird.
Leider ist es momentan so, dass die for-Schleife nachdem sie 512 mal 
durchlaufen wurde, einfach wieder von vorne (mit lauf=0) durchlaufen 
wird. Sie wird also endlos durchlaufen und somit die Funtion sram_test 
nie mehr verlassen.

Da ich mir dieses Phänomen gerade nicht erklären kann, hoffe ich auf 
Hilfe in diesem Forum.

Gruß
von Nichtkönner (Gast)


Lesenswert?

> for(lauf=0;

muß es nicht:

> for(lauf==0;

heißen?
von holger (Gast)


Lesenswert?

Super Idee das gesamte RAM mit 0 zu beschreiben.
Dabei machst du den Stack kaputt. Vermutlich startet
dein Prozessor einfach neu. Das sieht dann so aus
als würde deine Funktion nie verlassen.
von Dietrich L. (dietrichl)


Lesenswert?

Nichtkönner schrieb:
>> for(lauf=0;
> muß es nicht:
>> for(lauf==0;
> heißen?
Nein. Das ist eine Zuweisung (Startwert!) und keine Abfrage.
von Frank (Gast)


Lesenswert?

Nichtkönner schrieb:
>> for(lauf=0;
>
> muß es nicht:
>
>> for(lauf==0;
>
> heißen?

ganz sicher nicht. das ist nämlich eine Zuweisung und kein Vergleich

holger schrieb:
> Super Idee das gesamte RAM mit 0 zu beschreiben.
> Dabei machst du den Stack kaputt. Vermutlich startet
> dein Prozessor einfach neu. Das sieht dann so aus
> als würde deine Funktion nie verlassen.

Würde eigentlich das Verhalten erklären. Aber in der Vorlesung haben wir 
schon einmal so etwas mit einem anderen Mikrocontroller gemacht. Da 
haben wir die Speicherzellen nach dem löschen halt dann danach noch mit 
anderen Werten beschrieben, bevor wir die endadresse über den Pointer 
wieder an den Aufrufer übergeben haben.
Was muss ich dann jetzt am Programm ändern damit es funktionieren kann?

Gruß
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Frank schrieb:
> Was muss ich dann jetzt am Programm ändern damit es funktionieren kann?

Sicherstellen, daß der "untersuchte" Speicherbereich nicht mit dem 
Stack, dem Heap und dem Speicher für statische/globale Variablen 
übereinstimmt.
von Karl H. (kbuchegg)


Lesenswert?

Oder krasser ausgedrückt:

Ohne intime Kentnisse, wo im Speicher der Compiler was anordnet, ist das 
was der TO da macht eine extremst schlechte Idee.

Wer mit einer Hochsprache programmiert, muss akzeptieren, dass er eine 
gewisse Kontrolle abgibt. Dazu gehören die CPU-Register und 
selbstverständlich auch die exakte Verwaltung des Speichers. Arbeitet 
man da am Compiler vorbei, dann kann das enorm ins Auge gehen.
von Frank (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Oder krasser ausgedrückt:
>
> Ohne intime Kentnisse, wo im Speicher der Compiler was anordnet, ist das
> was der TO da macht eine extremst schlechte Idee.
>
> Wer mit einer Hochsprache programmiert, muss akzeptieren, dass er eine
> gewisse Kontrolle abgibt. Dazu gehören die CPU-Register und
> selbstverständlich auch die exakte Verwaltung des Speichers. Arbeitet
> man da am Compiler vorbei, dann kann das enorm ins Auge gehen.

Respekt. Das ist wohl echt das Problem an meinem Programm. Ist es dann 
eigentlich generell zu empfehlen auf dem internen SRAM Daten abzulegen, 
wenn es so kompliziert zu handlen ist?

Ich hab das Programm jetzt mal so abgeändert, dass nur noch die ersten 
62 Speicherzellen des internen SRAMs mit 0 beschrieben werden:
1
/*Dieses Programm demonstriert die Abspeicherung einer Zeichenkette. Die einzelnen Zeichen werden
2
immer nach den in der ASCII-Tabelle zugeordneten Werten abgespeichert.*/
3
4
5
#include <avr/io.h>
6
#include <util/delay.h>  
7
#include "lcd-routines.h"
8
#include <stdbool.h>
9
#include <avr/interrupt.h>
10
#include <stdio.h>        //nötig zur Benutzung von sprintf-Funktion
11
12
13
14
15
uint8_t *ergebnis_ptr;
16
char buffer[20];
17
18
uint16_t sram_anfangsadresse= 0x0060;  //Anfangsadresse des internen SRAMs
19
uint16_t sram_bereich= 0x0200;      //interner SRAM-Bereich von 512 x 1Byte
20
uint16_t sram_endadresse= 0x025F;
21
uint16_t test;
22
23
24
    
25
26
27
uint8_t* sram_test(uint16_t, uint16_t);    //Definition der Funktion
28
29
30
31
void delay_ms(uint8_t ms)
32
{
33
  while(ms>0)
34
  {
35
    _delay_ms(1);
36
    ms--;
37
  }
38
}
39
40
41
42
43
uint8_t* sram_test(uint16_t anf_adresse, uint16_t bereich)
44
{
45
  uint8_t *ptr= (uint8_t*) anf_adresse;    //Pointer an Anfangsadresse von SRAM-Bereich stellen
46
  uint16_t lauf, inhalt_zelle;
47
48
49
  PORTB &= ~(1<<PB5);    //LED an
50
  
51
52
  for(lauf=0; lauf < (bereich-450); lauf++)    //alle Speicherzellen des internen SRAMs löschen
53
  {
54
    *ptr = 0;
55
    inhalt_zelle= *ptr;
56
    PORTB ^=(1<<PB7);
57
    
58
    
59
    lcd_setcursor(0,1);    
60
    itoa(lauf,buffer,10);    
61
    lcd_string(buffer);      //Ausgabe der Speicherzellennummer des internen SRAMs
62
63
    lcd_setcursor(0,2);
64
    itoa(inhalt_zelle,buffer,10);
65
    lcd_string(buffer);      //Ausgabe des Inhalts der jeweiligen Speicherzelle
66
67
    delay_ms(100);
68
    ptr++;    //Pointer zur nächsten Zelle weiterschieben
69
  
70
  }
71
72
73
  return ptr;    //Adresse zurückgeben, auf die Pointer momentan zeigt
74
}
75
76
77
78
79
  
80
  
81
int main(void)
82
{
83
  lcd_init();
84
  DDRB |= 0xFF;  //alle Pins als Ausgang
85
  PORTB |= 0xFF;  //alle LEDs aus
86
  
87
  
88
  ergebnis_ptr= sram_test(sram_anfangsadresse, sram_bereich);
89
90
  test= (uint8_t*) ergebnis_ptr;
91
92
  delay_ms(2000);    //zwei Sekunden warten
93
94
  itoa(test,buffer,10);
95
  lcd_clear();
96
  lcd_setcursor(0,1);
97
  lcd_string(buffer);    //Adresse von Speicherzelle ausgeben, auf die Pointer am Ende zeigt
98
99
  while(1)
100
  {
101
  
102
  }
103
104
105
106
}

Jetzt scheint das Programm nicht mehr abzustürzen. Was mir allerdings 
immer noch nicht so recht zu funktionieren scheint sind die delay_ms() 
warteschleifen. Denn die laufen wesentlich schneller ab als sie sollten.
Kann das auch daran liegen, dass ich den internen SRAM beschreibe?

Gruß
von Peter D. (peda)


Lesenswert?

Ein RAM-Test in einer Hochsprache ist eine ganz schlechte Idee. Er 
zerstört in der Regel benötigte Daten.
Wenn man dem Compiler die Verwaltung des RAM übergibt, dann darf man 
nicht mehr direkt auf den RAM zugreifen.

Schau Dir mal an, wie ein RAM-Test auf dem PC funktioniert. Zuerst wird 
der Grafikspeicher getestet. Dann wird die Testroutine in den 
Grafikspeicher kopiert und dort ausgeführt. Nun kann in aller Ruhe der 
gesamte RAM getestet werden. Nach dem Test ist das OS natürlich völlig 
durcheinander gewürfelt. Deshalb wird ein Neustart ausgeführt.

Einen RAM-Test sollte man sich also gründlich überlegen. Ansonsten 
erreicht man dadurch schnell das Gegenteil, d.h. das System wird 
unzuverlässiger.


Peter
von Frank (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Ein RAM-Test in einer Hochsprache ist eine ganz schlechte Idee. Er
> zerstört in der Regel benötigte Daten.
> Wenn man dem Compiler die Verwaltung des RAM übergibt, dann darf man
> nicht mehr direkt auf den RAM zugreifen.
>
> Schau Dir mal an, wie ein RAM-Test auf dem PC funktioniert. Zuerst wird
> der Grafikspeicher getestet. Dann wird die Testroutine in den
> Grafikspeicher kopiert und dort ausgeführt. Nun kann in aller Ruhe der
> gesamte RAM getestet werden. Nach dem Test ist das OS natürlich völlig
> durcheinander gewürfelt. Deshalb wird ein Neustart ausgeführt.
>
> Einen RAM-Test sollte man sich also gründlich überlegen. Ansonsten
> erreicht man dadurch schnell das Gegenteil, d.h. das System wird
> unzuverlässiger.
>
>
> Peter

Eigentlich möchte ich ja eigentlich nicht wirklich den SRAM testen (dass 
der richtig arbeitet glaub ich einfach), ich möchte mehr einfach Daten 
auf dem SRAM ablegen und sie später wieder auslesen und dabei die 
abgelegten Daten kontrollieren.
Ist es dann eigentlich generell eine schlechte Idee Daten auf dem 
internen SRAM abzulegen? Was gibt für Alternativen?

Gruß
von spess53 (Gast)


Lesenswert?

Hi

>Ist es dann eigentlich generell eine schlechte Idee Daten auf dem
>internen SRAM abzulegen?

Eher üblich. Allerdings solltest du, wenn du nicht in Assembler 
programmierst, die Verwaltung der Daten deinem Compiler überlassen.

>Was gibt für Alternativen?

Z.B. Arrays.

MfG Spess
von Peter D. (peda)


Lesenswert?

Frank schrieb:
> ich möchte mehr einfach Daten
> auf dem SRAM ablegen und sie später wieder auslesen und dabei die
> abgelegten Daten kontrollieren.

Wo ist das Problem?
Du legst Dir einfach Variablen an und dann kannst Du dort Daten ablegen 
und wieder auslesen.


Peter
von Frank (Gast)


Lesenswert?

spess53 schrieb:
>>Was gibt für Alternativen?
>
> Z.B. Arrays.
>
> MfG Spess

Stimmt eigentlich. Dann war das was wir beim Studieren da im Praktikum 
gemacht haben also echt nur ein reiner Test des SRAMs. Dachte irgendwie, 
dass sich das SRAM zum Abspeichern von Informationen eignet.
Aber dann weiß ich jetzt wenigstens, dass das Ablegen abspeichern von 
Daten im internen SRAM keine arg sinnvolle Maßnahme ist.

Gruß
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Doch klar, machen wir alle so. Nur nageln wir sie nicht auf feste 
Adressen, sondern lassen es den Compiler machen.
Also z.B. :
1
uint_8t myArray[200];
 reserviert mir einen 200 bytes Bereich , in dem ich indiziert Daten 
anlege oder rauslese.
Den kann ich auch beliebig löschen:
1
for (i=0;i<201;i++){
2
   myArray[i]=0;
3
  }
von Peter D. (peda)


Lesenswert?

Frank schrieb:
> Aber dann weiß ich jetzt wenigstens, dass das Ablegen abspeichern von
> Daten im internen SRAM keine arg sinnvolle Maßnahme ist.

Huch, das ist mir neu.
Jeder legt in C Daten im RAM ab, was soll er denn sonst damit machen?

Nur werden die Daten über den Variablennamen angesprochen und nicht über 
eine RAM-Adresse.
Die Adresse interessiert daher nicht.


Peter
von Tilo (Gast)


Lesenswert?

Frank schrieb:
> Eigentlich möchte ich ja eigentlich nicht wirklich den SRAM testen (dass
> der richtig arbeitet glaub ich einfach), ich möchte mehr einfach Daten
> auf dem SRAM ablegen und sie später wieder auslesen und dabei die
> abgelegten Daten kontrollieren.
> Ist es dann eigentlich generell eine schlechte Idee Daten auf dem
> internen SRAM abzulegen? Was gibt für Alternativen?

Das kann man schon machen.
Wenn die Größe des Datensatz bekannt ist, kannst du ein festes Array 
verwenden.
Wenn die größe des Datensatz unbekannt ist, kannst du dynamische 
Speicherverwaltung mit new/delete verwenden. Der Zugriff erfolgt dann 
über einen Pointer, die Daten liegen im Heap.

Was willst du mit der Kontrolle erreichen? Reicht dafür eine Prüfsumme?
Musst du auch kontrollieren, ob das Programm korrekt ist?
von H.Joachim S. (crazyhorse)


Lesenswert?

Und allein das spart einen Riesenteil der Fehler ein, die man 
unweigerlich macht, wenn man die Speicherzellen/Adressen selbst 
verwaltet.
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.