Frage zu SRAM-Testfunktion

Gast #2513421
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ß
Gast #2513588
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ß
#2513667
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.
Gast #2513753
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ß
#2513809
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
Gast #2513820
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ß
Gast #2513840
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
Gast #2514012
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ß
(Firma: matzetronics) #2514175
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
  }
#2514312
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
Gast #2514337
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren