pgm_read_byte_far

Gast #1860572
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
Gast #1861653
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
Gast #1863019
Lesenswert?

Ich hab dazu ein Macro, welches einen 32 Bit-Pointer (bzw. 24 Bit) für 
Memory-Adressen oberhalb 64 kByte liefert:
1
//======================================================================
2
// Macro to access strings defined in PROGMEM above 64kB
3
//----------------------------------------------------------------------
4
#define FAR(var)                     \
5
({ uint_farptr_t tmp;                \
6
   __asm__ __volatile__(             \
7
       "ldi    %A0, lo8(%1)"  "\n\t" \
8
       "ldi    %B0, hi8(%1)"  "\n\t" \
9
       "ldi    %C0, hh8(%1)"  "\n\t" \
10
       "clr    %D0"           "\n\t" \
11
       : "=d" (tmp)                  \
12
       : "p"  (&(var)));             \
13
   tmp;                              \
14
})
15
//----------------------------------------------------------------------

Dann gehts einfach so:
1
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...
Gast #1863257
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
#1863289
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
Gast #1863437
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
Gast #1864312
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
Moderator Persönliche Seite #1864392
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.
Gast #1864491
Lesenswert?

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

4
//====================================================================
5
// Macro to access strings defined in PROGMEM above 64kB
6
//--------------------------------------------------------------------
7
#define FAR(var)                     \
8
({ uint_farptr_t tmp;                \
9
   __asm__ __volatile__(             \
10
       "ldi    %A0, lo8(%1)"  "\n\t" \
11
       "ldi    %B0, hi8(%1)"  "\n\t" \
12
       "ldi    %C0, hh8(%1)"  "\n\t" \
13
       "clr    %D0"           "\n\t" \
14
       : "=d" (tmp)                  \
15
       : "p"  (&(var)));             \
16
   tmp;                              \
17
})
18
//-------------------------------------------------------------------
19

20
//===================================================================
21
// Define a section above 64kB (FAR_SECTION)
22
// and add the required linker argument below
23
// -Wl,--section-start=.far_section=0x10000
24
//--------------------------------------------------------------------
25
#define FAR_SECTION   __attribute__((section(".far_section")))
26
//--------------------------------------------------------------------
27

28
//====================================================================
29
// Just a Sample
30
//--------------------------------------------------------------------
31

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

35
int main(void)
36
{
37
  char MyChar;
38
  DDRC = 0xFF;
39
  do
40
  {
41
    MyChar = pgm_read_byte_far(FAR(MyBitmap));
42
    PORTC  = MyChar;
43
  }
44
  while(MyChar);
45
}

Built Log:
1
Create eeprom image (ihex format)
2
avr-objcopy -j .eeprom --no-change-warnings --change-section-lma .eeprom=0 -O ihex Test.elf  "Test.eep"
3
Finished building: Test.eep
4
 
5
Invoking: Print Size
6
avr-size --format=avr --mcu=atmega128 Test.elf
7
AVR Memory Usage
8
----------------
9
Device: atmega128
10

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

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

17
Finished building: sizedummy

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

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

3
make all 
4
Building file: ../main.c
5
Invoking: AVR Compiler
6
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"
7
Finished building: ../main.c
8
 
9
Building target: Test.elf
10
Invoking: AVR C Linker
11
avr-gcc -Wl,-Map,Test.map -Wl,--section-start=.far_section=0x10000 -mmcu=atmega128 -o"Test.elf"  ./main.o   
12
Finished building target: Test.elf
13
 
14
Invoking: AVR Create Extended Listing
15
avr-objdump -h -S Test.elf  >"Test.lss"
16
Finished building: Test.lss
17
 
18
Create Flash image (ihex format)
19
avr-objcopy -R .eeprom -O ihex Test.elf  "Test.hex"
20
Finished building: Test.hex
21
 
22
Create eeprom image (ihex format)
23
avr-objcopy -j .eeprom --no-change-warnings --change-section-lma .eeprom=0 -O ihex Test.elf  "Test.eep"
24
Finished building: Test.eep
25
 
26
Invoking: Print Size
27
avr-size --format=avr --mcu=atmega128 Test.elf
28
AVR Memory Usage
29
----------------
30
Device: atmega128
31

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

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

38
Finished building: sizedummy
Gast #1864526
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.
1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3

4
//====================================================================
5
// Macro to access strings defined in PROGMEM above 64kB
6
//--------------------------------------------------------------------
7
#define FAR(var)                     \
8
({ uint_farptr_t tmp;                \
9
   __asm__ __volatile__(             \
10
       "ldi    %A0, lo8(%1)"  "\n\t" \
11
       "ldi    %B0, hi8(%1)"  "\n\t" \
12
       "ldi    %C0, hh8(%1)"  "\n\t" \
13
       : "=d" (tmp)                  \
14
       : "p"  (&(var)));             \
15
   tmp;                              \
16
})
17
//-------------------------------------------------------------------
18

19
//===================================================================
20
// Define a section above 64kB (FAR_SECTION)
21
// and add the required linker argument below
22
// -Wl,--section-start=.far_section=0x10000
23
//--------------------------------------------------------------------
24
#define FAR_SECTION   __attribute__((section(".far_section")))
25
//--------------------------------------------------------------------
26

27
//====================================================================
28
// Just a Sample
29
//--------------------------------------------------------------------
30

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

34
int main(void)
35
{
36
  char MyChar;
37
  DDRC = 0xFF;
38
  do
39
  {
40
    MyChar = pgm_read_byte_far(FAR(MyBmp64));
41
    PORTC  = MyChar;
42
  }
43
  while(MyChar);
44
}
#1871178
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
Gast #1874009
Lesenswert?

@Martin R.

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

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

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren