Hallo,
ich versuche gerade einen kleinen Test zu schreiben, der alle
Speicherzellen im Ram durchnudelt und schaut ob die auch noch
funktionieren.
Soll ein einfacher Test ohne Kurzschlusserkennung sein. Außerdem soll er
in C formuliert werden!
Habe das ganze so aufgezogen:
1
// Routine für den einfacheren RAM-Test
2
voidRamTest(){
3
if((iTempRamAdress+iRamCheckAnzahl)>RamE){// Prüfen ob Prüfrahmen über Ramende hinaus
// Ramzelle auf nächste Zelle setzen (falls Ramende, dann auf Ramanfang)
13
iTempRamAdress=iTempRamAdress+1;
14
if(iTempRamAdress>RamE)
15
iTempRamAdress=RamA;
16
17
}
18
19
// eigentlicher Ramtest
20
voidRamCheck(intiAadress,intiEadress){
21
chariAdress=iAadress;// Adresse übernehmen
22
intiTemp;// Variable für Speicherzelleninhalt
23
24
// solange nicht alle Zellen getestet wurden
25
while(iAdress<iEadress){
26
iTemp=*iAdress;// Inhalt speichern
27
*iAdress=0x55;// Testwerte schreiben und vergleichen
28
if(!*iAdress==0x55)
29
testError();
30
*iAdress=0xAA;
31
if(!*iAdress==0xAA)
32
testError();
33
*iAdress=iTemp;// Inhalt zurück schreiben
34
iAdress++;// Nächste Zelle
35
}
36
}
alle nicht deklarierten Variablen SIND im QC deklariert, darum bitte
keine Sorgen machen.
Wenn ich jetzt den wunderschönen Programmcode kompilieren möchte,
bekomme ich folgende Fehlermeldungen:
TestLib.c:282: error: invalid type argument of 'unary *' (have 'int')
4
TestLib.c:283: error: invalid type argument of 'unary *' (have 'int')
5
TestLib.c:284: error: invalid type argument of 'unary *' (have 'int')
6
TestLib.c:286: error: invalid type argument of 'unary *' (have 'int')
7
TestLib.c:287: error: invalid type argument of 'unary *' (have 'int')
8
TestLib.c:289: error: invalid type argument of 'unary *' (have 'int')
die Zeilen sind die unter der while-Schleife im RamCheck-Block.
Warum bekomme ich diese Fehlermeldung und wie bekomme ich sie weg. Ich
möchte auf die einzelnen Ramzellen (bei meinem ATMega169P von 0x0100 bis
0x04FF) zugreifen, sie auslesen, 2x schreiben und vergleichen, zurück
schreiben und dann die nächste zelle in angriff nehmen.
Leider habe ich im Tutorial keine Codebeispiele gefunden und auch im
Datasheet wird kein Beispiel genannt. Bin mir also leider nicht sicher
wie ich das in C realisieren kann (in ASM wäre es kein Problem, doch
bitte auf C-Ebene bleiben!)
Wer kann mir helfen?
Vielen Dank!
Max
Also ich ruf über die Ram-Test(void) quasi den Test-Vorlauf auf. Dort
bastel ich mir die Adresse zusammen. Meine Idee ist, dass diese dann als
0xirgendwas vorliegen, so dass ich nachher mit *0xirgendwas auf den
Speicher komme. Liege ich da Falsch? Wie könnte man es anders machen?
Im Prinzip will ich jede Speicherzelle zwischen 0x0100 und 0x4FF einmal
ansprechen.
Ich steh wahrscheinlich auf dem Schlauch und seh vor lauter Bäumen den
Wald nicht, vielleicht kann mir jemand einen Stubs in die richtige
Richtung geben!
>Meine Idee ist, dass diese dann als>0xirgendwas vorliegen, so dass ich nachher mit *0xirgendwas auf den>Speicher komme.
Das mag ja sein, der Compiler sieht aber nichts von deiner Idee. Was der
sieht, ist ein "int iAadress", auf das du dann den Operator "*"
anwendest, und das geht nicht.
Was du vermutlich möchtest, ist ein Pointer auf eine Speicherstelle,
also einen pointer auf einen unsigned char, "unsigned char *iAadress".
Dem Pointer kannst du deine zusammengebastelte Adresse zuweisen, und
dann damit per *-Operator im Speicher rumfuhrwerken.
Oliver
+000004AD: 91800116 LDS R24,0x0116 Load direct from data space
36
+000004AF: 91900117 LDS R25,0x0117 Load direct from data space
37
+000004B1: 91200118 LDS R18,0x0118 Load direct from data space
38
+000004B3: 91300119 LDS R19,0x0119 Load direct from data space
39
+000004B5: 0F28 ADD R18,R24 Add without carry
40
+000004B6: 1F39 ADC R19,R25 Add with carry
41
+000004B7: C001 RJMP PC+0x0002 Relative jump
42
296: iAdress++; // Nächste Zelle
43
+000004B8: 9601 ADIW R24,0x01 Add immediate to word
44
287: while(iAdress < iEadress){
45
+000004B9: 1782 CP R24,R18 Compare
46
+000004BA: 0793 CPC R25,R19 Compare with carry
47
+000004BB: F3E0 BRCS PC-0x03 Branch if carry set
48
274: iTempRamAdress = iTempRamAdress + 1;
49
+000004BC: 91800116 LDS R24,0x0116 Load direct from data space
50
+000004BE: 91900117 LDS R25,0x0117 Load direct from data space
51
+000004C0: 9601 ADIW R24,0x01 Add immediate to word
52
+000004C1: 93900117 STS 0x0117,R25 Store direct to data space
53
+000004C3: 93800116 STS 0x0116,R24 Store direct to data space
54
275: if(iTempRamAdress > RamE)
55
+000004C5: 5080 SUBI R24,0x00 Subtract immediate
56
+000004C6: 4095 SBCI R25,0x05 Subtract immediate with carry
57
+000004C7: F034 BRLT PC+0x07 Branch if less than, signed
58
276: iTempRamAdress = RamA;
59
+000004C8: E080 LDI R24,0x00 Load immediate
60
+000004C9: E091 LDI R25,0x01 Load immediate
61
+000004CA: 93900000 STS 0x0000,R25 Store direct to data space
62
+000004CC: 93800116 STS 0x0116,R24 Store direct to data space
63
+000004CE: 9508 RET Subroutine return
64
281: void Ram_Check(int iAadress, int iEadress){
65
+000004CF: 01FC MOVW R30,R24 Copy register pair
66
+000004D0: C002 RJMP PC+0x0003 Relative jump
67
288: iTemp = *iAdress; // Inhalt speichern
68
+000004D1: 8180 LDD R24,Z+0 Load indirect with displacement
69
295: *iAdress = iTemp; // Inhalt zurück schreiben
70
+000004D2: 9381 ST Z+,R24 Store indirect and postincrement
71
287: while(iAdress < iEadress){
72
+000004D3: 17E6 CP R30,R22 Compare
73
+000004D4: 07F7 CPC R31,R23 Compare with carry
74
+000004D5: F3D8 BRCS PC-0x04 Branch if carry set
75
298: }
76
+000004D6: 9508 RET Subroutine return
Warum ist das so extrem seltsam umgsetzt? Es sieht für mich so aus,
alsob die Befehle in zum Teil falscher Reihenfolge auftreten oder gleich
ganz geschluckt werden.
Kann sich das jemand erklären?
btw. wo kommt das wdt_reset her? Das habe ich, wie man oben im Quellcode
sieht, garnicht verwendet.. Sondern an ganz anderen Stellen in meinem
Programm
Max wrote:
> Warum ist das so extrem seltsam umgsetzt?
[x] Send compilable code, please.
> Es sieht für mich so aus,> alsob die Befehle in zum Teil falscher Reihenfolge auftreten oder gleich> ganz geschluckt werden.
Das wird nicht der Fall sein. Reich mal übersetzbaren Code
rüber, dann kann man sich den generierten Assemblercode mal
angucken.
> btw. wo kommt das wdt_reset her?
Ist keins drin. Oder wo würdest du den entsprechenden Code dafür
sehen?
Ich finde nach wie vor diese Disassembler-Listings absolut scheußlich
und verwirrend. Ich schau mir lieber direkt den Assemblercode an,
den der Compiler ausspuckt, ganz und gar ohne irgendwelchen C-Code
dazwischen. Den halte ich mir dann daneben (heutige Bildschirme sind
zum Glück ja breit genug) und versuche nachzuvollziehen, was der
Compiler da warum wohl gemacht hat.
hm seltsam. habe in der oben angehängten make mal die optimierung
ausgeschaltet (vorher s), nun geht der Timer-Test nichtmehr, dafür sieht
aber der Ram_Test in ASM ziemlich identisch mit dem in C aus.. Also,
wenn ihr sehen wollt wo das Problem ist, dann bitte mal die optimierung
auf s schalten (langsam krieg ich graue haare mit c!)
Dein Code ist furchtbar.
Du mischt da Datentypen wie du gerade lustig bist (Aber Hauptsache du
benutzt ungarische Notation. Genau deshalb find ich die unsinnig: Sie
bringt in der Praxis überhaupt nichts. Dein Code ist das beste Beispiel
dafür. Mit ordentlichen Variablennamen, jedes zweite Wort in deinem Code
ist entweder Tmp, Temp oder Adress wäre das Chaos schon um einiges
kleiner)
Ich denke mal, das fehlende volatile war dein Problem. Ohne dieses
volatile findet der Compiler raus, dass die Funktion im Grunde nichts
macht und optimiert sie komplett weg.
(Und lass die Datentypen in dieser Funktion so wie sie jetzt sind! Dein
Komplettpaket wird jetzt einige Fehler aufweisen. Arbeite dich von
dieser Funktion zurück und korrigiere deine Probleme beim Aufrufer.)
Max wrote:
> langsam krieg ich graue haare mit c!
Dann solltest du die Sprache mal lernen. Solche Low-Level Dinge sind
aber nicht wirklich gut geeignet das zu tun.
Naja, ich bin eigentlich sehr vertraut mit C aber das hier ging grad
irgendwie garnicht. ;/ Werd mich da aber noch reinfuchsen!
Also meine Lösung sieht bis jetzt so aus (Dank sei Karl Heinz ;)):
1
// Routine für den einfacheren RAM-Test
2
voidRam_Test(){
3
if((cErsteRamZelle+cTestLaenge)>RamE){// Prüfen ob Prüfrahmen über Ramende hinaus
Es funktioniert auch soweit!
In wiefern ist mein Code noch furchbar, abgesehen von der genannten
Routinen, in denen ich wirklich fies rumgefuhrwerkt habe und die
keinesfalls "Endgültig" waren ;)
Schmeiss diese bescheuerte hungarian Notation raus.
cStartAddr
beispielsweise ist kein char, wie dein Präfix suggeriert!
Zwichen cOriginalByte und cStartAddr besteht ein fundamentaler
Unterschied in den Datentypen, trotzdem benutzt du denselben
hungarian-Präfix dafür! Ein krasses Beispiel dafür wie blödsinnig das
Alles ist. Diese Hungarian sieht auf den ersten Blick gut aus. Die ist
es aber nicht. Sie ist eine Mogelpackung!
Einige dich mit dir selbst, ob du Variablen Namen mit englischen oder
mit deutschen Begriffen bildest.
Es ist schlecht, etwas aufs Ram zu schreiben, und gleich danach von
derselben Speicherzelle zu lesen. Mit ein wenig Glück bekommst du
sogar denselben Wert zurück, wenn du gar kein RAM angeschlossen hast,
einfach indem Leiterplattenkapazitäten den Wert auf dem Datenbus
speichern.
Mit deiner Routine würde nicht mal ein Kurzschluss über alle
Adressleitungen erkannt :-o
Besser schreibst du ein (zufälliges) Bitmuster auf 10 oder 13 oder 15
oder 17 (also keine 2er Potenz) aufeinanderfolgende Speicherzellen, und
vergleichst dann die zurückgelesenen Werte mit lokal gespeicherten
Werten.
>Es ist schlecht, etwas aufs Ram zu schreiben, und gleich danach von>derselben Speicherzelle zu lesen. Mit ein wenig Glück bekommst du>sogar denselben Wert zurück, wenn du gar kein RAM angeschlossen hast,>einfach indem Leiterplattenkapazitäten den Wert auf dem Datenbus>speichern.
Wenn ich aber einen RAM angeschlossen habe, dann bekomme ich den
RAM-Wert zurück, welcher auch der selbe ist, ausser der RAM ist defekt.
>Mit deiner Routine würde nicht mal ein Kurzschluss über alle>Adressleitungen erkannt :-o
Wieso nicht?
>Besser schreibst du ein (zufälliges) Bitmuster auf 10 oder 13 oder 15>oder 17 (also keine 2er Potenz) aufeinanderfolgende Speicherzellen, und>vergleichst dann die zurückgelesenen Werte mit lokal gespeicherten>Werten.
Warum keine 2er Potenz? Welche Fehler werden durch den Test erkannt?
Stuck-At-Faults? Transition-Faults? Coupling-Faults? Ich glaub keine
davon, oder nur durch Zufall, da der Zufallswert gerade passt.
Mr.X wrote:
> Wenn ich aber einen RAM angeschlossen habe, dann bekomme ich den> RAM-Wert zurück, welcher auch der selbe ist, ausser der RAM ist defekt.
Auch wenn das RAM defekt ist bekommst du so u.U. den korrekten Wert
zurück. Je nachdem was genau defekt ist. Beispielsweise wenn es nicht
mehr auf CE/OE reagiert, oder eine Dx Leitung defekt ist und floatet.
Die Tests sind mir vorgegeben und sind nicht von mir entwickelt. Wie
bereits einige Zeit vorher in einem Thema erwähnt dreht es sich dabei um
eine Bachelor-Abschlussarbeit und die RAM und ROM-Tests sind nur der
letzte Schliff ;)
Aber trotzdem danke für eure Anregungen, auch wenn ich, im Stress, grad
ein wenig resistent dafür bin. Hoffe einfach nur das ich es schaffe
pünktlich mit einer mir gefallenden Qualität abzugeben.
Lothar Miller wrote:
> Besser schreibst du ein (zufälliges) Bitmuster auf 10 oder 13 oder 15> oder 17 (also keine 2er Potenz)
Diese Einschränkung versteh ich auch nicht.
Warum keine 2-er Potenz?
Ich hätts so gemacht:
maximal 256 Bytes in einem Rutsch testen.
Lokales Array für entsprechend viel Speicherplatz.
max 256 Bytes (i) mit den Werten 0 bis i füllen.
Wieder auslesen und vergleichen
dieselben Zellen mit ~i füllen
wieder auslesen und vergleichen.
Damit sollten Leitungskapazitäten ausreichend ausgetrickst sein und
solange die Anzahl an Bytes nicht zu klein ist, sollten sich
Kurzschlüsse auch zeigen.
nächstes problem, wo ich bestimmt einfach grad zu verwirrt bin für.
ich möchte den ROM (Flash-Speicher) testen, indem ich über ihn eine
CRC-Summe bilde, welche ich dann im Flash-Mem ablegen möchte.
Diese soll dann zur Laufzeit ab und zu mal verglichen werden, ob im Rom
auch noch alles grün ist.
Meine Idee:
CRC-Summe über den beschriebenen Teil im Flash, da der restliche ja eh
uninteressant ist.
Diese Summe am Ende des Flashs ablegen (inklusive der Start- und
Endzelle)
Zur Laufzeit ab und zu mal ein paar Zellen zu einer Prüfsumme
zusammenfassen, solange bis die Prüfsumme über alle Zellen geht (nicht
alle auf einmal, da zu Zeitaufwendig!)
Dann prüfen.
Nun meine Probleme:
1. Wie kriege ich eine CRC über das Flash-File hin, was NUR die
bestimmten Zellen betrachtet? Geht das über das make-file? Wenn ja,
jemand ein Tutorial zur hand? Google spuckt mir kaum brauchbares raus.
2. Macht es überhaupt sinn NUR die gebrauchten Zellen zu betrachten?
3. Wie verbastel ich den Code am besten? Ich bin da absolut ratlos..
ok, ich habe jetzt mittels der avr/crc16.h eine funkion geschrieben,
welche meiner meinung nach das CRC schrittweise berechnet. nun bleibt
noch offen, wie ich das CRC einer datei berechne, wohin ich es in der
datei schreibe und wie ich erkennen kann von wo bis wo die summe
gebildet wurde.
am liebsten wäre es mir, dass ich die letzten x zellen des flashs für
den CRC nutzen kann. also an die letzte zelle (wenns denn passt) die
CRC-Summe hinschreibe, an Ende-1 das Ende des Bereichs über den ich die
CRC gebildet habe und an Ende-2 den Anfang (wobei dieser ja eh
sinnigerweise 0x0000 sein sollte).
Gibt es eine einfache möglichkeit das zu machen? srecord habe ich schon
gelesen, allerdings komme ich nicht ganz dahinter ob er die CRC über die
gesamte datei bildet, wohin er die summe schreibt und sowas.. wenn es
über die gesamte datei bildet, dann bringt es mir ja nicht, da die sich
ja ändert wenn er die CRC dann einfügt..
Vielleicht kann mir ja doch einer helfen.
Also ich habe jetzt mit srecord 1.42 (für Windows) eine CRC16-Summe
(CCITT) über meine *.hex datei gebildet. Diese wurde in den letzten
beiden Zellen (0x3FFE, 0x3FFF - Big Endian-Art) gespeichert.
Allerdings kann ich nirgendwo nachsehen, über welchen Bereich dieser
Datei die Summe gebildet wurde, also kann ich auch mit meiner
Kontrollroutine nicht die korrekte (oder eher die Prüfsumme über den
korrekten Rahmen) bilden.
Meine Funktion sieht so aus:
1
// Zeiger auf aktuelle Position des Flashspeichers
2
unsignedchar*cFlashZeiger=(unsignedchar*)0x0000;
3
// Anzahl der zu testenden Flashzellen pro Zyklus
4
unsignedintiFlashTestLaenge=10;
5
// aktueller CRC-Wert
6
uint16_tiCRC;
7
// Anfang und Ende der CRC-Berechnung des Flash-Speichers
wobei die while(1)-Schleife im moment nur zu Testzwecken drin ist um zu
sehen was denn die CRC-Routine berechnet hat.
Kann mir bitte jemand sagen, wie ich rausfinden kann über welchen
Bereich der CRC von der hex gebildet wird?
Max wrote:
> Kann mir bitte jemand sagen, wie ich rausfinden kann über welchen> Bereich der CRC von der hex gebildet wird?
Denk logisch!
Weiss das srecord Utility, wie gross der nicht benutzte Flash Bereich
ist?
Nein
Weiss das srecord Utility, wie gross der benutzte Flash Bereich ist?
Ja, im File steht ja drinnen, was dort abzulegen ist.
Und jetzt geb ich die Frage an dich zurück:
Was wird wohl das srecord Utility machen (können)?
Ich komm nicht wirklich dahinter was du mir damit sagen willst.. Ich
vermute du möchstest mir sagen, dass die CRC-Summe nur über den
benutzten bereich gebildet wird, darum frage ich dich nun: woher weiß
das programm wo dieser Endet? Endet er vor dem ersten 0xFFFF? Was wird
als "Loch" definiert, da im Manual steht, dass Löcher nicht
berücksichtigt werden!
Max wrote:
> woher weiß> das programm wo dieser Endet? Endet er vor dem ersten 0xFFFF? Was wird> als "Loch" definiert, da im Manual steht, dass Löcher nicht> berücksichtigt werden!
Schon mal in ein HEX File hineingeschaut und eine Beschreibung des
Formats studiert?
Hinweis: Am Anfang der jeder Zeile steht sowas wie ein Befehl und im
Falle dass hier Datenbytes abgelegt wurden, auch, wohin diese Bytes im
Speicher gehören.
Ergo -> Das srecord Utility ist in der Lage sich ein komplettes
Speicherabbild des Flash zu basteln. Das einzige was es nicht weiß ist,
wie gross das Flash ist. Aber vielleicht gibts ja auch einen Command
Line Switch dafür.
(Edit: In der Zeit, die du hier verplemperst, hättest du schon 3 mal
selbst ein CRC Tool schreiben können und von dem genau wüsstest, was es
tut)
So, klink mich jetzt wieder aus. Du hast weiter oben das Zauberwort
gesagt: Bachelor-Abschlussarbeit
Und das ist ja dann schliesslich nicht irgendwas. Immerhin verlangst du
dann von deinem ersten Arbeitgeber einen Haufen Geld dafür, dass du was
kannst.
Ich habe schon in das Hex-File reingeschaut und gesehen, dass dort
deutlich mehr Daten drin stehen als mir später vom AVR-Studio als
Programmspeicher angezeigt werden.