GCC - Länge eines Const Array in ein anderes bringen

Gast #4660906
Lesenswert?

Ich habe hier ein "Problem", welches eigentlich aus Faulheit aufgekommen 
ist. :-D

Ich habe ein Const Array (Ein HID Desc.) von welchem ich die Länge 
brauche:

1
  static const uint8_t PROGMEM rep_desc[] =
2
  {
3
    0x05, 0x01,                    
4
    0x09, 0x05,                    
5
    0xa1, 0x01,                    
6
    0x05, 0x09,                    
7
    0x19, 0x01,                    
8
    0x29, 0x06,                    
9
    0x15, 0x00,                    
10
    0x25, 0x01,                    
11
    0x95, 0x06,                   
12
    0x75, 0x01,                    
13
    0x81, 0x02,                    
14
    0x95, 0x01,                    
15
    0x75, 0x02,                  
16
    0x81, 0x03,                   
17
    0xc0
18
  };

Nun muss (möchte) ich die länge des Arrays in ein anderes, 
gleichartiges, Array bringen. Normalerweise mach ich das ja mit 
sizeof(). Jeoch meckert er dann rum, das sizeof() dann nicht 'const' ist 
- Logischerweise. Wie kann ich das umgehen? Momentan bleibt mir nichts 
weiter übrig und zähle die Werte per Hand und schreibe sie dann in das 
andere Array... aber wenn ich hier nun hundertmal rumteste, ist das 
wirklich nervig!

Danke für eure Hilfe.

p.s. So in etwa meine ich das, das geht ja nun nicht:

1
  static const uint8_t PROGMEM dev_desc[] =
2
  {
3
    0x09,0x21,        
4
    0x11,0x01,   
5
    0x00,0x01,        
6
    0x22,sizeof(rep_des)
7
  };
(Firma: fritzler-avr.de) #4660919
Lesenswert?

In eine Variable schreiben und den Pointer auf diese in das Array?

Lustigerweise meckert der GCC bei mir bei was ähnlichem nicht rum:
1
struct dispwert {  
2
  char uschrift[50];
3
  unsigned short adress;
4
  //Floatingpointanzeigen Formatangaben (müssen auf 6 Zeichen passen!)
5
  unsigned after; //Ziffern nach dem Komma
6
  float divider; //zB um kWh statt Wh anzuzeigen
7
};
8

9
//Array aus structs was angezeigt werden soll
10
struct dispwert anzeigeelemente[] = {
11
  {"P L3 MAX kw", P_L3_MAX, 3, 1000.0},
12
  {"U L3N", U_L3N, 2, 1.0},
13
  {"P GES kw", P_GES, 3, 1000.0}
14
};
15

16
//Länge des dynamischen Array herausfinden
17
const unsigned elements_anzeigeelemente = sizeof(anzeigeelemente)/sizeof(struct dispwert);
Moderator Persönliche Seite #4660928
Lesenswert?

Draco schrieb:
> p.s. So in etwa meine ich das, das geht ja nun nicht:
>
>   static const uint8_t PROGMEM dev_desc[] =
>   {
>     0x09,0x21,
>     0x11,0x01,
>     0x00,0x01,
>     0x22,sizeof(rep_des)
>   };

Doch, geht - wenn man vom fehlenden "c" beim Ausdruck "sizeof(rep_des)" 
absieht:

$ cat s.c
1
#include <stdint.h>
2
#define PROGMEM
3

4
  static const uint8_t PROGMEM rep_desc[] =
5
  {
6
    0x05, 0x01,
7
    0x09, 0x05,
8
    0xa1, 0x01,
9
    0x05, 0x09,
10
    0x19, 0x01,
11
    0x29, 0x06,
12
    0x15, 0x00,
13
    0x25, 0x01,
14
    0x95, 0x06,
15
    0x75, 0x01,
16
    0x81, 0x02,
17
    0x95, 0x01,
18
    0x75, 0x02,
19
    0x81, 0x03,
20
    0xc0
21
  };
22

23

24
  static const uint8_t PROGMEM dev_desc[] =
25
  {
26
    0x09,0x21,
27
    0x11,0x01,
28
    0x00,0x01,
29
    0x22,sizeof(rep_desc)
30
  };
$ gcc -c s.c
$ (keine Meldung)

Dein Problem muss woanders stecken - jedenfalls nicht in dem hier 
beschriebenen Text.
#4660936
Lesenswert?

Nimm den Präprozessor zur Hilfe:
1
#define REP_DESC { 0x05, 0x01, ..., 0xc0 }
2

3
static const uint8_t PROGMEM rep_desc[] = REP_DESC;
4

5
static const uint8_t PROGMEM dev_desc[] =
6
  {
7
    0x09,0x21,
8
    0x11,0x01,
9
    0x00,0x01,
10
    0x22, sizeof((const uint8_t[]) REP_DESC)
11
  };
Gast #4660940
Lesenswert?

Danke für eure Mühe, es lag am Rückgabewert von sizeof... er gibt uint16 
zurück. So gehts dann nun:
1
#include <stdint.h>
2
#define PROGMEM
3

4
#define low(x)   ((x) & 0xFF)
5
#define high(x)  (((x)>>8) & 0xFF)
6

7
  static const uint8_t PROGMEM rep_desc[] =
8
  {
9
    0x05, 0x01,
10
    0x09, 0x05,
11
    0xa1, 0x01,
12
    0x05, 0x09,
13
    0x19, 0x01,
14
    0x29, 0x06,
15
    0x15, 0x00,
16
    0x25, 0x01,
17
    0x95, 0x06,
18
    0x75, 0x01,
19
    0x81, 0x02,
20
    0x95, 0x01,
21
    0x75, 0x02,
22
    0x81, 0x03,
23
    0xc0
24
  };
25

26

27
  static const uint8_t PROGMEM dev_desc[] =
28
  {
29
    0x09,0x21,
30
    0x11,0x01,
31
    0x00,0x01,
32
    0x22,
33
    high(sizeof(rep_desc)),low(sizeof(rep_desc))
34
  };

Warum auch immer er mir da nen "non const" error rausgeworfen hat, keine 
Ahnung.

Aber geht nun... vielen Dank euch :-D
Moderator Persönliche Seite #4660941
Lesenswert?

Dr. Sommer schrieb:
> Kannst du das mal mit dem AVR GCC probieren? vermutlich muss der für
> PROGMEM alle Daten zur Kompile Zeit wissen...
1
#include <avr/pgmspace.h>
2
#include <stdint.h>
3

4
static const uint8_t PROGMEM rep_desc[] =
5
{
6
    0x05, 0x01,
7
    0x09, 0x05,
8
    0xa1, 0x01,
9
    0x05, 0x09,
10
    0x19, 0x01,
11
    0x29, 0x06,
12
    0x15, 0x00,
13
    0x25, 0x01,
14
    0x95, 0x06,
15
    0x75, 0x01,
16
    0x81, 0x02,
17
    0x95, 0x01,
18
    0x75, 0x02,
19
    0x81, 0x03,
20
    0xc0
21
};
22

23

24
static const uint8_t PROGMEM dev_desc[] =
25
{
26
    0x09,0x21,
27
    0x11,0x01,
28
    0x00,0x01,
29
    0x22,sizeof(rep_desc)
30
};
31

32
int
33
main ()
34
{
35
}
1
avr-gcc  -mmcu=atmega328p -Wall -gdwarf-2 -std=gnu99 -da -flto         -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT test.o -MF dep/test.o.d  -c  ../test.c
2
avr-gcc -mmcu=atmega328p -flto  -Os -Wl,-Map=test.map test.o     -o test.elf
3
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  test.elf test.hex
4
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex test.elf test.eep || exit 0
5
avr-objdump -h -S test.elf > test.lss
6

7
AVR Memory Usage
8
----------------
9
Device: atmega328p
10

11
Program:     138 bytes (0.4% Full)
12
(.text + .data + .bootloader)
13

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

Geht also auch beim avr-gcc einwandfrei durch.
Moderator Persönliche Seite #4660945
Lesenswert?

Draco schrieb:
> high(sizeof(rep_desc)),low(sizeof(rep_desc))
>   };
>
> Warum auch immer er mir da nen "non const" error rausgeworfen hat, keine
> Ahnung.

Zeig mal die vollständige Fehlermeldung.

> Aber geht nun...

Geht bei mir auch mit avr-gcc ohne den high/low-Trick.

Außer Du hast tatsächlich mehr als 255 Elemente im Array, was Du uns 
dann aber verschwiegen hast :)
Moderator Persönliche Seite #4660969
Lesenswert?

Draco schrieb:
> Ja das hab ich, leider :-D
>
> Ich dachte das wäre nicht von belangen, aber wie sagt man so schön "Man
> soll ja nicht denken"!

Dann hat die Fehlermeldung aber garantiert nicht so gelautet, wie Du es 
beschrieben hast, sondern:
1
warning: large integer implicitly truncated to unsigned type [-Woverflow]

Das kommt nämlich bei mir, wenn ich mehr als 255 Elemente einfüge. Auch 
ist es kein Error, sondern lediglich eine (ernstzunehmende) Warnung.
Gast #4661029
Lesenswert?

Das schmeißt er mir dabei raus:
1
c:\users\draconix\Documents\Atmel Studio\7.0\ThinJoyStick\ThinJoyStick\DracoUSB\DracoUSB.c(174,44): info: each undeclared identifier is reported only once for each function it appears in
2
c:\users\draconix\Documents\Atmel Studio\7.0\ThinJoyStick\ThinJoyStick\DracoUSB\DracoUSB.c(248,2): error: initializer element is not constant
3
      sizeof(rep_desc),
4
      ^
5
c:\users\draconix\Documents\Atmel Studio\7.0\ThinJoyStick\ThinJoyStick\DracoUSB\DracoUSB.c(248,2): error: (near initialization for 'conf_des[25]')
6
    make: *** [DracoUSB/DracoUSB.o] Error 1
7
    "C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG -DF_CPU=16000000 -DMCU=atmega32u4  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.106\include"  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega32u4 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.106\gcc\dev\atmega32u4" -c -std=gnu99 -MD -MP -MF "DracoUSB/DracoUSB.d" -MT"DracoUSB/DracoUSB.d" -MT"DracoUSB/DracoUSB.o"   -o "DracoUSB/DracoUSB.o" "../DracoUSB/DracoUSB.c" 
8
c:\users\draconix\Documents\Atmel Studio\7.0\ThinJoyStick\ThinJoyStick\Debug\Makefile(87,1): error: recipe for target 'DracoUSB/DracoUSB.o' failed
9
    make: *** Waiting for unfinished jobs....
Gast #4661052
Lesenswert?

Mw E. schrieb:
>> 'conf_des[25]'
>
> Wie hier schon geschrieben wurde, haste dich wohl vertippt.
> Fehlermeldungen sind nicht zum überfliegen da, sondern zum analysieren!

Nein halt, der Fehler war hier beim Aptippen. Im Sourcecode sind einige 
Variabel Namen ohne das "c" geschrieben. Die Konstante in dem diese 
Funktion aufgerufen wird, heißt tatsächlich bloß conf_des.


(Bei HID Descriptor unten steht die Zeile)
1
  static const uint8_t PROGMEM conf_des[] =  
2
  {
3
    0x09,        //bLength = 0x09, Groesse Deskriptor in Byte
4
    0x02,        //bDescriptorType = 0x02, Konstante Configuration = 2
5
    high(wTotalLength),low(wTotalLength),  //wTotalLength,
6
    0x01,        //bNumInterfaces = 1
7
    0x01,        //bConfigurationValue = 1
8
    0x00,        //iConfiguration = 0, Index fuer Str.-Deskr.(0=kein Txt)
9
    0x80,        //bmAttributes = 0x80, kein remote wakeup Bit 7=1
10
    250,         //MaxPower = 250(dezimal), in 2mA Schritten! (500mA)
11
    
12
    /*** Interface Descriptor ***/
13
    0x09,        //bLength = 0x09, Groesse Deskriptor in Byte
14
    0x04,        //bDescriptorType = 0x04, Konstante Interface = 4
15
    0x00,        //bInterfaceNumber = 0;
16
    0x00,        //bAlternateSetting = 0;
17
    Nr_eps,      //bNumEndpoints = USB_Endpoints;
18
    0x03,        //bInterfaceClass = 0x03 HID, Klassencode:
19
    0x00,        //bInterfaceSubClass = 0x00, Unterklassencode
20
    0x00,        //bInterfaceProtocol = 0x00, Protokollcode
21
    0x00,        //iInterface = 0, Index fuer String-Deskr. Interf.
22
    
23
    /*** HID Descriptor ***/
24
    0x09,        //bLength = 0x09, Groesse Deskriptor in Byte
25
    0x21,        //bDescriptorType = 0x21 (HID-Klasse)
26
    0x11,0x01,   //bcdHID = 0x0110, HID_Spec 1.1
27
    0x00,        //bCountryCode = 0 (wird hier nicht unterstuetzt)
28
    0x01,        //bNumDescriptors = 1
29
    0x22,        //bDescriptorType = 0x22,
30
    //sizeof(rep_desc),   
31
    low(sizeof(rep_desc)),high(sizeof(rep_desc)),
32
    
33
  /*** EP1 Descriptor ***/
34
    0x07,    //bLength = 0x07, Groesse Deskriptor in Byte
35
    0x05,    //bDescriptorType = 0x05, Konstante Endpoint = 5
36
    0x81,    //bEndpointAddress = 0x81, Bit 7 = 1 (IN) Bit 0-3 EP-Nummer
37
    0x03,    //bmAttributes = Interrupt
38
    Ep1_fs_l,Ep1_fs_h,    //wMaxPacketSize = EP1_FIFO_Size;
39
    0xFF,    //bInterval = 1 bei Interrupt: Latenzzeit in Millisekunden
40
    
41
  /*** EP2 Descriptor ***/
42
    0x07,    //bLength = 0x07, Groesse Deskriptor in Byte
43
    0x05,    //bDescriptorType = 0x05, Konstante Endpoint = 5
44
    0x02,    //bEndpointAddress = 0x82, Bit 7 = 1 (IN) Bit 0-3 EP-Nummer
45
    0x03,    //bmAttributes = Interrupt
46
    Ep2_fs_l,Ep2_fs_h,    //wMaxPacketSize = EP2_FIFO_Size;
47
    0xFF     //bInterval = 1 bei Interrupt: Latenzzeit in Millisekunden
48
  };

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