AVR und große Konstanten = Reboot?

Hi Leute, ich habe hier einen ATMega16, den ich mit WinAVR programmiere. Ich steuere damit ein Grafik-Display mit 2 SED1520 an. Zeichensätze habe ich mir realtiv umständlich via

static const UCHAR font6x8[][5]={ {0, 0, 0, 0, 0}, {0, 0, b01011111, 0, 0}, {b01111111, b00001001, b00001001, b00001001, b00000110}, //" {b01111111, b00001001, b00001001, b00001001, b00000110}, //# {b00000000, b00000010, b00000101, b00000010, b00000000}, //$ {b01111111, b00001001, b00001001, b00001001, b00000110}, //% {b01111111, b00001001, b00001001, b00001001, b00000110}, //& {b01111111, b00001001, b00001001, b00001001, b00000110}, //' . . . . . }

... deklariert. Die ganzen Binärzahlen existieren in einer separaten Datei als DEFINES.

Bisher hat das ganze immer wunderbar funktioniert. Ich habe den Zeichensatz immer weiter erweitert und ab einer bestimmten Größe, läuft der AVR nicht mehr richtig und resetet ständig (mehrfach pro Sekunde).

Diese Datei mit den Zeichensätzen und den Grafikroutinen könnt Ihr Euch unter

formatting link
anschauen. Es sind zwei unvollständige Zeichensätze integriert. Diese Version der Datei funktioniert noch. Ergänze ich jedoch an einem der Zeichensätze einige weitere Zeichen, führt das zu ständigem Reseten des AVR. Das Display zeigt immer kurz noch was an, teilweise funktioniert die Software also noch. Doch nach einigen ms ist dann wohl endgültig Ende und es gibt einen Reset. Umd das zu überprüfen habe ich die SW so erweitert, dass bei jedem Reset als erstes ein Port getoggelt wird. Das passiert dann mehrmals pro Sekunde.

An was kann das liegen? Ich greife auf die Zeichensätze ja nur lesend zu, kann also theoretisch maximal fehlerhafte Zeichen darstellen, wenn irgendwo anders was schief geht.

Macht der Compiler da Müll? Gibts ne andere Möglichkeit, Zeichensätze (große Datenmengen) einzubinden.

Wie würdet Ihr bei der Fehlersuche vorgehen?

Wenn wir schon dabei sind. Ich habe den Zeichensatz von Hand eingegeben, hatte nur einen Ausdruck zweier Zeichensätz zur Verfügung. Diese Arbeit ist ziemlich öde. Gibts im Netz irgendwo Zeichensätze zum runterladen?

weihnachtliche Grüße Michael

Reply to
Michael Rübig
Loading thread data ...

Ergänzung: Wenn ich am zweiten Zeichensatz was ergänze, reagiert der Controller etwas anders. Er rebootet z.B. 5 Sekunden lang ständig und erreicht dann einen stabilen Zustand. Manchmal läuft er auch einige Sekunden problemlos und dann gehts plötzlich los. Das Fehlerbild ist also nach jedem Reset anders, obwohl ich keine SW-Änderung gemacht habe.

Sieht irgendwie schwer nach Hardwarefehler aus. Aber warum ist der abhängig von der Software?

Gruß Michael

Reply to
Michael Rübig

Michael Rübig schrieb:

Ändere ich die Optimierungsstufe des Compilers, ändert sich auch das Verhalten des Controllers. Er hängt sich auch auf, rebootet aber nicht mehr.

Michael

Reply to
Michael Rübig

Michael Rübig schrieb:

Du solltest deine Konstanten im Programmspeicher und nicht im RAM anlegen. Wie das geht steht in der Doku der AVRLibc.

--
Matthias Weißer
matthias@matwei.de
http://www.matwei.de
Reply to
Matthias Weißer

Hi,

Ah, guter Ansatz, mal schauen ... Ich bin davon ausgegangen, dass die Konstanten bei dieser Deklaration im Programmspeicher angelegt werden. Wenn das nicht so ist, wird wahrscheinlich einfach das RAM voll sein ... Wahrscheinlich gibts dann einen Stack-Überlauf oder so. Das würde einiges erklären...

Gruß Michael

Reply to
Michael Rübig

Noch ne Frage':

Also ich habe das jetzt mal so deklariert:

static const PROGMEM UCHAR font8x16[][12]={ ....

jetzt läuft der AVR wieder durch. Allerdings funktioniert der Zugriff auf diese Konstante jetzt nicht mehr. Es wird also Müll ausgegeben. Bisher habe ich byteweise so darauf zugegriffen: Dummy = font8x16[ASCII-Zeichen][Index];

Ich vermute mal, dass ich nun mit read_pgm_byte_near(font8x16+ASCII_Zeichen*Index) auf diese Konstante zugreifen kann.

ASCII_Zeichen: erste Dimension des Arrays Index : Nr des Bytes innerhalb des Zeichens, auf das ich zugreifen will

Leider funktioniert das so nicht. Ich kann jetzt auch nicht weiterprobieren, weil ich zum Weihnachtsessen muss.

Ein Tipp für heute Abend wäre aber nicht schlecht.

Gruß Michael

Reply to
Michael Rübig

nöööö.

Es sieht nach einer Überbelegung des Arbeitsspeichers aus. Vermutlich versuchst du, mit dem Stack Daten zu überschreiben, oder sowas.

Delkariere deine Zeichenarrays im ROM und greife dann darauf zu:

*const unsigned char zeichenfeldoffset = [startadresse]

und greife dann auf die einzelnen Zeichen mit Zeigeroperationen zu.

Robert

Reply to
R.Freitag

Ab einer bestimmten Grösse (ich tippe mal auf 256byte) funktioniert der Arrayzugriff mit [] nicht mehr vernünftig, ist wohl ein Bug im Compiler. Ich habe mir dafür eine kleine Assemblerroutine geschrieben:

.file "hack.S" .arch atmega8515 .globl xxxx_bits ; Arraystart .global getval .type getval,@function ;extern char getval(int n); getval: mov r30,r24 mov r31,r25 ldi r23,hi8(xxxx_bits) ldi r22,lo8(xxxx_bits) add r30,r22 adc r31,r23 lpm mov r24,r0 ret

--
         Georg Acher, acher@in.tum.de
         http://wwwbode.in.tum.de/~acher
         "Oh no, not again !" The bowl of petunias
Reply to
Georg Acher

Ich glaube Du meinst eher read_pgm_byte_near(font8x16 + ASCII_Zeichen * 12 + Index)

Das Schema für char array[Y][X] ist *(p + y * X + x). In Deinem Fall wuerde ja mit ASCII_Zeichen = 5 und Index = 8 das gleiche Element wie bei ASCII_Zeichen = 8 und Index = 5 adressiert werden, das waere arg komisch.

Gruss, Felix

Reply to
Felix Opatz

Hallo Felix,

Ist mir inzwischen aus aufgefallen

Es geht trotzdem nicht. Muss jetzt mal suchen, wo der Fehler liegt.

Michael

Reply to
Michael Rübig

Felix Opatz schrieb:

Ich habe mal testweise folgendes deklariert: static const PROGMEM UCHAR test[][2]={

{1, 2}, {3, 4}, {5, 6}, {7, 8} };

pgm_read_byte_near(test) -> 1 pgm_read_byte_near(test+1) -> 3 pgm_read_byte_near(test+2) -> 5 pgm_read_byte_near(test+3) -> 7 pgm_read_byte_near(test+4) -> 2 pgm_read_byte_near(test+4) -> 4

Das würde Deiner Formel widersprechen und mich ziemlich ankotzen. Um das umzusetzen muss ich die größe des Arrays wissen, welche ich ja offen gelassen habe. Naja, das müsste mit sizeOf gehen. Allerdings kann der Compiler dann nicht das LPM Rd,Z+ benutzen, um das nächste Byte des Zeichen einzulesen, und muss bei jedem Zugriff die Adresse neu laden, was die Performance deutlich beeinträchtigen wird.

Irgendwelche Ideen?

Michael

Reply to
Michael Rübig

Michael Rübig schrieb:

Wozu überhaupt ein zweidimensionales Array?

Reicht denn unsigned char PROGMEM chartab[] = { 0x00,0x00,0x00,0x00,0x00, 0x02,0x20,0x44,0x40,0x6A, ..... };

nicht? Zugriff dann einfach mittels cur_byte = pgm_read_byte(chartab + char_num*5 + byte_in_char);

--
Matthias Weißer
matthias@matwei.de
http://www.matwei.de
Reply to
Matthias Weißer

Hi,

Am Anfang hat das ja noch Sinn gemacht, weils einfach übersichtlicher war. Aber jetzt ist das ne gute Frage. Ich habs inzwischen eindimensional gemacht.

Danke für die Hilfe, Michael

Reply to
Michael Rübig

Michael Rübig schrieb:

Hast Du es schon mal mit Simulation versucht. Gerade solche Speicherschreiber & Stackprobleme sind damit sehr viel einfacher zu finden. simulavrxx erzeugt komplette Tracefiles mit Interruptstatistik usw. Einen Reset kann man auch leicht an Adresse 0x0000 erkennen usw. Da kannst Du dem Problem wirklich sehr schnell auf die Schliche kommen. Auch wenn Du externe Hardware mit simulieren musst ist es eine Hilfe.

formatting link

Gruß Klaus

Reply to
Klaus Rudolph

[...]

Bis hier haette ich noch gemutmasst, dass einfach jedes zweite Byte gelesen wird, weil der Programmspeicher wordweise organisiert ist und irgendwas mit dem byte nicht ganz klappt.

Das hier finde ich allerdings etwas sonderbar. Sowohl dass es jetzt die anderen Komponenten ausgibt, als dass Du Dich vertippt hast ;-)

In diesem Fall sollte es Dich auch ziemlich ankotzen, denn:

int main(void) { int i, j, n = 0; char test[][2] = { {1, 2}, {3, 4}, {5, 6}, {7, 8} }; char *p = (char*)test;

for (i = 0; i < 4; i++) for (j = 0; j < 2; j++) { printf("test[%i][%i] = %i\t", i, j, test[i][j]); printf("*(p + %i) = %i\n", n, *(p + n)); n++; }

return 0; }

ergibt bei mir die Ausgabe

test[0][0] = 1 *(p + 0) = 1 test[0][1] = 2 *(p + 1) = 2 test[1][0] = 3 *(p + 2) = 3 test[1][1] = 4 *(p + 3) = 4 test[2][0] = 5 *(p + 4) = 5 test[2][1] = 6 *(p + 5) = 6 test[3][0] = 7 *(p + 6) = 7 test[3][1] = 8 *(p + 7) = 8

wie ich es auch erwartet haette (jetzt unter FreeBSD auf i386). Irgendwas ist also komisch [TM].

Neues Posting mit aussagekraeftigem Subject und hoffen, dass Joerg was dazu sagt *g*

Vielleicht findest Du ja auch das System darin, und kannst drumherumbasteln, also Deine Komponenten so in das Array legen, dass es beim Auslesen stimmt. Nicht schoen, aber selten.

Die Idee es als eindimensionales Array bzw. einfach als Puffer zu machen, in dem Du selbst den Krempel organisierst, wurde ja auch schon genannt.

Gruss, Felix

Reply to
Felix Opatz

Wenn du es brauchen kannst: Für ebend dieses Display hab' ich eine komplette Grafiklibrary samt Font-Routinen und Konvertertools zum konvertieren von PalmOS-Fonts geschrieben. Das ganze ist zwar nicht für AVR's gedacht, sondern für einen IPC@Chip, aber die Sache ist in C geschrieben, und du solltest zumindest einige Teile übernehmen können.

Ausserdem hab' ich auch noch ein Fontpack mit ca. 100 Fonts auf der Homepage, die alle schon passend für das Display (also in diesem komischen Zeilenformat) kodiert sind.

siehe:

formatting link

sowie im speziellen:

formatting link
formatting link

Achtung: Mein Source steht unter der GPL. Die Fonts sind von Rainer Zenz für die Verwendung mit meinem MP3-Player freigegeben. Bei Verwendung in eigenen Anwendungen also *unbedingt* bei ihm nachfragen. (siehe

formatting link

--
thomas.kindler@gmx.de, www.kreapc.de
Reply to
Thomas Kindler

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.