Forum: Mikrocontroller und Digitale Elektronik PIC24 Zeiger auf const unsigend char


von Markus Wi, (Gast)


Lesenswert?

Hallo zusammen,

ich verwende den PIC24. Nun möchte ich eine konstante Variable an einen 
bestimmten Speicherplatz im Flash setzen. Dies mache ich mit:

const unsigned char Variable __attribute__((address(0x800))) = 123;

ich denke das funktioniert sowei. Zumindest zeigt er mir im Mapping eine 
Variable an der Adresse 0x800 an.

Nun möchte ich diesen Wert im Programm in eine normale unsigned char 
Variable einlesen. Also etwa so:

unsigned char* const xxx = 0x800;
unsigned char yyy = (unsigned char)*xxx;

Leider hat die Variable yyy hinterher nicht den Wert 123. Was mache ich 
falsch?

Das Ganze ist für einen Bootloader. Im Bootloader möchte ich die 
Bootloaderversion an eine bestimmte Adresse speichern, sodass ich im 
Hauptprogramm die Version auslesen kann.

Vielen Dank!
Markus

von Karl H. (kbuchegg)


Lesenswert?

Was passiert, wenn du die Schreibweise mit der Adressvergabe in deinem 
Anwendungsprogram duplizierst?
1
unsigned char xxx __attribute__((address(0x800)));
2
unsigned char yyy = yyy;

von Karl H. (kbuchegg)


Lesenswert?

Markus Wi, schrieb:

> const unsigned char Variable __attribute__((address(0x800))) = 123;
>
> ich denke das funktioniert sowei. Zumindest zeigt er mir im Mapping eine
> Variable an der Adresse 0x800 an.


Ich denke, das solltest du erst mal verifizieren.
Ich würde das nicht mit einem Mapping kontrollieren, sondern ganz 
konkret den Bootloader (aus dem ja dieses Stück Code stammt) in den 
Flash brennen und dann mit einem Speicher-Dump Programm im Speicher 
nachsehen, ob an der bewussten Stelle im Flash tatsächlich 123 zu finden 
ist.

Kontrolle auf tiefster Ebene ist immer gut.

von Markus Wi, (Gast)


Lesenswert?

Danke für die Antwort!

Ich habe es jetzt so probiert:

Bootloader:
const unsigned char Variable __attribute__((address(0x800))) = 123;

Anwendungsprogramm:
const unsigned char xxx __attribute__((address(0x800)));

unsigned char yyy = (unsigned char)xxx;
if (yyy == 123) while(1);

Leider immer noch das gleiche: yyy = 0.



Karl Heinz schrieb:
> Ich denke, das solltest du erst mal verifizieren.
> Ich würde das nicht mit einem Mapping kontrollieren, sondern ganz
> konkret den Bootloader (aus dem ja dieses Stück Code stammt) in den
> Flash brennen und dann mit einem Speicher-Dump Programm im Speicher
> nachsehen, ob an der bewussten Stelle im Flash tatsächlich 123 zu finden
> ist.

Das wollte ich verifizieren. Allerdings habe ich keine Ahnung wie das 
geht. Deshalb "nun" über daas Mapping. Ich habe MPLABX und ein ICD3 
hier. Kann man im MPLABX irgendwie den Speicher wieder auslesen? Oder 
kann man es über das Hexfile machen? Allerdings weis ich auch hier nicht 
wie ich die Adresse 0x800 im Hex-File finde.

von Arc N. (arc)


Lesenswert?

Markus Wi, schrieb:
> const unsigned char Variable __attribute__((address(0x800))) = 123;
> Nun möchte ich diesen Wert im Programm in eine normale unsigned char
> Variable einlesen. Also etwa so:
>
> unsigned char* const xxx = 0x800;
> unsigned char yyy = (unsigned char)*xxx;

Entweder ich bin noch nicht ganz wach oder das eine passt u.U. nicht zum 
anderen...
Zeiger auf eine Konstante:
const unsigned char * ptr2const;
Konstanter Zeiger:
unsigned char * const constPtr;

von Markus Wi, (Gast)


Lesenswert?

Arc Net schrieb:
> Entweder ich bin noch nicht ganz wach oder das eine passt u.U. nicht zum
> anderen...
> Zeiger auf eine Konstante:
> const unsigned char * ptr2const;
> Konstanter Zeiger:
> unsigned char * const constPtr;

Daran habe ich auch schon gedacht. Habe bereits beide Varianten 
ausprobiert.

von Bronco (Gast)


Lesenswert?

Der PIC24 hat eine Harvard-Arhcitektur, d.h. Du hast unterschiedliche 
Adressräume für RAM und Flash.
Der PIC24 hat zwei Möglichkeiten, um aus dem Flash zu lesen:
1. Durch Einlenden eines bestimmten Flash-Fensters im RAM-Adressraum. 
Dieses Fenster wird i.a.R. automatisch vom Compiler verwaltet.
2. Über die "TBLRD"-Befehle.

Schau mal in Dein Compiler-Handbuch, da gibt es Intrinsic-Befehle zum 
Lesen aus dem Flash (hab leider gerade keine Doku da).

Ich hab in meinem Code da folgendes drinn:
1
uint32_t FlashReadSingleWord(uint32_t addr_u32) 
2
{
3
  asm("    push      TBLPAG      ");
4
  asm("     mov      W1,TBLPAG   ");
5
  asm("     tblrdh   [W0],W1     ");       
6
  asm("     tblrdl   [W0],W0     ");
7
  asm("    pop       TBLPAG      ");    
8
}

von Markus Wi, (Gast)


Lesenswert?

Also, ich habe herausgefunden, wie man mit MPLABX den PIC ausliest und 
den Speicher anzeigt.

const unsigned char Variable __attribute__((address(0x800))) = 123;

funktioniert. An der Speicherstelle 0x800 im Flash finde ich den Wert 
0x7B was ja dem dezimalen Wert 123 entspricht.

Also liegt das Problem am Auslesen des Wertes aus dem Flash.

von morph1 (Gast)


Lesenswert?

Ja, lies dich mal in das Thema "program space visibility (PSV)" ein, 
dann wirst du erkennen wo das Problem liegt :)

Der PIC kann nur einen Teil vom RAM-Adressraum ins FLASH mappen, darum 
sollte man das tunlichst dem Compiler überlassen wo er seine Konstanten 
hinlegt!

Ich mach das bei meinen Bootloader zwar ähnlich wie du was das ablegen 
der Konstanten betrifft, auslesen tu ichs aber wie schon über mir 
beschrieben über die "TBLRD"-Befehle.

von Markus Wi, (Gast)


Lesenswert?

Super!!! Vielen, vielen Dank!!! So funktioniert es jetzt!!!

Folgenden Code habe ich jetzt verwendet:

unsigned long FlashReadSingleWord(unsigned long addr_u32)
{
  asm("    push      TBLPAG      ");
  asm("     mov      W1,TBLPAG   ");
  asm("     tblrdh   [W0],W1     ");
  asm("     tblrdl   [W0],W0     ");
  asm("    pop       TBLPAG      ");
}

unsigned long yyy = FlashReadSingleWord(0x800);
unsigned char xxx = (unsigned char)yyy;

Ich werde mich jetzt noch einlesen, was da genau passiert, aber ich bin 
schon mal ein ganzes Stück weiter!

von Markus Wi, (Gast)


Lesenswert?

Beim Compilieren bekomme ich jetzt noch folgende Fehlermeldung:

warning: control reaches end of non-void function

klar, der Compiler vermisst das return in der Funktion. Kann man das 
irgendwie lokal ausschalten? Das stört mich ein wenig.

von Bronco (Gast)


Lesenswert?

Markus Wi, schrieb:
> klar, der Compiler vermisst das return in der Funktion. Kann man das
> irgendwie lokal ausschalten? Das stört mich ein wenig.

Also zumindest beim C30 (jetzt X16) hab ich das auch schon gesucht und 
nicht herausgefunden.
Aber schau dir mal die Intrinsic-Funktionen an, vielleicht gibt's da was 
besseres...

von Frank (Gast)


Lesenswert?

Markus Wi, schrieb:
> lokal ausschalten? Das stört mich ein wenig

Das return muß rein in die Funktion.

Dazu definierst Du eine Variable, ungeähr so, hab jetzt keine lust das 
in MPLab zu testen:


unsigned int FlashReadSingleWord(unsigned long addr_u32)
{
  unsigned int flash_word
  asm("    push      TBLPAG      ");
  asm("     mov      W1,TBLPAG   ");
  asm("     tblrdh   [W0],W1     ");
  asm("     tblrdl   [W0],W0     ");
  asm("    mov       W0, flash_word      ");
  asm("    pop       TBLPAG      ");
  return flash_word
}

Kann man auch auf long erweitern mit union

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.