Forum: Mikrocontroller und Digitale Elektronik Warnung bei Benutzung von "strncmp_PF"?


von AVRli (Gast)


Lesenswert?

Hallo,

ich nutze den PROGMEM zur Ablage von Zeichenketten, welche über den UART 
verarbeitet werden. Das nun im oberen Bereich eines ATmega 2560.

Die normalen Routinen wie strncmp_P funktionieren dort ja nicht mehr 
wegen der 64k Beschränkung. Nun bekomme ich aber Warnungen das die Typen 
nicht zusammenpassen.
1
...
2
const char pgm_cmd_run[] PROGMEM = "run";
3
...
4
5
//--- run ------------------------------------------------------
6
if (!strncmp_PF(buf_uart_read, (uint_farptr_t)(pgm_cmd_run), 3)) {
7
     ...
8
     ...am liebsten Kaffee trinken...
9
     ...
10
}

Erzeugt bei mir die Warnung:
Warning: cast from pointer to integer of different size 
[-Wpointer-to-int-cast]

Ich könnte die Warnungen an dieser Stelle vlt. ignorieren aber ich lebe 
ruhiger wenn erst gar keine kommen. Deshalb die Frage was genau wird 
beanstandet und wie schafft man da Abhilfe?

Grüße AVRli...

von Tom (Gast)


Lesenswert?

Hilft es pgm_cmd_run mit PROGMEM_FAR zu attributieren?

von Harry L. (mysth)


Lesenswert?

Irre ich mich, oder muß das nicht so aussehen?
1
if (!strncmp_PF(buf_uart_read, (uint_farptr_t)(&pgm_cmd_run), 3)) {

von Stefan E. (sternst)


Lesenswert?

AVRli schrieb:
> Ich könnte die Warnungen an dieser Stelle vlt. ignorieren

Nein, kannst du nicht, denn es wird so auch nicht funktionieren, wenn 
pgm_cmd_run jenseits der 64k liegt.

1
if (!strncmp_PF(buf_uart_read,  pgm_get_far_address(pgm_cmd_run), 3)) {

: Bearbeitet durch User
von AVRli .. (avrli)


Lesenswert?

Stefan E. schrieb:
> Nein, kannst du nicht, denn es wird so auch nicht funktionieren, wenn
> pgm_cmd_run jenseits der 64k liegt.

Das wird der Fall sein, also das pgm_cmd_run eben noch nicht außerhalb 
der 64k liegt. :-( Dann hätte es irgenwann geknallt und man wundert sich 
warum. Also vielen Dank für!

> if (!strncmp_PF(buf_uart_read,  pgm_get_far_address(pgm_cmd_run), 3)) {

Denn das funktioniert und es kommen auch keine WARNUNGEN mehr. :-)

Gibt es da auch einen Typen wie PGM_P ?
Wie übergibt man denn nun die ermittelte far_address an eine eigene 
Funktion?

An die Anderen auch ein Dankeschön, PGM_FAR wird hier nicht erkannt und 
das & davor hat nichts geändert.


Grüße AVRli...

von AVRli .. (avrli)


Lesenswert?

Für alle die genauso gesucht haben...

uint_farptr_t

ist als Pointer Variable festgelegt...

Grüße AVRli...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

AVRli .. schrieb:
> Stefan E. schrieb:
>> Nein, kannst du nicht, denn es wird so auch nicht funktionieren, wenn
>> pgm_cmd_run jenseits der 64k liegt.
>
> Das wird der Fall sein, also das pgm_cmd_run eben noch nicht außerhalb
> der 64k liegt. :-( Dann hätte es irgenwann geknallt und man wundert sich
> warum. Also vielen Dank für!
>
>> if (!strncmp_PF(buf_uart_read,  pgm_get_far_address(pgm_cmd_run), 3)) {
>
> Denn das funktioniert und es kommen auch keine WARNUNGEN mehr. :-)

Das Problem ist nur: Wenn Du pgm_cmd_run definierst als

AVRli schrieb:
> const char pgm_cmd_run[] PROGMEM = "run";

Dann liegt das Objekt in den unteren 64KiB, und das ganze far Zeug 
macht's nur aufwendiger, weil ein einfaches strncmp_P (..., 
&pgm_cmd_run) genügen würde.

Neuere Versionen der Toolchain unterstützen __memx und lokatieren dies 
nach .progmemx.data, das an einer höheren Flash-Adresse lokatiert wird 
um nicht untere 64KiB zu verschwenden.  Hier zB ein Auszug aus dem 
default ld-Script für avr6:
1
...
2
SECTIONS
3
{
4
  ...
5
  /* Internal text space or external memory.  */
6
  .text   :
7
  {
8
    *(.vectors)
9
    KEEP(*(.vectors))
10
    /* For data that needs to reside in the lower 64k of progmem.  */
11
     *(.progmem.gcc*)
12
    /* PR 13812: Placing the trampolines here gives a better chance
13
       that they will be in range of the code that uses them.  */
14
    . = ALIGN(2);
15
     __trampolines_start = . ;
16
    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
17
    *(.trampolines)
18
     *(.trampolines*)
19
     __trampolines_end = . ;
20
    /* avr-libc expects these data to reside in lower 64K. */
21
     *libprintf_flt.a:*(.progmem.data)
22
     *libc.a:*(.progmem.data)
23
     *(.progmem.*)
24
25
    ...
26
27
    *(.text)
28
29
    ...
30
31
     *(.progmemx.*)
32
33
    ...
34
35
    /* For tablejump instruction arrays.  We don't relax
36
       JMP / CALL instructions within these sections.  */
37
    *(.jumptables)
38
     *(.jumptables*)
39
     _etext = . ;
40
  }  > text
41
42
  ...
43
}

__memx liefert 24-Bit Adressen

Beispiel:
1
// $ avr-gcc-7 -mmcu=avr6 -Os -save-temps -fverbose-asm ...
2
3
#include <avr/pgmspace.h>
4
5
const __memx char str_run[] = "run";
6
7
int testrun1 (void)
8
{
9
    return strncmp_PF ("text1", (__uint24) &str_run, 3);
10
}
11
12
int testrun2 (void)
13
{
14
    return strncmp_PF ("text1", pgm_get_far_address (str_run), 3);
15
}
1
testrun1:
2
 ;  main.c:7:     return strncmp_PF ("text1", (__uint24) &str_run, 3);
3
  ldi r24,lo8(str_run)   ;  tmp45,
4
  ldi r25,hi8(str_run)
5
  ldi r26,hlo8(str_run)
6
  ldi r18,lo8(3)
7
  ldi r19,0
8
  movw r20,r24   ; , tmp45
9
  mov r22,r26
10
  ldi r23,0
11
  ldi r24,lo8(.LC0)
12
  ldi r25,hi8(.LC0)
13
  jmp strncmp_PF
14
15
16
testrun2:
17
 ;  main.c:12:     return strncmp_PF ("text1", pgm_get_far_address (str_run), 3);
18
/* #APP */
19
  ldi  r20, lo8(str_run)   ;  tmp,
20
  ldi  r21, hi8(str_run)   ;  tmp,
21
  ldi  r22, hh8(str_run)   ;  tmp,
22
  clr  r23   ;  tmp
23
 ;  main.c:12:     return strncmp_PF ("text1", pgm_get_far_address (str_run), 3);
24
/* #NOAPP */
25
  ldi r18,lo8(3)
26
  ldi r19,0
27
  ldi r24,lo8(.LC0)
28
  ldi r25,hi8(.LC0)
29
  jmp strncmp_PF
30
31
.section  .rodata.str1.1,"aMS",@progbits,1
32
.LC0:
33
  .string  "text1"

von Stefan E. (sternst)


Lesenswert?

Johann L. schrieb:
> Das Problem ist nur: Wenn Du pgm_cmd_run definierst als
>
> AVRli schrieb:
>> const char pgm_cmd_run[] PROGMEM = "run";
>
> Dann liegt das Objekt in den unteren 64KiB,

Aber nicht garantiert immer. Nämlich dann nicht, wenn
A) man so viel PROGMEN-Zeug anhäuft, dass es über die 64Ki hinaus 
wächst,
oder
B) man einen Bootloader schreibt.

Ich hatte sein
> Das nun im oberen Bereich eines ATmega 2560.
so interpretiert, dass eines von beiden bei ihm zutrifft.

Ich hoffe mal, er ist nicht in dem Irrglauben, dass er die far-Varianten 
auch dann braucht, wenn zwar nicht die Daten, aber der zugreifende Code 
jenseits der 64Ki liegt.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stefan E. schrieb:
> Johann L. schrieb:
>> Das Problem ist nur: Wenn Du pgm_cmd_run definierst als
>>
>> AVRli schrieb:
>>> const char pgm_cmd_run[] PROGMEM = "run";
>>
>> Dann liegt das Objekt in den unteren 64KiB,
>
> Aber nicht garantiert immer. Nämlich dann nicht, wenn
> A) man so viel PROGMEN-Zeug anhäuft, dass es über die 64Ki hinaus
> wächst,

Selbst dann kann es in den unteren 64k liegen, aber andere Objekte dann 
(teilweise) nicht mehr.  Um Kontrolle darüber zu haben, welche Objekte 
wo liegen, reicht ein PROGMEM hier nicht aus.  Entweder muss man dann 
entsprechende Objekte im ld-Skript händisch lokatieren, oder man nutzt 
eben bereits vorhandene Sections wie .progmemx.data, evtl. auch via 
section-Attribut.

Und schließlich gibt's noch die expliziten Flash-Seiten wie __flash1 bis 
(bei ATmega256x) __flash3.  Hier braucht's dann aber ein eigenes 
ld-Script, dass .text und .progmem1.data etc. anordnet wie gewünscht. 
Unterstützung im default ld-Script gibt's dafür nicht, weil es keine 
kanonisches Lokatierung gibt.

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.