Hallo,
ich habe gerade ein kleines Tesprogramm in Asembler für einen PIC18F2550
geschrieben, das auch funktioniert.
Ein paar Variablen habe ich ab 0x020 deklariert.
Vor dem Hauptprogramm habe ich dann ORG 0x000 hingeschrieben.
Nun will ich den Bootloader von sprut benutzen. Der 'Bootblock' belegt
den Anfang de Speichers (ab 0x000). Ich darf mein Programm laut sprut
erst bei 0x800 starten lassen.
Ich habe meinen Code dann einfach ORG 0x800 und die Variablen habe ich
ab 0x820 deklariert.
Leider hängt sich das Programm offenbar auf, sowie die erste Variable
benutzt werden soll.
Was mache ich denn falsch?
Ich muss gestehen, dass ich eigentlich auch gar nicht verstehe, wieso
die erste Variante ohne Bootloader so korrekt ist. Denn:
Der Programmcode wird ab 0x000 in den Speicher geschrieben.
Möglicherweise ist der aber so lang, dass er bis zu 0x020 oder darüber
hinaus reicht.
Das weiß ich doch gar nicht. Wäre es nicht sinnvoll die Variablen vor
dem Start des Programmcodes zu platzieren? (Ein entsprechender Test ließ
sich allerdings gar nicht erst compilieren...)
Kann mir jemand die Nutzung von Speicher für Programm und Variablen mal
bitte etwas erklären?
Viele Grüße,
Stefan.
Stefan schrieb:
> Hallo,>> ich habe gerade ein kleines Tesprogramm in Asembler für einen PIC18F2550> geschrieben, das auch funktioniert.> Ein paar Variablen habe ich ab 0x020 deklariert.> Vor dem Hauptprogramm habe ich dann ORG 0x000 hingeschrieben.>> Nun will ich den Bootloader von sprut benutzen. Der 'Bootblock' belegt> den Anfang de Speichers (ab 0x000). Ich darf mein Programm laut sprut> erst bei 0x800 starten lassen.>> Ich habe meinen Code dann einfach ORG 0x800 und die Variablen habe ich> ab 0x820 deklariert.
Hi 0x000000 ist der Anfang des Bootblocks im Flash und 0x0007FF das Ende
daher muss das Programm bei 0x000800 anfangen ab da beginnt der Erste
Block für das Programm.
0x800 != 0x000800
> Leider hängt sich das Programm offenbar auf, sowie die erste Variable> benutzt werden soll.>
kenne jetzt grade nicht die reg von den Gpio beim 2550 aber es solte ab
0x000 zu deklarieren sein nicht wie beim 16f ab 0x020
> Viele Grüße,> Stefan.
K. J. schrieb:
> 0x800 != 0x000800
Wer (welches Tool) erkennt denn hier auf Ungleichheit? 800 Hex sollte
doch 800 Hex sein - egal wie viele Nullen zwischen dem x und der 800
stehen.
Gruß,
Bernd
Hallo,
Variablen kannst du ab der Adresse 0x000 deklarieren. Diese Adresse
bezieht sich auf den Datenspeicher/RAM, und hat nichts mit dem
Programmspeicher zu tun, in welchem dein Programm bzw. auch der
Bootloader steht. 0x800 und 0x000800 ist meiner Meinung nach auch das
gleiche.
Gruß Flo
> Variablen kannst du ab der Adresse 0x000 deklarieren. Diese Adresse> bezieht sich auf den Datenspeicher/RAM, und hat nichts mit dem> Programmspeicher zu tun
Dem Stimme ich nur halb zu.
Durch die Harvard-Architektur ist der Datenspeicher und der
Programmspeicher getrennt. Also kannst du die Variable weiterhin
mit den alten Adressen benutzen. Du musst nur wissen, welche
Adressen der Bootloader benutzt. Da dieser wohl nicht mehr ausgeführt
werden soll (außer nach einem Neustart/Reset) kannst du diese aber
auch überschreiben.
Im PIC18F2550 ist der Speicher wieder in Bänke unterteilt.
Die Befehle haben deswegen noch ein Parameter, welcher bestimmt ob
in die SFRs (Special Function Registers, das sind die Register wie
PORTA, TRISA, SSPCON1, STATUS, etc.) oder in die GPRs (General
Purpose Registers, alle Register zur freien Verwendung) geschrieben
oder gelesen werden soll.
Die Bank setzt du mit einem MOVWF BSR, a oder mit MOVLB k, wobei
k eine Konstante ist und a = 0 definiert ist. Mit a = 1 schreibst du
in die GPR und mit a = 0 eben in die SFRs, darunter in das BSR.
Grob könnte man sagen, dass BSR die Entsprechung der Segmentregister
von einem 80386 kompatiblen Prozessor ist, falls dir das etwas sagt.
Da die Bytes 0x00-0x5F in Bank 0 und die Bytes 0x60-0xFF in Bank 15
die SFRs sind, solltest du einfach zu Beginn die Bank auf 1 setzen
und kannst dann die Variablen auch bei 0 beginnen lassen.
Ich hoffe, ich konnte dir etwas helfen. =)
Viele Grüße
Sebastian
Bernd O. schrieb:
> K. J. schrieb:>>> 0x800 != 0x000800>> Wer (welches Tool) erkennt denn hier auf Ungleichheit? 800 Hex sollte> doch 800 Hex sein - egal wie viele Nullen zwischen dem x und der 800> stehen.>> Gruß,> Bernd
GPASM z.b. wen man 0x800 schreibt macht GPASM daraus 0x800000 in
Vergleich zu 0x000800 ist des ne ganz andere Adresse.
K. J. schrieb:
> Bernd O. schrieb:>> K. J. schrieb:>>>>> 0x800 != 0x000800>>>> Wer (welches Tool) erkennt denn hier auf Ungleichheit? 800 Hex sollte>> doch 800 Hex sein - egal wie viele Nullen zwischen dem x und der 800>> stehen.>>> GPASM z.b. wen man 0x800 schreibt macht GPASM daraus 0x800000 in> Vergleich zu 0x000800 ist des ne ganz andere Adresse.
Das ist ja ein krankes Tool. Was wird denn aus 0x8? auch 0x800000?
Dass Assembler nicht sonderlich portabel ist, ist ja bekannt, aber sowas
nervt doch nur - oder hat das auch einen Vorteil?
Wenn sich die Architektur weiterentwickelt, dann wird aus den heute
korrekten 0x800000 später mal 0x80000000 - oder wie?
Ich hatte früher auch ein paar Jahre PICs in Assembler programmiert
(MPASM) mit diversen 16Cxxx, kann mich aber nicht an ein solches
unerwartetes Verhalten erinnern.
Vielleicht hätte es mich früher aber auch nicht gestört...
Also wen man weis passt es und es ist synaktisch auch korrekt wen man ne
6hex lange Speicher Adresse hat gibt man halt nicht 0x800 an ebenso wen
du ne 2 hex breite gibst ja auch nicht 0x2 an sondern 0x02 ob des dan
von links nach rechts oder von rechts nach links aufgefüllt wird ist
halt Sache des Interpreters.
K. J. schrieb:
> Also wen man weis passt es und es ist synaktisch auch korrekt wen man ne> 6hex lange Speicher Adresse hat gibt man halt nicht 0x800 an ebenso wen> du ne 2 hex breite gibst ja auch nicht 0x2 an sondern 0x02
Warum sollte ich das tun? Wenn ich den Wert 2 schreiben will, dann
schreibe ich 2 und nicht 0002 oder 00000002. Sowas macht man eigentlich
nur wenn mehrere Variablen untereinander stehen und man mit den
einstelligen Werten das Bild nicht versauen will.
> ob des dan> von links nach rechts oder von rechts nach links aufgefüllt wird ist> halt Sache des Interpreters.
Natürlich, man kann alles festlegen beispielsweise, dass rot nun grün
ist und links hier rechts bedeutet. Mit schöner Regelmäßigkeit geht das
dann aber auch schief - eben weil es unintuitiv ist.
Mathematisch ist eben 0x800 == 0x000800. Wenn ein Assembler hier aus der
Reihe tanzt und meint, dass 0x800 == 0x800000 wäre, somit also 2048 das
gleiche wäre wie 8388608, führt das zu Problemen. Spätestens wenn man
mehr Makrofähigkeit braucht als der Assembler liefern kann und zu einer
separaten Makrosprache greift wird's aufwändig und Fehlerträchtig.
Gruß,
Bernd
Sebastian Hepp schrieb:
> Nunja, wir Menschen mit unserem Dezimalen Zahlensystem lassen auch nur> führende Nullen weg.
Wir Menschen (und die allermeisten unserer Rechentools - von solchen
exotischen Ausnahmen wie diesem Assembler mal abgesehen) lassen in
jedem Zahlensystem, auch im Hexadezimalsystem, führende Nullen weg,
eben weil sie insignifikant sind. Aus diesem Grund ist eben 0x2 das
gleiche wie 0x02 oder 0x0002, genauso wie 1234 == 01234 ist.
Alles andere wäre fatal. Stell Dir vor, Du hast eine Konstante von sagen
wir mal 0x20. Wenn Dein Tool (Assembler) je nachdem, in welche Variable
Du die Konstante schreiben willst mal 0x20, mal 0x2000 oder mal
0x20000000 daraus macht erhöht das die Fehlerwahrscheinlichkeit enorm.
Darum bin ich mir auch relativ sicher, dass diese obskure Sonderregel
nur für Addressen gilt und nicht für sonstige Arithmetik mit diesem
Assembler.
> Mir wäre neu wenn 80 = 80000 sein soll XD
Mir auch, aber für diesen (ominösen) Assembler scheint das normal zu
sein, denn der macht genau das.
Gruß,
Bernd
Bernd O. schrieb:
>> Ich hatte früher auch ein paar Jahre PICs in Assembler programmiert> (MPASM) mit diversen 16Cxxx, kann mich aber nicht an ein solches> unerwartetes Verhalten erinnern.>
Das macht der MPASM auch heute noch nicht so. Mann kann führende Nullen
durchaus weg lassen. Notfalls füllt der Assembler die führenden Nullen
automatisch auf. Ich hab mir allerdings auch angewöhnt Bytes zweistellig
und Adressen vierstellig (Bei PIC16F) zu schreiben.
Sven
Ok, vielen Dank für die zahlreichen Antworten.
Leider habe ich in der Woche momentan zu wenig Zeit, aber ich werde
spätestens Freitag abend mit diesen Informationen nochmal im Datenblatt
lesen. Das Umschalten der Bänke kannte ich beim 18F2550 nicht. Das werde
ich mir mal ansehen.
Was die Zahlen angeht, also MPLab behandelt auch 0x20 wie 0x0020.
Zumindest ist mir aufgrund dieser Schreibweisenunterschiede noch kein
Fehler aufgefallen. Aber auch das teste ich sicherheitshalber am
Wo-Ende.
Ich sage dann nochmal Bescheid, ob und vor allem wie es dann mit dem
Bootloader funktioniert.
Viele Grüße,
Stefan.
Du musst dir halt immer vor Augen halten, dass du bei den µC in der
Harvard Architektur bist. Das heist Daten-, Programm- und Eprom-
Speicher sind völlig getrennt voneinender. Alle diese drei
Speicherbereiche fangen bei 0x0000 an und gehen bis zu ihrem Maximum
(hängt vom Typ des µC ab).
Dein Programm liegt im Flashspeicher und kann nur von hier aus
ausgeführt werden. Nichtflüchtige Daten kannst du im EPROM speichern
(bei vielen Typen auch im Flash, aber dass ist eher eine nützliche
Beigabe und sollte aufgrund der maximalen Schreibzyklen des Flash nicht
überbeansprucht werden). Und deine Variablen legst du im RAM an.
Die 18F können bis zu 16 RAM-Bänke a 256 Bytes haben. Nun gibt es noch
einen mit Access-RAM bezeichneten gesonderten Speicherbereich. Dieser
Access-RAM setzt sich aus den Bytes 0x0000 - 0x005F von Bank 0 und den
Bytes 0x0060 - 0x00FF der Bank 15 zusammen. In diesem zweiten Bereich
liegen auch die Statusregister (SFR) welche praktisch in den Access-RAM
gespiegelt werden. Damit ist es nun möglich ohne die Bank umzuschalten
die ersten 128 Userdatenbytes und die Statusbytes über den Access-RAM
anzusprechen. Benötigst du mehr wie 128 Bytes, geht die Bankumschalterei
wieder los, so wie halt schon bei den 16F...
Viel Spaß noch
Sven
Also, ich habe jetzt noch mal getestet und komme zu einem seltsamen
Ergebnis.
Gut ist erstmal, dass das Programm sowohl mit als auch ohne Bootloader
läuft, wenn ich als Startadresse 0x0800 eingebe (0x800 habe ich noch
nicht getestet) und die Variablen ab 0x60 definiere (war noch vom
letzten Test auf diesem Wert).
Komisch ist aber, dass die Takfrequenz offenbar wesentlich höher ist,
wenn ich das ganze über den Bootloader laufen lasse. Beide male wird der
gleiche 4MHz Resonator verwendet und für den Bootloader habe ich die
4MHz Variante gewählt. Allerdings muss ich bei Bootloaderbenutzung meine
Wartescheifen extrem vergrößern. Es scheint, als würde der PIC mit mehr
als 20 MHz laufen.
Kann das überhaupt sein? Kann irgendeine Einstellung im Bootloader den
PIC schneller machen, obwohl nur einen 4MHz Resonator angeschlossen ist?
Ich vermute sogar, dass mein Programm auch vorher schon mit dem
Bootloader lief - allerdings so schnell, dass ich es gar nicht
mitbekommen habe...
Wie seht ihr dieses Problem?
>Es scheint, als würde der PIC mit mehr>als 20 MHz laufen.>Kann das überhaupt sein? Kann irgendeine Einstellung im Bootloader den>PIC schneller machen, obwohl nur einen 4MHz Resonator angeschlossen ist?
Im Bootloader wohl kaum. Wahrscheinlicher ist das das ConfigWord
auf HSPLL eingestellt ist. Dann bekommst du auch mehr als 4MHz.
Die 18F haben einen internen PLL. Damit lässt sich die Taktfrequenz des
Prozessors intern vervielfachen. Der µC leitet daraus intern seinen USB
Takt von 96 MHz ab. Der Takt für den Prozessor kann über entsprechende
Vorteiler auf bis zu 48 MHz geschraubt werden. Es ist also durchaus
denkbar, dass dein Programm mit der 10fachen Geschwindigkeit läuft.
Zu den Variablen: Die solltest du gerade nicht ab 0x0060 definieren,
zumindest nicht in Bank0. Definiere deine Variablen ab 0x0000 und greife
über den Access-RAM darauf zu. Den Zugriff auf den Access-RAM steuerst
du im Befehl (a=0 oder 1). Wenn du am Anfang mit dem Access RAM
arbeitest sparst du dir die Bankumschalterrei. Beachte aber, dass deine
Uservariablen dann im Bereich 0x0000 bis 0x005F liegen und ab 0x0060 die
Special Funktion Register (SFR) kommen. Wenn du deine Variablen
allerdings ab 0x0060 anlegst, könnte es durchaus sein, dass du Probleme
bekommst.
Sven
Hallo ,
ich denke die Interrupt Vektoren müssen auch umgelegt werden.
Desweiteren kann es sein, dass im Linker-Script Platz für den Bootloader
reserviert werden muß. Ansonsten, wie schon oben gesagt, ist es eine
beliebte Falle über 0x5f mit den Variablen zu gehen.
;***********************************************************************
*******
STARTUP CODE 0x0000
bra RVReset
HI_INT_VECTOR CODE 0x0008
bra RVIntH ; Re-map Interrupt vector
;
_V_INT_LOW CODE 0x0018
bra RVIntL ; Re-map Interrupt vector
;**************************************************************
;
;**************************************************************
PROG1 CODE
org 0x800
RVReset
goto start
org 0x808
RVIntH
goto IntVector_high
org 0x818
RVIntL
goto IntVector_low