Hallo, ich habe mein erstes Projekt mit dem AVR32 fertiggetellt, und es läuft. Für mein nächstes Projekt ist es von Vorteil, wenn ich einzelne Programme von einem externen Speichermedium in den RAM laden und von dort ausführen könnte. Und jetzt weiß ich nicht weiter. Mir geistern da Fragen durch den Kopf, ich finde nur keine Antworten bei google: Das Programm muss so kompiliert sein, dass nur relative Sprünge benutzt werden. Wie sage ich das dem Compiler? Hat das etwas mit den 'shared Lib' bzw. 'static Lib'-Optionen in den Build-Einstellungen zu tun? Gibt es irgenwo ein Tutorial dafür? Beste Grüße aus Dreiecken!
Beim AVR kannst du keine Programme im RAM ausführen. Du kannst höchstens über einen Bootloader ein neues Programm in das Flash laden.
Hat den nichtmal jemand einen Hinweis, wo ich suchen kann? Google spuckt wirklich garnichts aus, oder ich habe die falschen Schlagwörter. Hier im Forum schrieb mal jemand einen Gameboyemulator, der die Programme aus dem RAM aufrief, wie hat er das den gemacht???
> Das Programm muss so kompiliert sein, dass nur relative Sprünge > benutzt werden. Noe. Dein Programm muss fuer die Zieladresse fuer die es laufen soll compiliert werden. > Wie sage ich das dem Compiler? Und das sagst dann nicht dem Compiler sondern dem Linker. Der Linker wiederum wird ueber Linkerscripts konfiguriert. Und dafuer gibt es ganz sicher tolle Anleitungen irgendwo. :) Nur wenn dein Programm an beliebigen Speicheradressen lauffaehig sein soll dann darf es entweder nur relativ sein, oder es enthaelt eine Tabelle mit den Sprungbefehlen die dein Ladeprogramm beim laden anpasst. Und wenn du es geladen hast, dann springst du einfach da hin: void *start_adress; start_adress=(void*)0x12345678; ((void (*)(void)) start_adress)(); Vorher vielleicht noch die IRQs abschalten. .-) Olaf
Dreieck schrieb: > Hier im Forum schrieb mal jemand einen Gameboyemulator, der die > Programme aus dem RAM aufrief, wie hat er das den gemacht??? Ich denke nicht, dass in einem Gameboy ein AVR32 drinnen ist. D.h. sein Emulator hat den kompletten Gameboy emuliert, inklusive CPU
>>Ich denke nicht, dass in einem Gameboy ein AVR32 drinnen ist. Hat er auch nicht, im Gameboy I war ein modifizierter Z80 drin. >>D.h. sein Emulator hat den kompletten Gameboy emuliert, inklusive CPU Ja, das ist ein Emulator dort, trotzdem führte der Author Programme aus dem RAM des AVR32 aus, um den langsameren Flash zu umgehen. Und das ist alles was mich interessiert: Wie erstelle ich ein AVR32-Programm, dass ich nachher aus dem RAM ausführen kann und wie kann ich es 'laden'.
Dreieck schrieb: > Wie erstelle ich ein AVR32-Programm, dass ich nachher aus dem RAM > ausführen kann Es unterscheidet sich von einem Programm im Flash ja nur dadurch, dass es auf Ram-Adressen gelinkt ist. Es kann auch position-independent sein (siehe GCC-Manual, -fpic), aber das ist fürs Laufen im Ram nicht grundlegend notwendig. > und wie kann ich es 'laden'. Irgendwie muss das Programm ins Ram kommen, ja. Das ist nun wirklich Deine Aufgabe (z.B. Loader im Flash), oder Du beauftragst ein Betriebssystem damit. Für einen recht umfangreichen Loader google mal nach „uboot“. Den sollte es auch für AVR32 geben und der ist nicht nur zum Booten von Betriebssystemen gut. Edit: Link zu uboot-Dokumentation: http://www.denx.de/wiki/U-Boot
Hc Zimmerer schrieb: > Für einen recht umfangreichen Loader google mal nach „uboot“. Den > sollte es auch für AVR32 geben und der ist nicht nur zum Booten von > Betriebssystemen gut. Für einen AP mag das richtig sein, für den UC3 find ich das nicht so toll. Kannst ja mal hier schauen: http://avr32linux.org/twiki/bin/view/Main/UBootOnUC3
Ich finde zwar keinen Hinweis auf einen UC3 beim TE, aber wenn er einen verwendet, ist der Hinweis sicher nützlich.
Bingo! Habe ich vergessen anzugeben. Es ist ein UC3A1. Wenn ich das gcc-Manual richtig verstehe, brauche ich nichts anderes zu tun, als die Projekte mit -fpic zu erstellen, mir aus der elf-Datei das Codesegment rauszuholen, das dem Hauptprogramm zu übergeben, das es in den RAM läd und das Segment aufruft. Es geht mir zuerst nur um einfache Programme (keine Interrupts), wie Blinken aus dem RAM. Danke für die Hilfestellungen!
Kann jemand meine Annahme betätigen, bzw. sagen was daran falsch ist?
Hi, Also bei dem Gameboy emulator ist das viel einfacher, da der Code interpretiert wird. Ich lade also einfach das Programm von einem speicher medium(SD karte) in ein Simples array(spezielle Speicheradresse). Dann interpretiere ich byte für byte. Ist also kein Richtiges ausführen ;), trozdem ist das Prinzip ähnlich. Also um Code auszuführen, muss du erstmal einen Loader schreiben der eine Compelierte Datei(die *.elf kann man zu einer *.bin umwandeln) in einen Speziellen Speicherbereich läd. z.b. 0xC0000000. Und dann muss du nur noch deinen PC und SP auf die Adresse stellen, vll auch noch alle Register löschen etc. Den Linker vom Compiler musst du jetzt noch einstellen/umschreiben, so das dein Code ab der Adresse 0xC0000000 anfangen soll. Bei dem AP7000 muss man den Linker nicht umstellen dank MMU ;). Gruß Zippi
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=95689 Hier wird beschrieben wie es geht.
Ich denke, Dreieck braucht relokierbare Programme, weil er mehr als ein Programm ins RAM laden, bez. ausführen will. Ein Programm liesse sich ja schlicht auf die Startadresse des RAM linken.
>Hier wird beschrieben wie es geht. Vielen Dank, das habe ich irgenwie nicht gefunden... >Ich denke, Dreieck braucht relokierbare Programme, weil er mehr als >ein Programm ins RAM laden, bez. ausführen will. Ein Programm liesse >sich ja schlicht auf die Startadresse des RAM linken. Das soll der nächste Schritt sein, wenn du mir aber jetzt schon sagen kannst wie das geht, wäre das wirklich Klasse. >Also um Code auszuführen, muss du erstmal einen Loader schreiben der >eine Compelierte Datei(die *.elf kann man zu einer *.bin umwandeln) in >einen Speziellen Speicherbereich läd. z.b. 0xC0000000. Da sehe ich kein Problem drin, ich reserviere mit malloc Speicher, lade meinen Code dahinein und springe die Adresse wie eine Funktion an (ich progge in C). malloc hat für dynamische arrays gut auf dem AT32UC3A1512 funktioniert. >Den Linker vom Compiler musst du jetzt noch einstellen/umschreiben, so >das dein Code ab der Adresse 0xC0000000 anfangen soll. Das und der letzte Beitrag unter dem Link von 'sma' verwirrt mich. Der gcc kann doch positionsunabhängigen Code erzeugen (mit '-fpic'), warum kann ich nicht ein Programm an eine beliebige Stelle im RAM zu laden? Die 'Programme' auf die ich ziele sollen alle sehr einfacher Natur sein und nicht mehr tun, als Protokollübersetzungen machen. Sie müssen nur die Peripherie bedienen, das reicht mir schon. (Leicht verwirrte) Grüße Dreieck
Beitrag "Harvard vs. Von Neumann" da avr in Havard aufgebaut sind kannst nur einen Interpreter ins Flasch brennen welcher dann auf Ram oder eeprom zugreift um, tokenisierte programme zu interpretieren ala homecomputer zx81/64, c64, atari oder KC85 hier hat schon mal jemand soe eine mashine vorgestellt. genau genommen must du ein OS und einen Interpreter erstellen.
>da avr in Havard aufgebaut Nein, der AVR32 (32-Bit) ist kein Harvard-Controller, sonst wäre eine Ausführung von einer festen RAM-Adresse auch nicht möglich. Trotzdem Danke!
@Winfried Das was du meinst betrifft die AVR prozessoren aber nicht die AVR32. Dort kann man programme auf dem SRAM ausführen. @Dreieck positionsunabhängigen Code? Also, wenn dann hast du ne loader tabelle, wo du damm beim Laden des Programms jeden sprung mit dem Speicheroffset addieren musst. Sonst geht bei programm z.b. bei einem Schleifen-rücksprung, funktionsausruf etc kaputt. Schau die mal die standard Linkerscripts an. C:\Programme\Atmel\AVR Tools\AVR32 Toolchain\avr32\lib\ldscripts Die kannst du einfach ändern(Ein Backup der alten wäre dann sinnvoll). Ich würde erstmal die Flash adresse von 0x80000000 auf deine RAM adresse stellen interner SRAM liegt bei 0x00000000. Gruß Zippi
Oh ich spiele schon über 2 Jahre mit dem Atmega32. Habe ich das die ganze Zeit übersehen oder von welchem 32er redet ihr. O.K. vorher benutzte ich den 128er Atmega, aber auch den nur in havard. Jetzt werde ich auch neugierig. Klärt mich bitte auf. dunklel war mir was beim 8515? mit externem sram in erinnerung geht das auch beim 32er? das wäre hoch interressant man könnte über /CE den Sram selektieren und das programm mit festen adressen anspringen
Ich glaub ich hab zulange nicht in die konkreten datasheet geschaut. Mist dachte kennste einen großen kennste Alle denkste Puppe
>Also, wenn dann hast du ne loader tabelle, >wo du damm beim Laden des Programms jeden sprung mit dem Speicheroffset >addieren musst. >Sonst geht bei programm z.b. bei einem Schleifen-rücksprung, >funktionsausruf etc kaputt. Ich kenne mich nicht mit dem Assembler des AVR32 aus, weil ich seit Jahren nur noch C nehmen, bei den (alten) Pics waren Sprünge in Schleifen und Funktionen immer relativ. Ist das hier anderes? Rücksprünge aus Funktionen sollten doch gehen, weil die Rücksprungadresse auf dem Stack liegt? Für einen 8-Bit-AVR habe ich mal ein ein Programm geschrieben, wo (zur Laufzeit) Stacks von Datenpaketen angelegt wurden und für jedes angekommende/abgehende Paket eine Funktion aufgerufen wurde. Die Funktionen lagen natürlich alle im Flash, die Adressen der Funktionen wurden den Paketen aber dynamisch zugeordente, so dass z.B. durch 'Packet[i].Rxfunction()' in der Empfangsroutine immer die richtige Funktion angesprungen wurde. Ich will nicht klugscheißen, aber irgendwie verstehe ich es nicht...
http://www.mikrocontroller.net/articles/AVR32 alles klar sorry da bin ich bisher glatt vorbeigerannt.
>Sprünge in Schleifen und Funktionen immer relativ. Ist das hier anderes? Also vom ASM code her, ist beides möglich. Kann sein das der AVR32 das alles ralativ macht. >Rücksprünge aus Funktionen sollten doch gehen, weil die >Rücksprungadresse auf dem Stack liegt? Jop das sollte auch gehen. Hast du denn schonmal ausprobiert ein programm in den Ram zu laden, und ihn dann auszuführen? @Winfried Ja leider verwechseln vielde den ATmega32 mit dem AVR32 ;). Gruß Zippi
>Schau die mal die standard Linkerscripts an. >C:\Programme\Atmel\AVR Tools\AVR32 Toolchain\avr32\lib\ldscripts >Die kannst du einfach ändern(Ein Backup der alten wäre dann sinnvoll). Nix ändern, kopieren - dann ändern und ins Projekt einbinden.
>Hast du denn schonmal ausprobiert ein programm in den Ram zu laden, und >ihn dann auszuführen? Bisher nicht, die Platine ist hierfür ist überfällig. Ich werde morgen die Hardware eines anderen Projektes zweckentfremden und das einfach mal probieren. In den Studio-Einstellungen gibt es die Möglichkeit positionsunabhängige Programme erstellen zu lassen: Project->Properties->C/C++ Build->Settings->AVR32 GNU C Compiler->Optimization->Generate position independent code das gleiche gibt es nochmal unter AVR32 GNU Linker->Optimization Nur wie man .bin-Dateien erstellt habe ich noch nicht rausgefunden, weißt du das?
die habe ich ganz am Anfang meiener Attinyversuche bein AVR Studio nach einem Simulatorlauf einfach aus dem Projektordner gefischt und dann ins flash geladen. vielleicht geht das ja beim AVR32 Stuio auch noch.
Wenn ein Intel Hexfile vorliegt lässt es sich auch daraus generieren. z.b. http://www.keil.com/download/docs/7.asp damit ;-)
HI, >>Schau die mal die standard Linkerscripts an. >>C:\Programme\Atmel\AVR Tools\AVR32 Toolchain\avr32\lib\ldscripts >>Die kannst du einfach ändern(Ein Backup der alten wäre dann sinnvoll). >Nix ändern, kopieren - dann ändern und ins Projekt einbinden. Ja kannst du auch machen. Habe bei mir so die flash adresse auf 0x80002000 gesetzt, damit ich mir das trampoline sparen kann. Geht auch wunderbar ;). @Dreieck Probier das mal aus mit Generate position independent code. Das würde mich schon interessieren. Hier im Anhang ein CMD file. Einfach in den gleichen Ordner kopieren wo deine *.elf ist. Dann das CMD file bearbeiten (input.elf) ändern und ausführen. Gruß Zippi
Ich meine damit, wie man direkt .bin-Dateien erstellt, ohne konvertierung über Konsole...
Danke euch!
>Wenn ein Intel Hexfile vorliegt...
leider nicht, die einzige Option für executabels ist '.elf'.
Sogar der Simulator verwendet die .elf-Dateien.
Bisher kann ich nur sagen, dass sich mein größtes (altes) Projekt (text:
124KB) problemlos erstellen lässt. Die Option -fpic wird dabei
verwendet, sie taucht mehrmals in den Meldungen in der Console auf. Die
Umwandlung in
.bin funktioniert auch gut. Jetzt fehlt nur noch der Hardwaretest.
Ich hoffe, dass ich den morgen hinkriege...
(Die .bin kann ich doch einfach direkt in den Speicher laden, oder ist
da was zu beachten?)
Gruß
Dreieck
>Sogar der Simulator verwendet die .elf-Dateien.
Sorry, meinte Debugger, der Simulator hat bei mir nie funktioniert...
Ja di +.bin kannst du jetzt einfach laden. Also das erste byte ist schon programmcode. Werde es vll auch mal mit meinem Board testen. gruß Zippi
So da bin ich wieder... folgender Status: Das zu ladende Programm (ohne Init der Ports, das macht das Ladeprogramm): [c] #include <avr32/io.h> #include "gpio.h" void main(void) { unsigned long int i; unsigned int k = 13; gpio_clr_gpio_pin(AVR32_PIN_PB23); while (k--) { for (i = 0; i<200000; i++) { gpio_tgl_gpio_pin(AVR32_PIN_PB22); }; gpio_tgl_gpio_pin(AVR32_PIN_PB21); } gpio_set_gpio_pin(AVR32_PIN_PB23); } [\c] Erstellt mit mit 'Position independent code', 'use assembler for pseudo instructions', 'force double word aligment' und den Linkereinstellungen nur 'Garbage collect unused section' und 'Position independent code'. Und der Ladeteil erstellt mit normalen Einstellungen (nicht positionsunabhängig) : [c] typedef void (*USER_FUNC)(void); ... USER_FUNC Fktpointer; size_t size; nav_reset(); nav_drive_set(0); nav_partition_mount(); int file; file = open("output.bin",O_RDONLY); size = fsaccess_file_get_size(file); sprintf(message,"Lese %ld der Datei ein...\n",size); usart_write_line(&AVR32_USART3,message); Fktpointer = malloc(size); size = read(file,Fktpointer,size); close(file); sprintf(message,"Laden der %ld Bytes abgeschlossen...Starte...\n",size); usart_write_line(&AVR32_USART3,message); (*Fktpointer)(); // <--bis hier alles problemlos usart_write_line(&AVR32_USART3,"Rücksprung erfolgreich!\n"); [\c] Bis zu 'Fktpointer()' ging alles gut (Bild 1). Dann ein Druck auf F5 (Einzelschritt) im Disassemblerfenster führte zum Funktionsaufruf (icall), ein weiterer führt zu Bild 2. Der nächste Schritt führt allerdings nicht an die Stelle 0xcd5c, sondern an 0x8000002d (Bild 3). Nun stehe ich im Wald...wieso springt der Prozessor an (fast) den Flashanfang? Laut http://www.atmel.com/dyn/resources/prod_documents/doc32000.pdf Seite 190 ist lddpc ein (relativer) Ladebefehl, der Pozessor sollte doch an Adresse 0x0000c554 springen? Hat es bei dir funktioniert?
Hi, Ich hab es noch nicht probiert. Sitze grad noch an dem Schaltplan von meinem neuen AVR32 projekt. Wieso der nach 0x8000002d springt weiß ich aber auch nicht. LDDPC ist ja ein 16bit opcode. kannst du mal mit hexeditor schauen wie der genau aussieht? Steht da 0xcd5c drin? Die Operation sieht ja so aus: Operation: I. Rd ← *( (PC && 0xFFFF_FFFC) + (ZE(disp7) << 2)); Syntax: I. lddpc Rd, PC[disp] Operands: I. d ∈ {0, 1, …, 15} disp ∈ {0, 4, …, 508} Ich frag mich nur wofür das ZE steht. Gruß Zippi
Nicht wirklich, ich verwende nun eine etwas andere Blinkroutine. Ich habe rausgefunden, die ersten Befehle eine Art Startupcode sind. Sobald ich aber in den Projektoptionen die Verwendung von Startup verbiete, blibt die .elf leer, keine Ahnung wieso. Ich komme trotzdem an den Code (ohne Startup), indem ich den Konvertierungsbefehl in deiner .bat-Datei auf die .o-Datei anwende. Solange die Sprünge im Code immer relativ sind, sollte das mit der .o-Datei auch funktioneren. Ich habe dann den Assembler Code im Debugger durchgestept. Fakt ist, dass der Loader richtig arbeitet und das Programm richtig im RAM landet (habe die Blink.o mit dem, was nach dem Aufruf des Funktionszeigers im Assemblerfenster stand verglichen, war exakt gleich). Dann bin ich durch das geladene Programm gestept. Bei dem Befehl 'mcall r6[0]' springt das Ding in eine Exceptionbehandlungsroutine und fährt sich dort fest. Komisch ist, dass r6 eine Adresse (im RAM) enthält, die Sinn macht. Wenn der AVR32 diese Adresse anspringen würde, würde wahrscheinlich alles laufen. Der AVR32 scheint bei der neuen und bei der alten Blinkroutine das gleiche Problem zu haben: Sobald ein xcall-Befehl mit einer RAM-Adresse aufgerufen wird, landet das Ding im Nirvana. Weißt du warum? Gruß Dreieck
Hi, Aso ich bin noch nicht weiter. Aber mir ist noch eingefallen, das der ram bereich und der flash bereicht auseinander liegen. Selbst beim Aktivieren Generate position independent code funktion, könnte das Probleme machen. Kannst du mal das *.bin file und das Disasm. Hochladen von dem Programm was du aus dem RAM startest. Gruß
Hier ist die .bin-Datei, als disassemble kann ich nur die .o-Datei
anbieten...
>...das der ram bereich und der flash bereicht auseinander liegen
Warum soll das Probleme geben, solange es sich um relative Sprünge
handelt?
Ich frage mich, wie dass der u-boot-Loader macht...der muss ja auch mit
dem
gcc oder in Assembler erstellt worden sein.
Hi, Ich weiß net ob du noch zwischendruch mal hier rein schaust ;). Bist du schon dazu gekommen das es funktioniert? Also programme aus festen Speicherposistionen(durch Linker eingestellt) Kann ich komplett aus dem RAM ausfürhen. -fpic code geht aber leider bei mit auch noch nicht. Vll gibt es jetzt auch ein paar andere die sich damit beschäftigt haben. Gruß Zippi
Hallo, da ich die gleiche Frage hatte: hier noch mal ein Link: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=95689 Hat sich sonst noch jemand mit der Thematik beschäftigt?
Hi, beschäftige mich gerade auch mit dem Thema, konnte aber noch nichts im Inet finden. Hatte vielleicht jemand schon Erfolg??
Hallo ich arbeite gerade auch an dem gleichen Problem und möchte position independent code im RAM ausführen. Hat jemand eine Lösung?
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.