Forum: Mikrocontroller und Digitale Elektronik PIC MPASM - Festlegung Startadresse in Programmspeicher


von Michael S. (mistreit)


Lesenswert?

Hallo zusammen,

ich kämpfe hier mit der Programmierung eines PIC´s in Assembler.
Da ich schon einiges an Projekten mit dem PIC in Assembler erstellt habe 
werden die Programme doch immer länger und unübersichtlicher.
So habe ich jetzt angefangen Projekte in mehrere .asm-Files aufzuteilen.
Prinzipiell funktioniert das auch, aber ich habe ein Problem, bei dem 
ich nicht weiter komme.
Routinen, die mit Tabellen arbeiten erfordern es, dass sie innerhalb 
einer Memory-Page des PIC´s liegen. Wenn ich in einem Projekt nur EIN 
.asm-File habe, setze ich einfach in den Programmcode an die 
entsprechende Stelle ein org mit der Startadresse einer Page und es 
funktioniert.
Wenn ich aber mit mehreren .asm-files arbeite, so lässt der Compiler das 
nicht zu. Offensichtlich darf man da nur in einem .asm-File die 
org-Funktion verwenden. Wenn ich dann in einem weiteren file versuche 
eine Zuordnung mit org durchzuführen bekomme ich Fehlermeldungen.
Da es sich dann ja offenslichtlich um "relocatable code" handelt darf 
man wohl nur noch "code" verwenden. Aber wie kann ich dann die Adresse 
im Programmspeicher festlegen?

Würde mich sehr über eine guten Tipp freuen :)

Michael S.

: Bearbeitet durch User
von Fachmann (Gast)


Lesenswert?

Man braucht nich mehrere .asm-files. Es gibt noch .inc files.Die kann 
man einbinden in .asm-file.

von schris (Gast)


Lesenswert?

Das macht man mit sections, also im linker file
Ein Beispiel eines default Linker file:
CODEPAGE NAME=vectors START=0x0 END=0x27 PROTECTED
CODEPAGE NAME=page0 START=0x28 END=0x1FFF
CODEPAGE NAME=page1 START=0x2000 END=0x3FFF PROTECTED
CODEPAGE NAME=config START=0xFE00 END=0xFE0F PROTECTED

Also wenn der Code (main) die section page1 verlangt, dann wird dieser
dort plaziert. Ob jetzt code auch bei mpasm funktioniert, oder durch ein 
Pragma ersetzt werden muss, weiss ich nicht mehr genau, code 
functioniert bei gpasm

 vectors code
 btfss 3,3
 return        ; return from sleep
 clrf pclath
 goto _main
int_vector
 movwf int_w
 swapf status,w
 clrf  status
 movwf int_s
 movfw pclath
 movwf int_p
 movfw fsr
 movwf int_f
 lcall interrupt
 clrf  status
 movfw int_f
 movwf fsr
 movfw int_p
 movwf pclath
 swapf   int_s,w
 movwf   status
 swapf   int_w,f
 swapf   int_w,w
 retfie

_main
 lcall init
 lgoto main

page1 code
init
 ; ...
interrupt
 ; ...
main
 ; ...

 code

von schris (Gast)


Lesenswert?

_main muss auch im page0 liegen, ansonsten gibt es eine fehlermeldung 
weil
vectors zu klein fuer den Code ist.

von Meister E. (edson)


Lesenswert?

1
A_VECTOR_ADDRESS equ 0x0000
2
B_VECTOR_ADDRESS equ 0x1234
3
4
A_Vector CODE A_VECTOR_ADDRESS
5
6
   ; code
7
   movlw ...
8
9
B_Vector CODE B_VECTOR_ADDRESS
10
11
   ; code
12
   movlw ...

: Bearbeitet durch User
von Chris B. (dekatz)


Lesenswert?

Michael S. schrieb:
> Hallo zusammen,
>
> Routinen, die mit Tabellen arbeiten erfordern es, dass sie innerhalb
> einer Memory-Page des PIC´s liegen. Wenn ich in einem Projekt nur EIN
> .asm-File habe, setze ich einfach in den Programmcode an die
> entsprechende Stelle ein org mit der Startadresse einer Page und es
> funktioniert.
>..............
> Aber wie kann ich dann die Adresse im Programmspeicher festlegen?
>
 Wozu eine Adresse festlegen. Das ist ja der "Witz" and er Sache das 
sich der Linker dann um die Auflösung kümmert.

Was die Tabellen betrifft: geht auch über Seitengrenzen hinweg, nur muss 
man ein bisschen Rechenarbeit leisten.
Irgendwo im Speicher steht deine Tabelle - als Beispiel auf 0x9FD

Table:
0x9FD movwf PCL,F   ;Offset in Tabelle wurde in W übergeben
0x9FE retlw 'A'
0x9FF retlw 'B'
0xA00 retlw 'C'
0xA01 retlw 'D'

Dein Programm steht irgendwo in Page0!
Der Zugriff erfolgt dann wie folgt:

movlw   LOW Table    ;unteren 8 Bit der Adresse
addwf   offset,F     ;in Variable <offset> steht welcher Tabelleintrag
movlw   HIGH Table   ;die oberen 5 Bit der Adresse
btfsc   STATUS,C     ;Seitenüberschreitung??
addlw   1            ;wenn JA, dann korregiere HIGH-Seitenadresse
movwf   PCLATH
movf    offset,W     ;das berechnete Offset
call    Table        ;wie gewohnt in W übergeben

(etwas modifiziert aus der AN556 von MICROCHIP)

: Bearbeitet durch User
von schris (Gast)


Lesenswert?

Nicht bei allen Pics ist der ganze Flash ueber einen Call erreichbar und 
genau da braucht man solche Sachen.

von Michael S. (mistreit)


Lesenswert?

Hallo an alle fleissigen Helfer hier!

Das mit den Antworten ging ja echt super schnell.

Vielen Dank dafür!

Das mit den #INCLUED-Dateian hatte ich auch probiert. Es scheint aber 
so, als sei das nicht der richtige Weg Programmcode als Modul 
einzubinden. Es müssen die #INCLUDE-Anweisungen immer am Ende des 
Programms stehen und im letzten dann ein END. Das hat mir nicht so 
gefallen.

Durch Eure anderen Vorschläge werde ich mich mal durcharbeiten.

Eine Sache habe ich bei der MPLAB-Entwicklungsumgebung auch noch nicht 
verstanden.
Da ich mit mehereren .asm-Dateien in einem Projekt arbeite und ich das 
auch compiliert bekomme, muss der Linker ja wohl schon im Einsatz sein.
Aber wo definiere ich den linker file, der verwendet wird?

: Bearbeitet durch User
von ./. (Gast)


Lesenswert?

Frueher™, als der Assembler noch auf Disketten vor sich hindrehte,
musste man ohne make und Buildsysteme von der Stange auskommen.

Dafuer gab es ja $INCL oder moderner: #include.
Fuer reine Assemblerprojekte ist es ueberhaupt kein Problem
die einzelnen Assemblermodule zu "includen".

Man muss sich nur rechtzeitig Gedanken machen, in welche Teile
man das ganze zerlegt.

Protipp:
Ein Include-File was die Definitionen und Deklarationen enthaelt.
Und dann das zugehoerige Modul als 2. File.
Fast wie in C :-)

Und das "END" kann man schon in sein "MAIN.ASM" schreiben,
und nicht in des letzte includierte File.

Da machst Du noch irgendwas verkehrt.

von Chris B. (dekatz)


Lesenswert?

Michael S. schrieb:
> Da ich mit mehereren .asm-Dateien in einem Projekt arbeite und ich das
> auch compiliert bekomme, muss der Linker ja wohl schon im Einsatz sein.
> Aber wo definiere ich den linker file, der verwendet wird?

Wenn man nicht irgendwelche Speicherbereiche schützen muss, Variablen 
unbedingt auf einer bestimmten Adresse stehen müssen (und dies nicht mit 
CONFIG-Einstellung und/oder im Sourcecode gemacht wurde/gemacht werden 
kann) etc etc. braucht man ein angepasstes Linkerfile.

 Wenn in einem Project meherer .asm Datein assembliert werden, werden 
die daraus resultierenden .obj (.o) Dateien automatisch gelinkt und dazu 
genügt das Standard-Linkerfile aus .../MPASM suite/LKR für den 
verwendeten Controller.

Zum nachlesen wie und was es alles gibt:
MICROCHIP DS33014K (bzw. DS33014L): MPASM/MPLINK/MPLIB Users Guide

von Michael S. (mistreit)


Lesenswert?

Vielen Dank für die Antworten.

Ich denke ob man mehrere .asm-Files verwendet oder "includes" ist auch 
"Geschmacksache". Es geht mir nicht darum "...in welche Teile man das 
ganze zerlegt...", sondern wie man Programmmodule schaffen kann, für 
bestimmte Hardwarekomponenten, die  man dann immer wieder in 
verschiedenen Projekten verwendet, möglichst ohne was daran ändern zu 
müssen.

@Chris B.
Natürlich kenne ich das User Guide auch. Ich hoffte halt, dass mir hier 
mal jemand mit wenigen einfachen Worten das Konstrukt erklären kann, 
wenn man mit einem linkerfile arbeitet. Am besten ganz praktisch, wo der 
File steht und wie ich den File, den MPLAB aktuell benutzt einsehen 
kann. Das habe ich einfach noch nicht verstanden. Wie dann der genaue 
Syntax ist usw. finde ich dann schon wieder selbst raus...

von Ottmar K. (wil1)


Angehängte Dateien:

Lesenswert?

Hallo Michael,
Dein Problem hatte ich früher auch mal. Daher habe ich in meinen alten 
Projekten gekramt und Dir daraus etwas zusammengestellt. Du kannst das 
Projekt laden und ausführen. Verwende dazu MPLAB-SIM im Debug-Modus. 
Setze auch mal Haltepunkte in den Includefiles und schau dir dazu über 
das Menü   "View" - Programm-Memory" den Inhalt des Programmspeichers 
an. Dort werden auch Haltepunkte angezeigt.

Beiliegend ein MPLAB-ASM-Beispiel, welches demonstriert wie das mit den
*.INC-Files funktioniert. Auch ist in einem Include-file eine Subroutine 
enthalten, welche das Lesen von Tabellen, auch über Pagegrenzen hinweg 
erlaubt.

Solche Includefiles sind ganz praktisch. So halte ich z.B. meine 
LCD-Initialisierung, Mathematische Routinen wie z.B. 16x8Bit 
Multiplikation, Binär- zu BCD- Wandlung u.a. in Includefiles bereit.

Als Ausblick:
Wenn man mit sogenanntem "relocatable" Code arbeitet, genügt 1 File, 
welches alle interessierenden, von Dir oder anderen entwickelten 
Subroutinen enthält. Du gibtst nur an, welche Subroutinen verwendet 
werden sollen und der ASM-Compiler fügt dann auch nur diese
Subroutinen und nicht die komplette Datei in das Hexfile ein.

mfG Ottmar

von Takao K. (takao_k) Benutzerseite


Lesenswert?

Verwende doch C.

Welcher PIC ist es denn?

von Chris B. (dekatz)


Lesenswert?

Michael S. schrieb:
> Vielen Dank für die Antworten.
> Natürlich kenne ich das User Guide auch. Ich hoffte halt, dass mir hier
> mal jemand mit wenigen einfachen Worten das Konstrukt erklären kann,
> wenn man mit einem linkerfile arbeitet. Am besten ganz praktisch, wo der
> File steht und wie ich den File, den MPLAB aktuell benutzt einsehen
> kann.

Das würde wohl eine mehrseitige Anleitung werden und dann noch immer 
nicht alle Fragen beantworten. Und das Linkerfile ist bei einem 
Multi-File-Projekt ziemlich was Nachrangiges wo man normalerweise gar 
nix herumdrehen muss( da schon eher beim Bootloader-Basteln etc....)

Auch sind die Lösungen mit dem Includen eines .ASM Files nicht wirklich 
das was man möchte wenn man fertige, getestet Routinen einbinden will 
oder ein größeres ASM-Project mit mehreren Sourcefiles aufziehen will.

Die Stichwörter sind wohl:
- Relocatable Modules
- Creating a multiple file Project
- Creating a relocatable Modul
- Calling a relocatable Modul
- Including object Files

Hier ein Link:
http://www.talkingelectronics.com/projects/Elektor/Gooligum%20PIC%20Tutorials/PIC_Base_A_3.pdf

Ab Seite 11 findet sich dort ein einfaches Beispiel mit den Programmen, 
Project-Aufbau, Verwendung von PUBLIC, EXTERN etc. etc.

von Michael S. (mistreit)


Lesenswert?

Hallo Ottmar,

vielen, vielen Dank für die Mühe!
Ich werde mir das mal in den nächsten Tagen in Ruhe ansehen und 
durcharbeiten!


Hallo Takao,

ich freue mich über jeden der weiterhelfen will und hier antwortet. Aber 
sei mir nicht böse, genau so eine Antwort habe ich "befürchtet".
Die Antwort ist für mich ein wenig so, wie wenn ich Autoforum schreibe 
ich habe mit meine VW Passat das und das Problem und als Antwort kommt: 
Fahr doch einen Opel! Das hilft also kein bischen bei dem Problem 
weiter.
Aber zum Thema. Ich kann kein C, habe aber in "PIC-Assember" schon vor 
10 Jahren einiges prgrammiert. Das Programmietren selbst ist weniger das 
Problem, aber ich kämpfe immer mit den Entwicklungsumgebungen.
Übrigens ist es in dem aktuellen Projekt ein 16F1828.

Hallo Chris,

vielen Dank für die Info und den Link. Der sieht schon mal sehr 
interessant aus. Dann muss ich mich da halt doch mal durcharbeiten...

von Ottmar K. (wil1)


Lesenswert?

Ergänzend zum Link von Chris, hier die Originaladresse der Tutorials zu 
MPASM-Assembler und auch zu PIC-C in englischer Sprache:

http://www.gooligum.com.au/tutorials.html

mfG Ottmar

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.