www.mikrocontroller.net

Forum: Compiler & IDEs pgm_read_byte_far


Autor: neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
guten tag,

ich habe mal eine frage, und zwar benutze ich einen Mega128,habe mehre 
bilddaten im flash ligen alles bis 64K wird korrekt angezeigt aber alles 
über 64K eben nicht,dann habe ich mit pgm_read_byte_far das ganze 
versucht, aber das haut auch nich hin.

meine bilddaten;
#include <avr/pgmspace.h> //WinAVR
prog_uchar 63bmp[]= { //AVR-GCC, WinAVR
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};


mein aufruf;
by=pgm_read_byte_far(bitmap);


vielleicht kann mir jemand bischen weiterhelfen

mfg

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
pgm_read_byte_far() braucht eine 32-bit-Zahl als Adresse.  Zeiger
sind im AVR-GCC aber nur 16 bit groß.

Autor: neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
in Assembler ist das ganze eigendlich ganz einfach
ldi ZL, byte3(2*63bmp)
out rampz,ZLldi ZL, low(2*63bmp)
ldi ZH, high(2*63bmp)
elpm WL, Z+
das Funktioniert herforragend von 0-128K beim Mega128
warum ist das in AVR-GCC so schwierig
vielleicht könnt mir da jemand ein stück weiterhelfen


mfg

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab dazu ein Macro, welches einen 32 Bit-Pointer (bzw. 24 Bit) für 
Memory-Adressen oberhalb 64 kByte liefert:
//======================================================================
// Macro to access strings defined in PROGMEM above 64kB
//----------------------------------------------------------------------
#define FAR(var)                     \
({ uint_farptr_t tmp;                \
   __asm__ __volatile__(             \
       "ldi    %A0, lo8(%1)"  "\n\t" \
       "ldi    %B0, hi8(%1)"  "\n\t" \
       "ldi    %C0, hh8(%1)"  "\n\t" \
       "clr    %D0"           "\n\t" \
       : "=d" (tmp)                  \
       : "p"  (&(var)));             \
   tmp;                              \
})
//----------------------------------------------------------------------

Dann gehts einfach so:
by=pgm_read_byte_far(FAR(bitmap));

Ich verstehe nicht, wieso die AvrLib-C kein eintsprechendes Macro im 
pgmspaceModul enthält. Es existieren zwar "far"-Funktionen die einen 32 
Bit Pointer erwarten, aber eben kein FAR-Macro, welches diesen Pointer 
liefert.

Vermutlich könnte man das Macro z.B. direct in die pgm_read_far Funktion 
integrieren, so dass man der Funktion bloss den 16-Bit Pointer mitgeben 
müsste...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> Ich verstehe nicht, wieso die AvrLib-C kein eintsprechendes Macro im
> pgmspaceModul enthält.

Weil du es noch nicht als Patch eingereicht hast?

(Bitte nicht vergessen, dafür doxygen-Dokumentation mit zu liefern.
Sonst benutzt den Makro keiner, weil ihn keiner kennt.)

https://savannah.nongnu.org/patch/?group=avr-libc

Autor: neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so ich habs in der pgmspace.h eingefügt nun kommt allerdings 3x der 
Fehler
undeundefined reference t 'r30'
undeundefined reference t 'r30'
undeundefined reference t 'r30'


vielleicht könnte mir wer sagen was ich falsch mache

mfg

Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm. So wie ich das sehe, wird ein Pointer beim Zugriff aufs Flash 
ohnehin zu einem uin16_t bzw. uint32_t gecasted. Da stellt sich für mich 
schon die Frage, ob man 32-Bit-Pointer in gcc-avr einführen sollte, nur 
um sie anschließend wieder auf uint32_t zu casten. Sonst wird doch 
nirgendwo ein 32-Bit-Poiter benötigt, noch ist das SRAM ja nicht so 
groß, ;)

Gruß, DetlevT

Autor: neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mit dem Macro bekomme ich mein Quelltext nicht Compilliert da er mir 
immer den Fehler 3x ausgibt,
undefined reference t 'r30'
das einzigste was funktioniert ist halt dies,
by=pgm_read_byte_far(   0x10000UL +  (uint32_t) (uint16_t) bitmap);
schade das es keine funktion gibt wo ich den gesamten Flash lesen kann

mfg

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nach den Backslashs "\" muss direkt eine neue Zelie (Newline) folgen, 
kein Leerschlag, Tab oder Kommentar. Vielleicht liegts daran?

Autor: neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,
wiegesagt habe das Macro in pgmspace.h eingefügt so wie es weiter oben 
gepostet ist
und dazu dann der aufruf  by=pgm_read_byte_far(FAR(bitmap));
es kommt dann immer der Fehler mit undefined reference to 'r30'
Schade das das nicht funktioniert,
oder mach ich da was verkehrt

mfg

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
neuling schrieb:
> mach ich da was verkehrt

Gib mal den Code, den du wirklich compilieren willst.  Ich wollte
gerade dein Beispiel von ganz oben testen, aber das ist offensichtlich
nicht per copy&paste aus deinem Editor, denn "63bmp" ist zwar
vielleicht ein gültiger Domainname im Internet, aber es ist kein
gültiger Bezeichner in der Sprache C.

p.s.: Bitte markiere den C-Code als solchen.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich hab hier mal ein Beispiel mit dem aktuellen WinAVR erzeugt, das 
lässt sich ohne Fehler oder Warning compilieren (AtMega128)
#include <avr/io.h>
#include <avr/pgmspace.h>

//====================================================================
// Macro to access strings defined in PROGMEM above 64kB
//--------------------------------------------------------------------
#define FAR(var)                     \
({ uint_farptr_t tmp;                \
   __asm__ __volatile__(             \
       "ldi    %A0, lo8(%1)"  "\n\t" \
       "ldi    %B0, hi8(%1)"  "\n\t" \
       "ldi    %C0, hh8(%1)"  "\n\t" \
       "clr    %D0"           "\n\t" \
       : "=d" (tmp)                  \
       : "p"  (&(var)));             \
   tmp;                              \
})
//-------------------------------------------------------------------

//===================================================================
// Define a section above 64kB (FAR_SECTION)
// and add the required linker argument below
// -Wl,--section-start=.far_section=0x10000
//--------------------------------------------------------------------
#define FAR_SECTION   __attribute__((section(".far_section")))
//--------------------------------------------------------------------

//====================================================================
// Just a Sample
//--------------------------------------------------------------------

char MyBitmap[] FAR_SECTION = "Hier liegt mein Teststring!";
char bmp64[]    FAR_SECTION = {0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x00};

int main(void)
{
  char MyChar;
  DDRC = 0xFF;
  do
  {
    MyChar = pgm_read_byte_far(FAR(MyBitmap));
    PORTC  = MyChar;
  }
  while(MyChar);
}

Built Log:
Create eeprom image (ihex format)
avr-objcopy -j .eeprom --no-change-warnings --change-section-lma .eeprom=0 -O ihex Test.elf  "Test.eep"
Finished building: Test.eep
 
Invoking: Print Size
avr-size --format=avr --mcu=atmega128 Test.elf
AVR Memory Usage
----------------
Device: atmega128

Program:     236 bytes (0.2% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)

Finished building: sizedummy

Wenn ich mir die dabei erzeugten LSS- und HEX-Files angucke, so sehe ich 
dass alles richtig rauskommt..

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ups, ich hatte da nicht das ganze Buit-Log erwischt! ;o)
**** Build of configuration Release for project Test ****

make all 
Building file: ../main.c
Invoking: AVR Compiler
avr-gcc -Wall -O1 -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega128 -DF_CPU=14745600UL -MMD -MP -MF"main.d" -MT"main.d" -c -o"main.o" "../main.c"
Finished building: ../main.c
 
Building target: Test.elf
Invoking: AVR C Linker
avr-gcc -Wl,-Map,Test.map -Wl,--section-start=.far_section=0x10000 -mmcu=atmega128 -o"Test.elf"  ./main.o   
Finished building target: Test.elf
 
Invoking: AVR Create Extended Listing
avr-objdump -h -S Test.elf  >"Test.lss"
Finished building: Test.lss
 
Create Flash image (ihex format)
avr-objcopy -R .eeprom -O ihex Test.elf  "Test.hex"
Finished building: Test.hex
 
Create eeprom image (ihex format)
avr-objcopy -j .eeprom --no-change-warnings --change-section-lma .eeprom=0 -O ihex Test.elf  "Test.eep"
Finished building: Test.eep
 
Invoking: Print Size
avr-size --format=avr --mcu=atmega128 Test.elf
AVR Memory Usage
----------------
Device: atmega128

Program:     236 bytes (0.2% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)

Finished building: sizedummy

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Macro kann mann sogar die Zeile mit dem [clr  %D0"  "\n\t" \] 
weglassen, das 4. Adressbeyte wird ja nicht benötigt. => Spart 2 Bytes 
und einen CPU-Zyklus pro Aufruf.
#include <avr/io.h>
#include <avr/pgmspace.h>

//====================================================================
// Macro to access strings defined in PROGMEM above 64kB
//--------------------------------------------------------------------
#define FAR(var)                     \
({ uint_farptr_t tmp;                \
   __asm__ __volatile__(             \
       "ldi    %A0, lo8(%1)"  "\n\t" \
       "ldi    %B0, hi8(%1)"  "\n\t" \
       "ldi    %C0, hh8(%1)"  "\n\t" \
       : "=d" (tmp)                  \
       : "p"  (&(var)));             \
   tmp;                              \
})
//-------------------------------------------------------------------

//===================================================================
// Define a section above 64kB (FAR_SECTION)
// and add the required linker argument below
// -Wl,--section-start=.far_section=0x10000
//--------------------------------------------------------------------
#define FAR_SECTION   __attribute__((section(".far_section")))
//--------------------------------------------------------------------

//====================================================================
// Just a Sample
//--------------------------------------------------------------------

char MyString[] FAR_SECTION = "Hier liegt mein FAR-Teststring!";
char MyBmp64[]  FAR_SECTION = {0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x00};

int main(void)
{
  char MyChar;
  DDRC = 0xFF;
  do
  {
    MyChar = pgm_read_byte_far(FAR(MyBmp64));
    PORTC  = MyChar;
  }
  while(MyChar);
}

Autor: Martin R. (martin63)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

die Lösung sieht gut aus, aber wie läßt sich ein Element im FAR-Bereich 
referenzieren? In dem Beispiel gibt's ja immer nur 0xAA zurück. Wie 
komme ich z.B. an 0xDD? mit FAR(&MyBmp64[3]) komme ich nicht weiter wg. 
Lvalue.

Danke!
Martin

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>mit FAR(&MyBmp64[3]) komme ich nicht weiter wg. Lvalue.

Da müsste ich mal bisschen pröbeln, aber eigentlich müsste es zum 
Beispiel folgendermassen klappen:


pgm_read_byte_far(FAR(MyBmp64)+3);

Autor: Martin R. (martin63)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

ja, so mit direkter Pointerarithmetik scheint es zu gehen, hatte ich 
auch schon probiert. Wenn es aber komplexere Tabellen sind, wäre ein 
Indexzugriff sicher besser. Falls also beim "pröpeln" was rauskommen 
sollte, wäre das sicher nicht nur für mich sehr hilfreich.

Nochmal Danke!

Martin

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Martin R.

Mit direkter Indexangabe, die der Compiler auflösen kann, funktioniert 
es folgendermassen: (ohne &)
MyChar = pgm_read_byte_far(FAR(MyBmp64[3]));

Aber leider nicht mit variablem Index:
int n=3;
MyChar = pgm_read_byte_far(FAR(MyBmp64[n]));
=>main.c:(.text+0x32): undefined reference to `r30'
=>main.c:(.text+0x34): undefined reference to `r30'
=>main.c:(.text+0x36): undefined reference to `r30'

Da muss man sich offenbar mit direkter Pointerarithemetik begnügen:
int n=3;
MyChar = pgm_read_byte_far(FAR(MyBmp64)+n);

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.