Hallo zusammen!
Ich schreibe schon seit einiger Zeit an einem Projekt mit resistiv
touch, T6963 Grafik kontroller basierendem 240 x 128 pixel display
usw....
Als Controller verwende ich den ATmega128 mit Bootloader von MicroSyl.
Ich habe mittlerweile ein für meine Verhältnisse großes Menü aufgebaut
mit insgesammt 15 verschiedenen bmp's a 4096 Bytes groß. Diese lege ich
als Arrays im Flash ab und habe sie bisher immer mit der funktion
pgm_read_byte(); ausgelesen und byte für byte ans Grafikram vom LCD
übertragen. Seit mein code (mit den Arrays) die 299pages (?) grenze
erreicht hat kommt beim übersetzen die Fehlermeldung:
C:\*\Temp/ccWAaaaa.s: Assembler messages:
C:\*\Temp/ccWAaaaa.s:97691:
Error: value of 67785 too large for field of 2 bytes at 7852
C:\*\Temp/ccWAaaaa.s:138:
Error: value of 67785 too large for field of 2 bytes at 0
Als IDE verwende ich die neueste WinAVR Version.
Ich sehe zwar dass 67785 zu viel für eine integer variable ist (65535 =
0xffff) aber ich weiß nicht wo das passiert!
Kann es sein dass die funktion pgm_read_byte(); nur auf die Lower 64k
Flash ausgelegt ist oder gibts da andere bekannte Fehler die ich gemacht
haben könnte?.
Ich würde den Quelltext gerne schicken aber der ist fast noch nicht
kommentiert und der würde wahrschenlich nicht viel bringen!
Welchen externen Speicherbaustein (am liebsten IIC) würdet ihr mir für
die zukunft vorschlagen?
HAb zwar schon ein 24C64 I²C EEPROM zum Temperatur loggen dranhängen
aber bei 400KHz Max. Clock leidet der Datendurchsatz für "Bewegte
Bilder" ganz schön.
Danke schonmal im Vorraus,
MainSter
Ok, da hab ich wohl wieder zu wenig gelesen.... aber an der
Fehlermeldung vom compiler hats nichts geändert.
Wenn ich das 15. Array komplett aus meinem Code nehme kommt die
fehlermeldung nicht mehr.
Hab mir in die Arrays mal 'Strings' reinkopiert und mir des ganze in
Ponyprog mal angeguckt. Das 15. Array liegt an 0x0FFD0 bis 0x10FD0.
Dann müsste ich jetzt ein teil des Arrays mit pgm_read_byte() und den
anderen mit pgm_read_byte_var() auslesen oder gibt es eine möglichkeit
dem array zu sagen wo es liegen soll?
Danke für die schnelle Antwort!
MFG MainSter
@ johnny.m: Nein, war ein tippfehler im Forum!
@ Rolf Magnus: eben weil ich so wie ich mitgekriegt hab mit
pgm_read_byte() nicht aus den oberen 64k lesen kann oder nicht?
mfg Mainster
Ahh....
Danke. Dass kann man aus der libc doku nicht eindeutig herrauslesen,
oder?
Ich hab gelesen dass es effektiver ist die near version zu benuten!
Jetzt könnte ich doch meinen executable code in die ober 64k schreiben
und die bmp's in den unteren 64k ablegen?! Funktioniert es dann noch mit
dem pgm_read_byte_near() ?
Und, wie müsste ich dass genau machen? Muss ich da wirklich mit dem
RAMPZ bit rumspielen?
• Bit 0 – RAMPZ0: Extended RAM Page Z-pointer
The RAMPZ Register is normally used to select which 64K RAM Page is
accessed bythe Z-pointer. As the ATmega128 does not support more than
64K of SRAM memory,this register is used only to select which page in
the program memory is accessed whenthe ELPM/SPM instruction is used. The
different settings of the RAMPZ0 bit have the
following effects:
RAMPZ0 = 0: Program memory address $0000 - $7FFF (lower 64K bytes) is
accessed by ELPM/SPM
RAMPZ0 = 1: Program memory address $8000 - $FFFF (higher 64K bytes) is
accessed by ELPM/SPM
Note that LPM is not affected by the RAMPZ setting.
> Und, wie müsste ich dass genau machen? Muss ich da wirklich mit dem> RAMPZ bit rumspielen?
Wieso dieses? Das macht doch die entsprechende Funktion für Dich. Der
Unterschied zwischen den near- und far-Versionen ist im Prinzip
lediglich, dass die near-Versionen den lpm-Befehl verwenden (der mit
einer 16-Bit-Adresse arbeitet und dementsprechend nur bis 64 K
adressieren kann) und die far-Versionen den elpm-Befehl, der in
Zusammenarbeit mit dem RAMPZ-Register den Rest erledigen kann.
> und die bmp's in den unteren 64k ablegen?!
Genau das machen die normalen pgmspace-Routinen und -Makros. Da es
kein Problem ist, Code oberhalb 64 KiB anzusiedeln und auszuführen,
werden Daten (also "progmem") vorzugsweise vor den Code gelinkt
(Ausnahme: die Interruptvektortabelle und der Startupcode sind noch
davor).
Ahh, ok... So langsam wirds heller!
Also das sinnvollste wäre wie oben beschrieben die Arrays in die lower
64k zu linken. Das hab ich halt auch nochdie gemacht... Ich weiß dass
"linken" was mit dem Compiler und der makefile zutun hat...
Kann mir jemand ungefähr sagen was ich in mein makefile eintragen muss
dass der linker weiß das er die Arrays in die lowr 64k linkt?
Danke für die hilfe, MainSter
Naja... mit der makefile hab ich mich eigentlich noch nicht so wirklich
beschäftig. Ich hab halt mal eine Makefile mit Program das bei dem WIN
AVR paket dabei ist, mfile glaub ich, generiert.
Die Arrays wurden bis jetzt ja auch nicht in die oberen 64k geschrieben
aber seit mein code mit den Arrays größer 64k ist stehen eben alle neuen
arrays oberhalb 64k.
Wenn ich den Programm Code in den oderen bereich linke und den Daten
Code, eben die arrays, in den unteren bereich linke sollte es ja
funktionieren.
MFG MainSter
Was soll dieser ganze Zirkus jetzt eigentlich? Wenn die Daten grösser
sind als 64KB, dann passen sie nun einmal nicht in 64KB. Dann ist es
auch schnurzpiepegal ob sie unten oder oben im ROM liegen. Weil mal
ohnehin mit dem _far Funktionen ran mus. Und denen ist es egal wo die
Daten liegen.
MainSter wrote:
> Die Arrays wurden bis jetzt ja auch nicht in die oberen 64k> geschrieben aber seit mein code mit den Arrays größer 64k ist stehen> eben alle neuen arrays oberhalb 64k.
Darum frage ich dich ja, wie du das denn geschafft hast. Das ist
nicht der Normalfall: alle "progmem"-Objekte werden im
Standardlayout vor dem Code gelinkt.
1
$ cat foo.c
2
#include <avr/pgmspace.h>
3
4
uint8_t foo[] PROGMEM = {
5
42, 21, 213, 123
6
};
7
8
uint8_t bar[] PROGMEM = "Hello, cruel world!";
9
10
int
11
main(void)
12
{
13
int i;
14
15
i = pgm_read_byte(&foo[0]) + pgm_read_word(&bar[1]);
16
17
return i;
18
}
19
$ avr-gcc -Os -mmcu=atmega128 -o foo.elf foo.c
20
$ avr-nm -n foo.elf
21
...
22
00000000 T __vectors
23
...
24
0000008c T foo
25
00000090 T bar
26
000000a4 T __ctors_end
27
000000a4 T __ctors_start
28
000000a4 T __dtors_end
29
000000a4 T __dtors_start
30
000000a4 W __init
31
000000a4 T __trampolines_end
32
000000a4 T __trampolines_start
33
000000b0 T __do_copy_data
34
000000ca T __do_clear_bss
35
000000d2 t .do_clear_bss_loop
36
000000d4 t .do_clear_bss_start
37
000000de T __bad_interrupt
38
000000de W __vector_1
39
...
40
000000de W __vector_9
41
000000e2 T main
42
000000f8 A __data_load_end
43
000000f8 A __data_load_start
44
000000f8 T _etext
45
...
(Ich habe mal alle nicht mit dem ROM in Zusammenhang stehenden
Symbole rausgestrichen.)
Es ist deutlich zu sehen, dass die beiden ROM-Arrays foo und bar sogar
noch vor dem Initialisierungscode platziert werden.
Danke für die Hilfe....
@Jörg Wunsch: Sehr schönes Beispiel. Jetzt weiß ich wie es sein sollte!
Bei mir wird auf jeden fall nicht nach Standart gelinkt!
Aber ich glaub ich muss mir da noch einiges durchlesen.
Kann mir jemand ein einfaches Makefile schicken mitdem die programmteile
nach dem Standardlayout gelinkt werden?
Und/oder kann mir jemand ne doku zu Makefiles empfehlen? Ich wollte mich
schon länger mal mit dem thema auseinandersetzen.
Vielen Dank, MainSter
Hallo!
Hab jetzt nochmal ein Standart Makefile mit Mfile generiert. Wenn ich
mir die lst file anschaue wird alles so gelinkt wie es soll (das andere
Makefile wahr wohl nichtmehr standart). Alle Arrays werden vor den
Quellcode und nach die INT Vectoren gelinkt. mein 16. Array liegt jetzt
wie gesagt genau auf der Grenze von 64k zu 128k. Dieses Array kann ich
jetzt mit pgm_read_byte_far(); erreichen, oder??
Was kann man für fehler machen da ich mein 16. Array mit meiner far
funktion nicht auslesen kann.
--> Die anderen Arrays (< 64k) können mit der selben funktion
einwandfrei ausgelesen werden.
Muss man die Pointervariable vergrößern? In der LIBC doku steht nähmlich
auch bei der funktion pgm_read_byte_far(); dass der Arrayname (Addresse)
ein char (8Bit) ist.
MFG MainSter
pgm_read_byte_far() sollte allerdings in der Tat funktionieren, da
es explizit das RAMPZ-Register setzt. Was passiert denn genau?
Die Adresse ist übrigens nicht 8 bits, sondern 32. Du verwechselst
die Größe der Adresse mit der Größe des Objekts, auf die die Adresse
verweist.
wie hast du es geschaft dass er es dir überhaupt auf/über die grenze
ablegt hat?
ich gehe mal davon aus dass deines ein zusammenhängendes array ist.
bei mir meckerte der compiler rum, dass ihm das array "nicht mehr
erreichtbar scheint" und er es deswegen nicht abgelegt hat ('attribut'
PROGMEM):
Error: value of 73728 too large for field of 2 bytes at 1736
hatte also erstmal nichts mit dem lesen zutun. im makefile habe ich auch
gewühlt, war jedoch schnell ernüchtert...
pumpkin
Aha!
@Jörg Wunsch: Hast recht, habs verwechselt!
Diese Fehlermeldung kommt bei mir wenn ich ein 17es 4k Array mit in
meinen Code aufnehme!
Error: value of 73728 too large for field of 2 bytes at 1736
Ich kann nicht genau sagen was passiert! Ich lade in einer Function byte
für byte aus dem Array und übertrage diese ins Grafik Ram bis 4096 bytes
gelesen wurden.
Für das array >64k habe ich die selbe Function nur anstatt
pgm_read_byte_near() benutze ich pgm_read_byte_far();
Im display werden die ersten zwei byte weiß (die ersten 16 Punkte) und
der rest bleibt schwarz.
Die Adresse ist aber nur bei der far() version 32Bit und bei der near()
version 16Bit, oder? Sonst würde es ja fast keinen Sinn machen.
Könnte es auch daran liegen? Weil ich müsste die Variable für den Zeiger
ja auch 32Bit groß machen....
Sorry für die NOP fragen aber ich bin grade zimlich verunsichert!
Danke, MainSter
>> 73728 passt auch nicht in 2 Bytes (16 Bit). Da hat der Compiler vollig>> Recht. Das hört bei 65535 auf. Mehr besagt die Fehlermeldung nicht.
hat er ja auch, aber was soll der blödsinn? dann soll er halt 32bit
adressen nehmen, habe ich doch keinen einfluss drauf. also wie löst man
das problem? bisher konnte ich keine lösung finden...
pumpkin
nachtrag:
was ich meine ist, dass es schön und gut ist dass es _far zugriffe gibt,
aber sie nichts nützen wenn ich nichts explizit dort ablegen kann.
können bestimmt, aber wie...
pumpkin
> können bestimmt, aber wie...
Explizite Zuordnung der Variablen zu Sektionen, die man per
Linker-Script an die gewünschten Stelle im Speicher plaziert.
Findet sich alles in Doku von GCC (Zuordnung zu Sektionen) und LD
(Anordnung der Sektionen im Speicher per Linker-Script). Bei AVRs
normalerweise nicht nötig, aber bei ARMs kommt man mit sowas öfter in
Kontakt.
Du kannst auf alle pgmspace-Daten per _far-Funktionen zugreifen. Du
kannst soviele Daten ins Flash packen, wie dort überhaupt reinpasst.
Wenn du jedoch partout zwischen den Daten in den ersten 64KB und dem
Rest unterschieden willst, dann laste das bitte weder Compiler noch
Library an.
> dann soll er halt 32bit adressen nehmen, habe> ich doch keinen einfluss drauf.
Ob eine Variable mit 16 Bits adressierbar ist, weiss der Compiler nicht.
Kann also auch nicht abhängig davon unterschiedlichen Code erzeugen.
Erst der Linker kriegt das spitz, dann aber ist es dafür zu spät.
Und so erzeugt der Compiler immer dann 16bit-Adressverarbeitung, wenn es
man ihm nicht ausdrücklich anders mitteilt. Weil das in 99% der Fälle
sinnvoll ist, alles andere wäre grober Unfug und würde den Code massiv
aufblähen.
In deinem Fall merkt der Linker, dass die Adresse einer Variable nicht
in das nur 16 Bits grosse Adressfeld eines Befehles oder einer
Adressvariablen passt und meckert entsprechend.
Niemand hindert dich daran, mit geschickt plazierten 32bit Datentypen,
den Compiler dazu zu überreden, für Adressen 32 Bits vorzusehen. Und
sieh an, auf einmal geht es.
>> Niemand hindert dich daran, mit geschickt plazierten 32bit Datentypen,>> den Compiler dazu zu überreden, für Adressen 32 Bits vorzusehen. Und>> sieh an, auf einmal geht es.
find ich gut!
pumpkin
Hallo,
Bin mir immernoch unsicher wegen dem Pointer....
const uchar *array1_ptr PROGMEM = array1;
const uchar *array2_ptr ................
So hab ich bis jetzt allen Arrays einen Pointer zugewiesen.
Ich hatte das mal aus einem anderen Code abgeschrieben und es
funktioniert auch... Bis jetzt....
MFG MainSter
hallo Robert,
ich mache grade eine Ausbildung asl elektroniker für geräte und systeme.
In meiner Berufschulklasse hab ich einen kollegen der bei einer Firma
arbeitet wo sie Industrie PC s herstellen. Da kann der hin und wieder
mal ne scheibe abgreifen....
Ich hab noch eine 15" resistiv scheibe in einem ca. 3-4 cm breiten
rahmen... Die könnt ich für nen zehner inclusive versand entbehren....
Sind sogar noch 4 folientaster drauf....
Die Ansteuerung ist mehr als einfach (wenn der verwendete µC nen
intergrierten AD wandler hat)
MFG Mainster
Hi MainSter
Das ist ein Deal :)
Bitte meld dich unter robert.schilling@gmx.at. Bitte beachte wegen den
Versandkosten, dass ich aus Österreich komme.
Bitte schick mir dann deine Kontodaten, um da Geld überweisen zu können
(bitte mit IBAN und BIC).
Zum Schaltplan, den werd ich später noch online stellen. (Muss erst
einen Screenshot machen...)
mfg Robert
Hallo,
Das display hab ich auch von dem kumpel der mir die folien besorgt hat!
Die Grafik lib hab ich auch mal irgendwo im netz gefunden.... Es waren
die grundfunktionen (init, bytes ins grafik & textram ablegen)
implementiert. Mittlerweile hab ich aber sehr viel funktionen
implmentiert hauptsächlich fürs grafikram. Z.B. Bytes und pixel lesen
(zum Invertieren der per touch gedrückten buttons) Ist allerdings noch
fast alles für die Port version (nicht memmory mapped)
Wenn ich das mal umgeschrieben und kommentiert hab werd ich die Lib auch
online stellen....
Danke für den schaltplan....
Ich meld mich bis spätestens dienstag wegen dem Touch.
MFG MainSter
hallo robert,
könntest du mir noch sagen was das unten rechts in der ecke für 2
Bauteile sind (das eine is n OPAxx) aber die beiden drüber mit 14 und 8
Pins sind selbsgemachte symbole, oder?
MFG MainSter
...und dann wäre da noch die Funktion von PD7 & PD6 an SV1
(LCD connector?)
Einer davon wird der C/D Pin sein und der andere wahrscheinlich
/Disp_OFF.
Die eine Leitung die von dem unbeschrifteten 8pin bauteil (irgendwas
richtung Resetbaustein ?) weggeht wird am /reset vom T6963 angeschlossen
sein, oder??
So wie ich deine Schaltung verstehe verwendest du zur Addressierung des
Grafik - RAMs Adressen wo die obersten vier addr. pins (A15...A12) high
sind.
Und bei dem 128k sram? es wird ja nur als 64k sram verwendet. Die CS
pins von dem sram sind aber nur dann aktiv wenn eine der obersten 4
Addr. bits low ist, oder? Dann kannst du ja da auch wieder nicht die
vollen 64k verwenden, oder?
Hab noch nie was mit dem Addr. Bus gemacht außer jetzt mit dem T6963!
darum die vielen fragen!
Danke, MainSter
Ich hab grad noch gesehen dass du nen JTAG connector auf deinem board
hast...
Verwendeset du diesen zufällig als debugger schnittstelle?
Wenn ja, hast du dir die debugger-hardware auch selber gebastelt oder
verwendest du was gekauftes??
Danke, MainSter
Hallo MainSter
Der OPA547 ist ein Leistungs OP. DEn hab ich zum steuern der Helligkeit
der Hintergrundbeleuchtung. Das schnell erzeugte Eigenbauteil ist ein
MC34063 und dient zur Erzeugung der negativen Kontrastspannung. Sowohl
die Kontrastspannung, als auch die Hintergrundbeleuchtung wird über ein
Digtales Poti (MCP42010) gesteuert. DIe Leitung die vo 8 PIn IC weg
geht, ist die negative Kontrastspannung.
Zum Ram. Mit dem Mega128 kann an maximal 64kB Ram ansteuern (mit dem
XMEM Interface) ohn irgendwelche Zusatzlogik... Die Unteren 56kB Ram die
adressiert werden, sind für den SRAM reserviert. (NAND GAtter aktiviert
die CS Pins des SRAM). Sobald man über 56kB adressiert, sind die oberen
4 Bits der Adresse HIGH und das NAND GAtter akiviert den CS Pin des
Displays. C/D ist an A0 angschlosssen. Somit sind bei allesn geraden
Adressen A0 auf LOW, sprich es ist ein Datenbyte. Bei einer ungeraden
Adresse über 56kB wird es zu einem Kommandobyte.
Als JTAG Debugger verwende ich einen selbstgebautes Evertool --> GOOGLE.
Vereint ISP und JTAG.
Wenn noch Fragen offen sind, einfach Fragen.
mfg Robert
Hallo Robert,
danke für die Erklärung. DAs mit den 56k ist mir gestern Nacht auch noch
gekommen! Die sache mit der
geraden Addr > 56k = Datenbyte fürs Display und
ungerade Addr > 56k = Befehlsbyte fürs display ist sehr schön gelöst!
Hast du dein Projekt auch mit 16MHz am Laufen???
Wenn ja, brauchst du auch einen Wait State bei datenübertragungen zum
Grafik Ram???
MFG, MainSter
Hi MainSter,
Danke ;)
Am LAufen hab ich noch gar nicgts, da die PLatine erst geätzt werden
muss. Als Quarz hab ich einen 18.irgendwas gedacht. (Es kommen sehr
viele Daten per Uart). Dann aber 2 Wait States...
Läuft deiner mit 16MHz?
Gruß Robert
läuft mit einem wait state wunderbar. Wenn ich ihn ohne Waits laufen
lass hab ich nach ca. 5 sekunden übertragungsfehler.
Zum testen lass ich eine bmp 50x50pixel auf dem Bildschirm umherkreisen.
Nach dieser zeit werden manche datenpakete die fürs GRafik - ram gedacht
waren durch die übertragungsfehler ins Textram geschrieben.....
Mit einem wait gehts aber echt klasse! Man kommt ohne probleme auf
einige Frames / sekunde..... genaueres werd ich nacher mal austesten!!!
MFG MainSter
Hallo Robert,
sorry dass ich so lange auf mich warten lassen hab!! Ich muss dir leider
mitteilen dass das Panel nicht mehr funktionsfähig ist. Ich habe es
dummer weise auf dem "Plastik- Anschluss" gelagert und mit der zeit ist
da wohl ein kontakt gebrochen..... Wenn man ein bischen dran rumdrückt
dann funktionierts wieder....
Ist aber nicht wirklich toll... Ich hab auf den kollege gewartet weil er
gemeint hat, dass er vll. nochmal eins Abstauben kann aber so wies
aussieht dauert es noch..... Ich würde sagen dass ich dir dein geld
zurücküberweise... Ich versprech dir dass du der erste bist der ne email
kriegt falls es nochmal klappen sollte dass der kollege welche
organisiert kriegt.
Denk an BIC usw....
Sorry nochmal,
MainSter
Hallo MainSter
Das ist natürlich ncht gut. In welchem Zeitraum denkst du du, wirst du
das nächste Touchpanel bekommen??
Kannst du mir bitte deine Mail nochmal schicken??
mfg Robert
Hallo Robert!
Es tut mir leid dass ich so lange nichts von mir hören lassen hab aber
ich hab auf ne E-mail gewartet....
Meine Mail: ManuelDelBasso@web.de