PIC24 Zeiger auf const unsigend char

Gast #3655410
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
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.
Gast
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.
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;
Gast
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.
Gast
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
}
Gast
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.
Gast
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.
Gast
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!
Gast
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.
Gast
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...
Gast
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

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 12 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.