Guten Tag.
Ich bastel nun seid einigen Stunden daran meinen ATMega 162 um einen
externen 64k sram zu erweitern. Leider will mir das trotz intensivem
lesen der Foren und google nicht gelingen.
Ich bin der Meinung, dass ich den RAM und das Latch richtig verkabelt
habe... es lief bisher auf dem mC ein Programm, fuer welches ich jetzt
mehr Speicher brauche. Das Programm das bisher lief habe ich nun
ausreichend getestet, von Fehlern am uart ist nicht auszugehen. Ich
dimensioniere nun einen Array in einen Bereich, den der interne sram des
mC noch aufnehmen kann, beschreibe das array und sende die daten per
uart - das laeuft soweit.
meldung des compilers:
1
Data: 165 bytes (16.1% Full)
2
(.data + .bss + .noinit)
hier die variable aus einer header datei
1
#define DAT_BUFFER_SIZE 128
2
volatileunsignedchardat_buffer[DAT_BUFFER_SIZE];
Wenn ich nun aber DAT_BUFFER_SIZE soweit erhoehe (z.b. 2048), das der
Inhalt des Arrays nicht mehr in das interne sram passt, dann verhält
sich die Rueckgabe des uart (der im endeffekt nur den inhalt von diesem
array sended) schlagartig scheinbar komplett zufällig. Es wird garnicht,
stückweise oder falsch ausgelesen. Deshalb gehe ich davon aus, das ich
das externe sram nicht richtig verwende.
meldung des compilers:
1
Data: 2085 bytes (203.6% Full)
2
(.data + .bss + .noinit)
Hier sehe ich schonmal ein Problem und frage mich warum der Compiler die
64k externen speicher hier nicht beruecksichtigt.
hier ein ausschnitt aus der main.c
1
#include<avr/io.h> //header für die register
2
#include<stdint.h> //header für lesezugriffe
3
4
#include"uart.h"
5
6
#ifndef F_CPU
7
8
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 14745600"
9
#define F_CPU 14745600UL // Systemtakt in Hz - Definition als unsigned long beachten >> Ohne ergeben Fehler in der Berechnung
UCSR0B|=(1<<RXEN0)|(1<<TXEN0);// UART RX und TX einschalten
48
UCSR0C|=(1<<URSEL0)|(3<<UCSZ00);// Asynchron 8N1
49
50
UBRR0H=UBRR_VAL>>8;//setzen der Baudrate
51
UBRR0L=UBRR_VAL&0xFF;//setzen der Baudrate
52
53
sei();
54
55
//wait until condensators are charged up
56
intwaittimer=0;
57
while(waittimer<30000)
58
{
59
waittimer++;
60
}
61
//beschreiben einer stelle die meiner meinung nach mitten im sram liegen muesste
62
uint8_t*pExtSRAM=(uint8_t*)0x2FFF;
63
uint8_t*pExtSRAMandererPointer=(uint8_t*)0x2FFF;
64
65
uart_write_char(pExtSRAMandererPointer[0]);
66
67
pExtSRAM[0]=0x60;
68
uart_write_char(pExtSRAM[0]);
69
uart_write_char(pExtSRAMandererPointer[0]);
70
//....
Ich bin mir nicht sicher, ob ich alle wichtigen Register fuer den sram
und das xmem gesetzt habe (siehe "void xram(void)"). Ausserdem ist mir
die zeile
nicht klar. Ich verstehe sie so, dass die Funktion xram geladen wird
(und damit der speicher initialisiert) bevor andere Programmteile
ausgefuehrt werden, damit die anderen Programmteile eben diesen Speicher
verwenden koennen. geschiet das auch vor dem definieren einer Variable
ueber den header wie in meinem Beispiel? Und muss das Makefile irgendwie
bezug auf ".init1" nehmen ? Ist ".init1" an sich schon eine klar
definierte Phase oder muss ich darum im makefile irgendwie bezugnehmen?
Ich wundere mich wo die Stelle ".init1" definiert ist, ist dem Linker
einfach nur durch diese Bezeichnung klar in welcher Phase des ...
Bootvorganges diese Funktion "xram" geladen werden soll?
hier evtl nocheinmal alles von dem ich denke das es fuer das externe
sram notwendig ist aus dem makefile:
Hm... da hab ich lange gesucht ;-)
"Ist ".init1" an sich schon eine klar
definierte Phase"
Guck hier: AVR-Libc Manual "8.7 Memory Sections"
Also....ich habe bei mir (ATMEGA128, 64k externes SRAM
den Heap(!) ins externe Ram gelegt, die deklarierten variablen
(.data und .bss) bleiben im internen.
Und zwar so:
-Wl,--defsym=__heap_start=0x801100
-Wl,--defsym=__heap_end=0x80ffff
Die Option
-Wl,--section-start,.data=0x800500,--defsym=__heap_end=0x80ffff
dagegen legt .data und .bss auch noch ins externe RAM
Schau mal, hier ist ne ganze Doktorarbeit übers Thema
Beitrag "Externes Speicherinterface Hintergrundwissen"
Hat mir sehr geholfen, außerdem im AVR-libc-Manual das Kapitel
8.3.16 How to use external RAM?
auf S. 195.
ACHTUNG: Variablen auf dem Heap (pointer)musst Du immer mit malloc()
allozieren, z.B.:
1
uint8_t*Buffer;
2
Buffer=malloc(BUFSIZE*sizeof(uint8_t)
Geht auch fix, ist aber nicht schön
Zu guter letzt:
[/c] statt [/code] ;-)
Andreas Paulin wrote:
> ACHTUNG: Variablen auf dem Heap (pointer)musst Du immer mit malloc()> allozieren, z.B.:
Man kann aber den externen Speicher auch ganz ohne Heap benutzen.
Einfach einen Zeiger passend casten und die Verwaltung komplett
manuell vornehmen:
1
uint8_t*bigarray=(uint8_t*)0x2000;/* array in XMEM, length 1024 */
2
uint16_t*another=(uint16_t*)0x2400;/* another array */
> Wenn ich nun aber DAT_BUFFER_SIZE soweit erhoehe (z.b. 2048), das der> Inhalt des Arrays nicht mehr in das interne sram passt, dann verhält> sich die Rueckgabe des uart (der im endeffekt nur den inhalt von diesem> array sended) schlagartig scheinbar komplett zufällig.
Hast du denn auch mal einen prüfenden Blick in den Sourcecode geworfen?
Vielleicht eine 8-Bit-Variable für den Index verwendet?
> //beschreiben einer stelle die meiner meinung nach mitten> im sram liegen muesste
Und, funktioniert denn das, oder auch nicht?
Jo, danke schonmal für die Antworten.
von dem Array dat_buffer habe ich nun erstmal abstand genommen, den
schon das auslesen einzelner bytes will nicht gelingen.
Ich habe bisher erstmal die Fuse fuer das JTAG deaktiviert, die sorgte
schonmal dafür dass der Port C teilweise schlecht belegt war. Da liegen
gleichzeitig die JTAG und die hohen Adress Pins beim ATMega 162. Als ich
das endlich gefunden hatte dachte ich schon das wäre es jetzt gewesen,
wars aber nicht. Der code schaut im moment so aus : die hterm ausgabe
habe ich unten angehaengt.
1
#include<avr/io.h> //header für die register
2
#include<stdint.h> //header für lesezugriffe
3
4
#include"cam.h"
5
#include"uart.h"
6
7
#ifndef F_CPU
8
9
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 14745600"
10
#define F_CPU 14745600UL // Systemtakt in Hz - Definition als unsigned long beachten >> Ohne ergeben Fehler in der Berechnung
Das macht auf mich den Eindruck, als sei da ein Wackelkontakt oder ne
induzierte Spannung und etwas dergleichen. Darauf hin habe ich die Pins
saemtlich mit dem Auge abgesucht und nichts gefunden. benachbarte pins
mit nem multimeter durchgemessen, nichts gefunden.
zu
1
uint8_t*bigarray=(uint8_t*)0x2000;/* array in XMEM, length 1024 */
Das verstehe ich noch nicht ganz. Ich dachte es handelt sich hier um
einen Pointer auf einen Array dessen elemente jeweils vom type her
uint8_t sind.
Mit
1
bigarray[0]=0x00;
dachte ich auf Adresse 0x2000 einen uint8_t (8 bit) mit nullen zu
füllen. Sollte ich danach
1
bigarray[1]=0x00;
verwenden, so dachte ich das ich dann das zweite Element des Arrays mit
nullen fülle - um ein Offset verschoben welches sich aus der grösse des
Typs uint8_t ergibt. So das nun an Adresse 0x2000 und 0x2001 alle 16
bits 0 sind. Ist das nicht richtig ? Ich bin irritiert wegen der "length
1024". evtl liegt ja auch hier mein fehler.
Ich habe dann jetzt nochmal probiert das makefile so zu gestalten wie
Andreas Paulin es vorgeschlagen (nur heap, malloc) hat und folgenden
code verwendet:
1
uint8_t*Buffer=malloc(2000*sizeof(uint8_t));
2
3
Buffer[0]=0x00;
4
uart_write_char(Buffer[0]);
5
Buffer[0]=0xFF;
6
uart_write_char(Buffer[0]);
7
Buffer[0]=0x01;
8
uart_write_char(Buffer[0]);
9
Buffer[0]=0x02;
10
uart_write_char(Buffer[0]);
11
Buffer[0]=0x03;
12
uart_write_char(Buffer[0]);
13
Buffer[0]=0x04;
14
uart_write_char(Buffer[0]);
15
Buffer[1800]=0x05;
16
uart_write_char(Buffer[1800]);
17
Buffer[1900]=0x06;
18
uart_write_char(Buffer[1900]);
19
20
free(Buffer);
Tja, "manchmal" waren die Werte in Ordnung, meistens waren die Werte
falsch - Die Fehler waren ziemlich zufaellig verteilt und nicht
haeufiger oder weniger haeufig als richtige Ergebnisse, was an sich doch
dafür spricht, dass das Ram zumindest arbeitet, nur halt nicht so wie es
soll. Nach mittlerweile 10 Stunden herrumprobieren liegt für mich ein
deffekter Chip oder nen Wackelkontakt am nächsten.
uint8_t*bigarray=(uint8_t*)0x2000;/* array in XMEM, length 1024 */
> Ich bin irritiert wegen der "length 1024". evtl liegt ja auch> hier mein fehler.
Das "length 1024" ist wohl als "Gedächtnisstütze" für den Programmierer
da, denn der Ausdruck definiert nur einen Pointer (wie du richtig
ausgeführt hast), und beinhaltet daher keine Information zur Länge des
Array.
Mache doch mal bitte ein paar Angaben zur Hardware, also Latch und RAM
(genaue Typenbezeichnung).
Kleine Anmerkung zum Schaltplan. Die Datenleitungen RxD vom MAX zum
Controller ist nicht richtig angeschlossen :-). Und ich sehe auch gerade
das du einen 128Kbyte RAM verwendest, schließe doch einfach A16 auch mit
an den Controller an, dann kannst du die restlichen 64Kbyte auch noch
nutzen über umwegen (siehe Banking). Aber nicht vergessen das du A16
auch richtig Einstellst (Controllerpin als Output einstellen, sonst gibt
es komische effekte :-) ).
Aber so sieht es schon mal gut aus, und sollte vom Prinzip her richtig
sein.
Ja, Danke - das stimmt. In der Hardware ist der RX/TX auch schon richtig
angeschlossen. Flüchtigkeitsfehler beim entwerfen des Schaltplans den
ich erst beim löten bemerkt und in dem Moment in den dox nicht
korrigiert habe. Den A16 schliesse ich evtl. spaeter an wenn der Rest
laeuft. Das Ding ist, das ich mit dem Ram zwei Bilder einer Digicam
gleichzeitig speichern will. 8 bit Graustufe auf 160*120 = 19200 oder
320*240 = 76800. für 320*240 reichen weder 64k noch 128k und fuer
160*120 reichen auch 64k, deswegen habe ich davon bisher abgesehen. Wenn
dieser eine ram laeuft dann werde ich evtl. nochmal nen ganz anderes
setup für den Ram verwenden (grösserer Stein, oder mehrere Steine) um
2*640*480*8bit = 2*307200*8bit speichern zu können. Hier habe ich
nämlich bei der Auslegung den dummen Fehler gemacht, den Ram um Faktor
10 zu klein auszulegen. eigentlich waren 2*307200*8bit geplant, und das
sollten etwas weniger als 64k sein, sind aber etwas weniger als 640k ...
, doof das :)
Naja, aber step by step. Fürs erste möchte ich erstmal nur das vom avr
vorgesehene setup verwenden, ohne zusätzliche Adressleitungen um Fehler
an dieser Stelle ausschliessen zu können. Erstmal muss 1 byte des Rams
laufen :)
Aber generell sollte ich dann das Programm so schreiben, dass ich gleich
direkt auf die Adressen zugreife um sie zu beschreiben statt malloc zu
verwenden oder den Variablen automatisch speicher zuweisen zu lassen,
weil sich das dann später vermutlich einfach auf eine von xmem nicht
unterstütze Adressbreite übertragen lässt. Das ist auch günstig für die
Form der Daten die als serieller Stream vorliegen.
So, zum Stand der Dinge. Es geht noch immer nicht :) .. aber ich konnte
einen weiteren Teil des Problems beheben. Einer der Pins am Latch oder
Ram hatte einen Wackelkontakt mit dem Federsockel (das nächste mal kaufe
ich keine Federsockel mehr). Aber auch das war nur ein Teil des
Problems. Im Moment arbeite ich mit folgendem Code:
// es handelt sich bei dieser ausgabe um falsche werte, aber sie haben system.
158
//ich habe das fuer verschiedene speicheradressen getestet. die werte sind immer die beiden low bytes der adressen.
159
160
// hterm gesamtausgabe: AA AA AA AA AA BB 03 04 FF 03 11 03 AA BB AA CD FF 0F BB 0F AA 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18
So, systemattische Fehler also. Es scheint so als wuerde der ram bei
jedem Schreib oder Lesezugriff geloescht. Es scheint mir so als haette
der ram Standartwerte eingestellt die jeweils der low bits der
entsprechenden Adresse entsprechen. Ich haette ja sonst vermutet das
anfaenglich alles auf 0x00 oder 0xFF oder undefiniert steht. Oder ich
habe den Pointerarray nicht verstanden und lese die Adresse aus die ich
angelegt habe. Es waere gut, wenn mir jemand sagen koennte, dass der
Code so wie er ausschaut prinzipiell funktionieren sollte - nach all den
Fehlern bin ich mir bei den Pointern und Arrays schon nicht mehr so
sicher.
in diesem post : Beitrag "Frage zu "sections" im ext. memory"
sah ich, das die Speicherausgabe von
Autor: OldBug (Gast)
Datum: 18.02.2005 00:02
(in der angehaengten Datei uart_log.txt das gleiche Schema enthaelt,
naemlich die low bits der Adressen als Werte an eben diesen Adressen.
Leider ist aus dem Code nich ersichtlich was "data" ist. Da es
inkrementiert wird könnte es auch sein, das in diesem Post diese
Korellation nicht besteht.
in diesem post :
http://www.embeddedrelated.com/groups/avrclub/show/521.php
beschreibt jemand das selbe Problem auf dem selben mC. Er sagte dann
später er habe es gelöst. Leider sagt er nicht genau wie. Die Fusebits
seien das Problem gewesen. Ich vermute er bezieht sich hier auf den 161
Kompatibilitätsmodus, welchen ich aber meiner Meinung nach schon
abgeschaltet habe.
Meine Fuse Bits: alles deaktiviert (1 / kein Häkchen im ponyprog) bis
auf BOOTSZ0=0 und BOOTSZ1=0 und SPIEN=0
Ich vermute im Moment weiterhin ein Hardwareproblem. Wenn lese oder
schreib Zugriffe den Inhalt des Rests des Rams loeschen, dann halte ich
die read,write oder ale Leitung für schuld. Ich konnte da aber bisher
nichts finden. Ist es sonst evtl. möglich, dass ich zu viele oder zu
wenige 100nF Kondensatoren angebracht habe (ich habe mal einen zwischen
jeden IC Vcc und Grd geschaltet um die Versorgung zu glaetten) und mir
die Spannung zwischen den schreib und lesezugriffen wegbricht? Das
sollte ja eigentlich nur beim Einschaltvorgang zu einem Zeitproblem
führen. Der Ram hält laut dokumentation die Daten bis 2V. Da würde wohl
eher der mC reseten und das würde ich ja am uart sehen. Die Spannung
nehme ich vom Pc Netzteil an den Festplattenstromsteckern (Rot,Schwarz)
ab. Das Netzteil sollte ja eigentlich dafür gebaut sein sehr stabile 5V
zu erzeugen.
Ich beschäftige mich nun schon sicher 20 Stunden mit dem Problem und bin
für jede Hilfe oder Anregung sehr dankbar!