Forum: Mikrocontroller und Digitale Elektronik Speicherbereich der Variablen beim PIC18F2550: wohin damit?


von Stefan (Gast)


Lesenswert?

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.

von K. J. (Gast)


Lesenswert?

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.

von Bernd O. (bitshifter)


Lesenswert?

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

von Flo (Gast)


Lesenswert?

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

von Sebastian H. (sebihepp)


Lesenswert?

> 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

von K. J. (Gast)


Lesenswert?

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.

von Bernd O. (bitshifter)


Lesenswert?

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...

von K. J. (Gast)


Lesenswert?

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.

von Sebastian H. (sebihepp)


Lesenswert?

Nunja, wir Menschen mit unserem Dezimalen Zahlensystem lassen auch nur
führende Nullen weg.

Mir wäre neu wenn 80 = 80000 sein soll XD

von Bernd O. (bitshifter)


Lesenswert?

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

von Bernd O. (bitshifter)


Lesenswert?

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

von Sven S. (stepp64) Benutzerseite


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

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.

von Sven S. (stepp64) Benutzerseite


Lesenswert?

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

von Stefan B. (changlee)


Lesenswert?

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?

von holger (Gast)


Lesenswert?

>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.

von Sven S. (stepp64) Benutzerseite


Lesenswert?

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

von Martin (Gast)


Lesenswert?

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

von Maik W. (werner01)


Lesenswert?

Vieleicht sind Pic's einfach nur sinnlos!`?

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
Noch kein Account? Hier anmelden.