Forum: Mikrocontroller und Digitale Elektronik Real-View-Compiler


von Martin (Gast)


Lesenswert?

Hallo Leute!

Ich beginne gerade mit dem RealView-Compiler.

Ich wollte fragen, wie ich es schaffe, eine Variable an eine bestimmte
Speicherstelle zu schieben.

Mit dem Keil-Compiler funktioniert das z.B. folgendermaßen:
uint32_t const f_protect __at 0x1FC = 0x87654321;

Leider hat der RealView hier anscheinend eine andere Syntax, weil er
bei obiger Zeile folgenden Fehler meldet:
": error: #65: expected a ";"
Ich habe leider im Benutzer-Guide nicht die richtige Stelle finden
können, um das Problem zu lösen.
Gibt es bei dem RealView-Compiler eine Möglichkeit, die Variablen
ebenfalls auf eine bestimmte Speicherstelle zu schieben?

Danke für eure Antworten.

Tschüss,
Martin

PS: Schönes Wochenende

von A.K. (Gast)


Lesenswert?

Wer sich nicht an einen bestimmte Compiler binden will, tut gut daran, C
nicht bloss aus dem Handbuch des Compilers zu lernen. Und verwendet
folglich so weit wie möglich nur Standard-Konstrukte (geht nicht immer,
z.B. bei Interrupts geht's eher selten).

Konkret heisst es, dass man keine Variable per Compiler-spezifischer
Option (__at) irgendwo plaziert, denn das sieht jedesmal anders aus.
Sondern dass man einen Makro verwendet wie:
  #define f_protect (*(volatile unsigned int *)0x12345678)
denn das geht zumindest ausserhalb des vom Linker verwalteten
Speicherplatzes immer.

Wenn die Variable freilich irgendwo im RAM liegen soll, also in dem
Bereich der üblicherweise von Compiler und Linker verwaltet wird, dann
sollte man mal überlegen, ob man überhaupt den richtigen Ansatz hat.

von Martin (Gast)


Lesenswert?

Hallo!

Es geht darum auf die Speicherzelle Adresse 0x1FC, das ist eine
Speicherzelle im Flash, den Wert 0x87654321 zu schreiben.

Ich verwende den LPC2138 und dieser ist, wenn dieser entsprechende Wert
an die entsprechende Speicherstelle geschrieben wurde lesegeschützt.

Ich kenne mich mit diesem Makro nicht ganz so gut aus.
#define f_protect (*(volatile unsigned int *)0x12345678)

Bedeutet diese Definition, dass f_protect nun ein Zeiger ist, der auf
die Speicherzelle 0x12345678 zeigt?

Tschüss,
Martin

von Bartholomäus S. (sam_vdp)


Lesenswert?

Nicht direkt. #defines in C werden vom Präprozessor behandelt, d.h.
bevor das Programm compiliert wird, wird jedes vorkommen von
"f_protect" in deinem Quelltext durch "(*(volatile unsigned int
*)0x12345678)" ersetzt.

Siehe http://de.wikipedia.org/wiki/Pr%C3%A4prozessor

von ARM-Fan (Gast)


Lesenswert?

Dann schreibst du in deinem Programm einfach:

{
   (*(volatile unsigned long *)0x000001FC) = 0x87654321;
}

Fertig.

Ums zu verstehen, muß man von rechts nach links lesen:

Die "Zahl" 0x000001FC sei ein Zeiger auf einen flüchtigen
unsigned long Wert - das ist der cast in der Klammer (volatile...*).

Nun haben wir einen Zeiger an die gewünschte Adresse.

Mit dem "*" links neben der Klammer wird der Zeiger nun
dereferenziert.
Sprich: Wir greifen auf den INHALT der Speicherzelle zu, auf die
der Zeiger zeigt.

Und eben dieser Inhalt wird auf den gewünschten Wert von 0x87654321
gesetzt.

OK?

Der Compiler macht dann daraus erstaunlicherweise genau das richtige
;-)

von Dietmar (Gast)


Lesenswert?

Der Umstieg auf RealView steht mir auch noch bevor :-{

Bei mir sieht die Syntax bisher noch ähnlich aus:

const unsigned int Code_Read_Protection __at 0x1FC = 0x87654321;

Alternativ kann man die Konstantendefinition auch in der Startup.s
unterbringen:

Man definiere dort an passender Stelle eine Checkbox für die Bedienung
über den Configuration Wizard, damit man die Code Read Protection
während der Softwareentwicklung auf einfache Weise ein- und ausschalten
kann, denn eingeschaltet verweigert der Keil ULINK JTAG-Adapter nach dem
Flash Download jeglichen Zugriff auf den Controller und damit auch einen
erneuten Flash Download. Wohl dem, der für solche Fälle in seiner
Hardware auf jeden Fall den UART0 für z.B. das Philips Flash Utility
zugänglich gemacht hat.

Hier die Erstellung der Checkbox:

/*
// <e> Flash Code Read Protection On / Off
// </e>
*/
        CODE_PROT_SETUP EQU     0

Je nach Zustand der Checkbox wird dem Symbol CODE_PROT_SETUP dann
automatisch eine 0 oder 1 zugewiesen.

Dann am Ende, vor das END-Label, die Segmentdefinition mit Festlegung
von Speicheradresse und Daten:

// Setup the Flash Code Read Protection:
IF (CODE_PROT_SETUP != 0)

    CODE_PROT_BASE  EQU  0x000001FC   ; Flash Adresse
    CODE_PROT_DATA  EQU  0x87654321   ; Flash Daten

AREA    CODE_PROT, DATA, READONLY, ALIGN=2, AT CODE_PROT_BASE

RSEG    CODE_READ_PROTECT             ; selektiere Segment
        DD      CODE_PROT_DATA        ; Speicherreservierung
ENDIF

Das funktioniert ganz gut.
Allerdings möchte ich nicht versprechen, dass Assemblersyntax zwischen
RealView und z.B. Keil harmoniert.

Gruß

Dietmar

von Dietmar (Gast)


Lesenswert?

Sorry, im letzten Assemblerfile-Schnipsel war noch ein Dreckfuhler (für
den Fall, daß jemand das ausprobieren möchte):


// Setup the Flash Code Read Protection:
IF (CODE_PROT_SETUP != 0)

    CODE_PROT_BASE  EQU  0x000001FC   ; Flash Adresse
    CODE_PROT_DATA  EQU  0x87654321   ; Flash Daten

AREA    CODE_PROT, DATA, READONLY, ALIGN=2, AT CODE_PROT_BASE

RSEG    CODE_PROT                     ; selektiere Segment
        DD      CODE_PROT_DATA        ; Speicherreservierung
ENDIF


Dietmar

von Martin (Gast)


Lesenswert?

Hallo Leute!
Danke.

Danke Dietmar, ich werde das noch versuchen.

Hallo Arm-Fan
Das mit dieser Zeile hat leider nicht funktioniert.

(*(volatile unsigned long *)0x000001FC) = 0x87654321;

Der Kontroller kann von Haus aus nicht ins Flash schreiben.
Es hadelt sich bei 0x1FC um eine Adresse im Flash-Baustein.

Jedes Mal wenn der µC auf diese Zeile trifft, bleibt er
hängen und läuft nicht mehr weiter.

Vielleicht gibt es noch eine andere Möglichkeit.

Gruß, Martin

von Martin (Gast)


Lesenswert?

Hallo Leute!

Ich habe mich etwas rumgehört.
Man muss für die einzelne Konstante ein eigenes Modul erstellen und
dies dann auf die ensprechende Adresse anheben.

Dies geschieht in "Options for Target - On-Chip - IROM2".
Dort kann man nun den neuen Speicher eintragen, so wie es bei mir der
Fall ist 0x1FC und Größe 0x04.

Leider gibt es hier einen kleinen Haken. Das Problem ist nämlich, dass
sich dieser neue Speicherbereich mit dem original überlappt, der
nämlich folgendermaßen angegeben ist:IROM1: 0x000  Größe 0x80000.

Um erste Versuche machen zu können, verkleinerte ich IROM1 und legte
IROM2 hinter IROM1 an.
Danach definierte ich im File "flashprotect.c" eine Kosntante:
uint32_t const f_protect = 0x87654321;

Wählte nun mit der rechten Maustaste dieses File an und aktivierte die
Option "Options for File" unter Memory Assignment wies ich nun den
Constanten das IROM2 zu.

Während des Komplierens erhielt ich folgende tolle Mitteilung:
warning: L6329W: Pattern flashprotect.o(RO) only matches removed unused
sections.

Nun war der Zahlenwert wieder nicht dort wo er hinsollte.

Irgendwie habe ich das Gefühl wie wenn der RealView einwenig schwach
wäre.
Aber schimpfen bringt nichts. Vielleicht hat doch jemand eine einfache
Lösung.


Tschüss, Martin

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.