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
Probier's doch mal mit pgm_read_byte_far().
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
> Dann müsste ich jetzt ein teil des Arrays mit pgm_read_byte() und den > anderen mit pgm_read_byte_var() auslesen Warum?
> pgm_read_byte_var()
Wenn Du das im Programm auch so geschrieben hast, dann ist es klar, dass
Du ne Fehlermeldung bekommst...
@ 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
Was Rolf wohl meint: Man kann mit den far-Versionen auch aus den unteren 64KB lesen.
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
Wie stellst du es denn an, dass er sie in den Bereich oberhalb 64 KiB lädt?
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
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.
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
das mit den 32bit pointern würde mich interessieren wie man das macht. so'n bissl beispielcode wäre phänomenal. pumpkin
Hi MainSter Woher hast denn du deine Touch Folie?? Oder war die schon am Display oben? Gruß Robert
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
Hier nun der Schaltplan. Hast du deine T6963 Routinen selbst geschrieben? 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
Hi Das Geld müsste heute angekommen sein (Ich hab das ganze am Montag Abend überwiesen). mfg Robert
Hallo MainSter Hast du das Touch Panel schon verschickt? mfg Robert
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
Hi Kannst du mir bitte deine EMail Adresse nochmals 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
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.