Hallo Community, ich habe ein großes Problem beim kombinieren von meinen beiden Projekten. Ich habe den Silabs C8051F120 als MCU + vorhandene Elektronik mit kompletter Peripherie, d.h. ich kann den Prozessor nicht mehr wechseln! Ich arbeite mit µVision 3.30a (incl. PK51). Ich habe ein Bootloader-Projekt und ein Frimware-Projekt. Ich muss nun auf Codebanking umsteigen, weil der Firmware-Code mittlerweile die 64k Grenze übersteigt und noch nicht alle gewünschte Funktionalität implementiert ist. Deshalb habe ich bei beiden Projekten auf Codebanking umgestellt. Wenn ich die Projekte für sich kompiliere und aufspiele, gibt es keine Probleme. Ich habe nur ein Problem mit dem Firmware-Projekt, weil ich dort dem Linker(LX51) aus welchem Grund auch immer nicht mitteilen kann, dass die Firmware in der Ersten Bank die ersten 8191 Bytes nicht verwenden soll, weil diese ja schon vom Bootloader verwendet wurden. Die Konfiguration ist zur Zeit so: Bankarea(C:0x8000 - C:0xFFFF) Der Bootloader-Code beginnt bei 0x8000 und endet bei 0x9FFF. Die Firmware soll bei 0xA000 beginnen, das funktioniert aber nur teilweise, weil ich kann zwar dem Linker sagen, dass erst bei einem Offset von 0xA000 begonnen werden soll, aber er linkt trotzdem irgendwelche Funktionen in den Bereich davor. Kann mir da irgendjemand einen guten Tipp geben, was ich ggf. falsch mache? Ich bedanke mich schon im Vorraus für zahlreiche Antworten. Viele Grüße, Daniel
> aber er linkt trotzdem irgendwelche Funktionen in den Bereich davor. Ich tippe mal spontan, dass IRGENDWELCHE Funktionen die Interrupt-Vektoren sind... > Kann mir da irgendjemand einen guten Tipp geben, was ich ggf. falsch mache? SiLabs hat ne AppNote für einen USB-Bootloader, evtl. findest du da schon mal Infos. Für Code-Banking-Applikationen müsste auch was da sein. Ansonsten gäb's noch die Keil Knowledge-Base als Anlaufpunkt. Ralf
Hallo Ralf, danke für deine Antwort, aber die Interrupt-Vektoren sind es nicht, die habe ich schon per Linker-Befehl fix in den Common-Bereich geschoben. Da rutschen immer irgendwelche Funktionsfragmente anderer Funktionen rein. Es kann ja aber nicht das Ziel sein, dass ich jedes einzelne Segment separat addressieren muss - nur damit alles hintereinander kommt - oder? Die Knowledge-Base und alles mögliche von Keil zu diesem Thema habe ich schon durchforstet, habe dazu auch einiges gefunden. Ich bleibe aber immer wieder am selben Problem hängen. Es gibt im Linker irgendwie nur die Möglichkeit bestimmte Segmente direkt zu adressieren. Die AppNote zu dem USB-Bootloader werde ich mir gleich mal ansehen, vielleicht find ich da noch was brauchbares und meld mich dann wieder. Daniel
Bei den unseren AVR machen wir das so, dass wir auf einen Master-AVR den Bootloader aufspielen, dann über den Bootloader die Applikation nachladen und anschließend ein Hexdump ziehen; das dann als Vorlage für alle weiteren Controller dient.
Ich arbeite zwar mit SDCC, aber das sollte da analog funktionieren. Per Bank-geswitchtes Modul musst Du für alle globalen Variablen/Daten und Funktionen normalerweise per pragma-Direktive einen Segmentnamen angeben. Im Linker-Script weist Du dann jedem Segment eine 20-Bit-Adresse zu. Wie das bei Keil genau geht, weiss ich nicht mehr, der flog zugunsten von SDCC in die Ecke. Vielleicht kannst Du dir von diesem SDK http://openschemes.com/2011/08/23/our-turn-with-the-ax206-digital-photo-frames/2/ was abgucken. Gruss, - Strubi
> Es kann ja aber nicht das Ziel sein, dass ich jedes einzelne Segment > separat addressieren muss - nur damit alles hintereinander kommt - oder? Das nicht, doch ich glaube, du musst es für jedes Modul machen, bzw. für jede Gruppe von Modulen. Wobei es eigentlich reichen sollte, dem Linker zu sagen, dass der Code-Bereich für's komplette Projekt an einer anderen Stelle beginnt. Das ist im Memory-Dialog, wenn man den Haken bei "use memory layout from target dialog" rausnimmt, dann sollte man es selbst einstellen können. Hast du dir mal das MAP-File angeschaut, welche Funktionen im "verbotenen" Bereich landen? Ralf
Hallo zusammen, vielen Dank für die vielen Tipps. @Ralf: das USB-Bootloader Projekt habe ich mir angesehen, das beschreibt im Prinzip genau den Status meines Programms bevor ich mit Codebanking angefangen habe, es ist genau so aufgebaut. @Stefan: genau das iss ja mein Problem, den Bootloader aufspielen kann ich nur ich bekomm ja nichtmal nen lauffähiges Firmware-Executable aus dem Compiler raus, was ich dann aufspielen könnte. @Strubi: Bei Keil werden Funktionen automatisch zu Segmenten, die man speziefisch adressieren kann. @Ralf: Der Codebereich fürs komplette Projekt kann nur einmal deklariert werden, das stimmt soweit. Nur habe ich bei diesem Controller das Problem, dass ich so ne Einstellung für jede Bank seperat machen müsste, da es folgende Einschränkungen gibt: 1. Der Bootloader fängt bei Bank1:0x8000 an und hört bei B1:0x9FFF inclusive Reserve auf. Das würde bedeuten, wenn ich den Codebereich im Firmware-Projekt von 0xA000 - 0xFFFF definiere, gilt das dann auch für die anderen Bänke und damit würde ich dann 2x 0x2000 Bytes einbüßen. 2. Laut Datenblatt vom Controller darf ich den Bereich Bank3:0xC000 - 0xFFFF nicht mehr beschreiben, da dort die lese/schreib - Schutz Bytes sind. Wenn ich dort was reinschreibe, dann wird der ganze Controller lese/schreib geschützt, so dass ich über den JTAG nichts mehr machen kann (ist alles im Zuge der Problemlösung passiert, die letzten Tage). Das MAP-File ist ständig offen bei mir, daher weis ich ja, dass der Linker da irgendwie mist gebaut hat. Nun habe ich dann nach intensievem Suchen endlich das erlösende Schlüsselwort RESERVE für den Linker gefunden. Damit kann man spezielle Bereiche als Reserviert deklarieren und somit weis der Linker, dass er nichts in diese Bereiche legen soll. Nachdem ich das nun nochmal Compiliert hab, habe ich nun aber das Problem, dass unzählige IMPROPER FIXUP's kommen und ich nicht weis, wie ich die alle beheben soll. Weil in der Hilfe zu diesem Problem steht nur im Groben, dass dieser fehler auftritt, wenn ein Jump gemacht werden soll, der zu weit weg ist. Wie soll man das jetzt verstehen, muss ich jetzt die Funktionen(FYI: es sind über 95!) doch einzeln adressieren und auch noch solange die Reihenfolge tauschen, bis kein Fehler mehr auftritt? Vielleicht kann mir ja dazu noch jemand einen guten Tipp geben. Viele Grüße, Daniel
Normaler Weise plaziert man den Bootloader nicht irgendwo mittendrin, sondern ganz ans Ende. Die Applikation fängt dann ganz normal bei 0x0000 an, sie weiß garnichts davon, daß überhaupt ein Bootloader existiert. Kann dieser MC überhaupt den Resetvektor verschieben, damit er auf den Bootloader zeigt? Peter
Hallo Peter, klar kann man den Resetvektor verschieben, das habe ich auch gemacht. Und bei Codebanking mit diesem Controller fängt nun mal alles bei 0x8000 an, weil der Bereich davor 0x0000-0x7FFF ist die Common-Area. Nun gut, ich könnte jetzt den Bootloader auch nach hinten schieben, das löst aber mein Problem nicht. Vielen Dank trotzdem.
Hier noch ein Nachtrag zum vorigen Beitrag: Es besteht ausserdem das Problem, dass der Linker aus unerklärlichen Gründen große *Gap*'s zwischen die Funktionen macht. Woran liegt das und kann man das irgendwie verhindern? Nur mal ein Beispiel: Er hat in einer Bank einen Gap von 0x29FB, was 10747 Bytes sind, produziert. Gruß, Daniel
Ich hab bisher nie so extrem große Programme gehabt, daher habe ich Banking noch nie benutzt. Benutzt Du keine Optimierung? Benutzt Du das Large-Modell? Man erreicht deutlich kompakteren Code, wenn man das Small-Modell benutzt und nur große Arrays als xdata definiert. Beim Banking muß natürlich Code auch unter 0x8000 plaziert werden, z.B. Interrupthandler. Das sollte eigentlich der Linker selbst entscheiden können. Deshalb auch den Bootloader ans Ende, damit der Linker ihn nicht überschreibt. Peter
Daniel schrieb: > 1. Der Bootloader fängt bei Bank1:0x8000 an und hört bei B1:0x9FFF > inclusive Reserve auf. Das würde bedeuten, wenn ich den Codebereich im > Firmware-Projekt von 0xA000 - 0xFFFF definiere, gilt das dann auch für > die anderen Bänke und damit würde ich dann 2x 0x2000 Bytes einbüßen. Hallo, warum definierst du nicht einfach eine (leere) Datentabelle an dieser absoluten Adresse oder eine Folge von 8192 NOPs? Das frisst doch auch der dümmste Linker. Gruss Reinhard
Hallo Peter, ja ich habe die höchste Optimierungsstufe (11) eigestellt und ja im Moment benutz ich das Large-Memory-Modell. Ich habe aber auf deinen Hinweis hin mal auf Small umgestellt, ohne Erfolg. Die Fehler bleiben die gleichen. Das da auch im Common was rein muss, weis ich natürlich, aber da ich zur Zeit nur 3 Interrupt-Handler habe, ist das auch überschaubar. Ich habe diese natürlich manuell direkt dahin adressiert. @Reinhard: Wie kann man das im C-Code machen? Grüße, Daniel
Daniel schrieb: > Ich habe aber auf deinen > Hinweis hin mal auf Small umgestellt, ohne Erfolg. Small hat doch keinen Einfluß auf das Banking. Es soll nur die Codegröße verringern, daß vielleicht kein Banking nötig ist. Peter
Hallo Peter, das hat aber leider nicht dafür gereicht. Ich habe ja noch vor, was dazu zu nehmen, aber im moment bekomm ich ja nichtmal das vorhandene lauffähig. Vielen Dank für die Informationen. Grüße, Daniel
> 1. Der Bootloader fängt bei Bank1:0x8000 an und hört bei B1:0x9FFF > inclusive Reserve auf. Das würde bedeuten, wenn ich den Codebereich im > Firmware-Projekt von 0xA000 - 0xFFFF definiere, gilt das dann auch für > die anderen Bänke und damit würde ich dann 2x 0x2000 Bytes einbüßen. Bist du sicher? Ich meine, man kann für die Bänke separate Adressbereiche angeben (komme leider grad nicht dazu, nachzuschauen). > 2. Laut Datenblatt vom Controller darf ich den Bereich Bank3:0xC000 - > 0xFFFF nicht mehr beschreiben, da dort die lese/schreib - Schutz Bytes > sind. Wenn ich dort was reinschreibe, dann wird der ganze Controller > lese/schreib geschützt, so dass ich über den JTAG nichts mehr machen > kann (ist alles im Zuge der Problemlösung passiert, die letzten Tage). Nicht ganz richtig, du darfst da sehr wohl reinschreiben, nur an die Adressen der entsprechenden Security-Bytes darfst du nix schreiben, wenn ich mich recht entsinne. > habe ich nun aber das Problem, dass unzählige IMPROPER FIXUP's kommen > und ich nicht weis, wie ich die alle beheben soll. > Weil in der Hilfe zu diesem Problem steht nur im Groben, dass dieser > fehler auftritt, wenn ein Jump gemacht werden soll, der zu weit weg ist. P.Danneger hat's schon angedeutet, aber ums klar zu machen: Du kannst beim Banking keinen Code zwischen den Bänken aufrufen. Das heisst im Klartext: Eine Funktion, welche in der oberen Hälfte beispielsweise in Bank 1 liegt, kann keine Funktion aus Bank 2 aufrufen. Deswegen sollte der Hauptteil der Applikation immer in Bank 0 sein, und Funktionen, die andere Funktionen aufrufen müssen entsprechend in der gleichen Bank sein. Könnte das evtl. dein Problem mit den FixUps sein? Ralf
Nachtrag: Evtl. findest du hier noch passende Informationen: http://www.cygnal.org/ubb/Forum1/HTML/002578.html http://www.cygnal.org/ubb/Forum1/HTML/003294.html http://www.cygnal.org/ubb/Forum1/HTML/003390.html Ralf
Hallo Ralf, > Bist du sicher? Ich meine, man kann für die Bänke separate > Adressbereiche angeben (komme leider grad nicht dazu, nachzuschauen). Ja, das geht nur bei Segmenten, wo man es so schreiben kann: B1:0x8000 - B1:0xFFFF > Nicht ganz richtig, du darfst da sehr wohl reinschreiben, nur an die > Adressen der entsprechenden Security-Bytes darfst du nix schreiben, wenn > ich mich recht entsinne. Das stimmt schon, aber irgendwas steht da noch, dass code der in dieser Region ausgeführt wird nix in Regionen weiter unten schreiben kann oder so ähnlich. > P.Danneger hat's schon angedeutet, aber ums klar zu machen: > Du kannst beim Banking keinen Code zwischen den Bänken aufrufen. Das > heisst im Klartext: Eine Funktion, welche in der oberen Hälfte > beispielsweise in Bank 1 liegt, kann keine Funktion aus Bank 2 aufrufen. > Deswegen sollte der Hauptteil der Applikation immer in Bank 0 sein, und > Funktionen, die andere Funktionen aufrufen müssen entsprechend in der > gleichen Bank sein. > Könnte das evtl. dein Problem mit den FixUps sein? Möglicherweise ja, ich kann es zumindest nicht ausschließen. Ich habe nun halt alle Funktionen (ca. 100) geschnappt und diese entsprechend ihrer Codegröße in die drei Banken eingeteilt. Es gibt keinen richtigen Haupt und Nebenteil, da es sich um ein Messgerät handelt und immer zyklisch alles gebraucht wird, was da ist. Wenn ich das eher nach dem Call-Tree einsortieren muss, werd ich bestimmt ein mega großes Problem haben, weil es sind zwei drei Funktionen dabei, die alleine ca. 4kB groß sind und auch noch alle möglichen Funktionen aufrufen. Daniel
Hi Daniel, okay, dann sagste Bescheid, wenn du "umstrukturiert" hast. Ralf
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.