Hallo zusammen, ich versuch ein Menü auf dem LCD Display vom MSP430 darzustellen. Dazu wollte ich das Ganze per doppelt verkettete Liste realisieren. Ich hab alles unter C normal in einer kleinen Konsolenanwendung getestet und nun wollte ich alles auf den uC übertragen und merkte dabei, dass da irgendetwas nciht stimmt. Als ich mir dann die liste mit der Quickwatch angeguckt habe, sah das so aus, wie ein Speicherüberlauf o.Ä. Der Controller ist ein FG4618. Den Screenshot seht ihr im Anhang. Man erkennt deutlich, wie die Speicheradresse mittendrin wieder bei 0x00 anfängt. Links daneben seht ihr im Code, wie die Liste aufgebaut ist. Gibt es vielleicht irgendeine Möglichkeit dem Controller zu sagen, dass er die Liste irgendwo speichern soll, wo mehr Platz ist (Ich erinnere mich nur grob an die Stichworte Code-, Daten-, und Stack-Segment. Das Daten Segment müsste doch genug Platz haben - oder nicht?). Vielen Dank für eure geduldige Hilfe :-) EDIT: Wenn ich die auskommentierten Knoten wieder mit einschalte, dann fängt der Controller schon früher an zu spinnen...
>Gibt es vielleicht irgendeine Möglichkeit dem Controller zu sagen, dass >er die Liste irgendwo speichern soll, wo mehr Platz ist je nach Compiler vielleicht dieses? #pragma abs_address:<0x????> (ICC-Compiler)
Wir verwenden übrigens die IAR Embedded Workbench IDE. Wo müsste ich diesen Hinweis für den Compiler denn platzieren? An die Funktion zum erstellen eines Knotens? An die Struktur (struct) des Knotens? Der Controller hat übrigens 8kb RAM. Das kann doch nicht schon voll sein... Wie kann ich meine Liste dahin verlagern?
Hier mal ein Abdruck solch eines Problems. Die Vorinitvariablen (können auch Strings sein) sollen vom Linker/Locater in des Flash-Segment A des MSP430F149 gelegt werden:
1 | // Flash-Segment A:
|
2 | #pragma abs_address:0x1080
|
3 | unsigned int uiFlashArrayA[64] = |
4 | { 0x0000, 0x032F, 0xFFFF, 0xFFFF, |
5 | 0x0003, 0x2301, 0xFFFF, 0xFFFF, // BR_PORT1, Messgr.ID/Busadresse, |
6 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
7 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
8 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
9 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
10 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
11 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
12 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
13 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
14 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
15 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
16 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
17 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
18 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // irgendwas 4x |
19 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF // irgendwas 4x |
20 | };
|
21 | #pragma end_abs_address
|
Zur Änderung des Speicherplatzes kann man die Strings auch mit const unsigned char* deklarieren. Der Locater sucht dann den optimalen Platz.
Wenn Du Variablen als const deklarierst, landen sie beim MSP430 im Flash-ROM, von dem es deutlich mehr gibt als RAM. Dein Menü dürfte eine konstante Struktur haben, also solltest Du es komplett ins Flash-ROM packen können.
Wenn ich ein "const" vor die Definition der struct stelle, kommt eine Warnung, dass das "bedeutungslos" wäre. Wenn ich das const vor die Listendeklaration stelle, gibt es auch Fehler. Ist ja auch logisch, denn eigentlich ändert sich dadrin immer irgendetwas bis die Liste komplett aufgebaut ist.
Roland Moch schrieb: > Wenn ich ein "const" vor die Definition der struct stelle, kommt eine > Warnung, dass das "bedeutungslos" wäre. Das dürfte ein typedef sein, also eine Typdeklaration. Typen an sich sind aber nicht const. > Ist ja auch logisch, denn eigentlich ändert sich dadrin immer > irgendetwas bis die Liste komplett aufgebaut ist. Das ist die hohe Kunst der Initialisierung. Oder soll das Menü wirklich erst zur Laufzeit zusammengebastelt werden? Aber selbst dann können die einzelnen Elemente des Menüs bis auf die Zeiger const sein. Wie gesagt, alles eine Frage der Initialisierung.
Ja, der Titel könnte const sein, aber das wird schwierig mit der Initialisierung. Du hast recht, eigentlich muss das Menü nicht zur Laufzeit aufgebaut werden, dann ist ein Array doch vielleicht besser geeignet, oder? Zwei Arrays: Eins mit dem Menütitel, ein anderes mit einem Opcode und dann reicht eine Int-Variable für den Index des aktuellen Menüs. Ist zwar nicht mehr so elegant, aber darum geht es bei Microcontrollern im Gegensatz zu den Hochsprachen auf den PCs auch nicht, oder? Was meinst du?
Ich würde die Strings aus dem Befehl extrahieren, in const einhüllen und diese dann durch eine Routine auslesen und anzeigen lassen. Mal schnell als Beispiel:
1 | const unsigned char Messen_String1 [] = {"gemessen am:"}; |
2 | |
3 | |
4 | NT_String_senden ((unsigned char*)Messen_String1); |
5 | |
6 | |
7 | //Funktion
|
8 | //----------------------------
|
9 | |
10 | void NT_String_senden (unsigned char *string) |
11 | {
|
12 | unsigned char i=0; |
13 | |
14 | |
15 | while((string[i] != '\0')&&(i<31)) |
16 | {
|
17 | |
18 | SOFT_UART_TXD ((unsigned int) string[i]); |
19 | i++; |
20 | |
21 | }
|
22 | SOFT_UART_TXD (0); |
23 | }
|
Roland Moch schrieb: > Zwei Arrays: Eins mit dem Menütitel, ein anderes mit einem Opcode und > dann reicht eine Int-Variable für den Index des aktuellen Menüs. Wozu zwei? Man kann doch auch Strukturen in ein array packen. Z.B.
1 | typedef struct { |
2 | const int prev; |
3 | const int next; |
4 | const int list; |
5 | const char* title; |
6 | const char opcode; |
7 | } node_t ; |
8 | |
9 | const node_t menu[] = { |
10 | {3, 1, 0, "a", 0x01 }, |
11 | {0, 2, 0, "b", 0x02 }, |
12 | {1, 3, 0, "c", 0x03 }, |
13 | {2, 0, 0, "d", 0x04 }, |
14 | // ...
|
15 | };
|
prev, next, list sind dann halt keine Pointer, sondern Arrayindizes. Vom Prinzip her also fast dasselbe wie Deine verkettete Liste, nur halt nicht dynamisch zur Laufzeit erzeugt sondern statisch zur Compilezeit.
Wow, vielen Dank für diese gute Idee. Das hört sich wirklich ausgezeichnet an und ist gar nicht so "unelegant" :-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.