Forum: Mikrocontroller und Digitale Elektronik GCC - Länge eines Const Array in ein anderes bringen


von Draco (Gast)


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
  };

von Dr. Sommer (Gast)


Lesenswert?

C++ nehmen, da geht das IIRC genau 1:1 so

von Mw E. (Firma: fritzler-avr.de) (fritzler)


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);

: Bearbeitet durch User
von Nop (Gast)


Lesenswert?

Könnte man nicht die Daten im ersten Array als Enums machen und dann 
immer als letztes Enum ein Größen-Enum anhängen?

von Frank M. (ukw) (Moderator) Benutzerseite


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.

: Bearbeitet durch Moderator
von Dr. Sommer (Gast)


Lesenswert?

Frank M. schrieb:
> Dein Problem muss woanders stecken - jedenfalls nicht in dem hier
> beschriebenen Text.

Kannst du das mal mit dem AVR GCC probieren? vermutlich muss der für 
PROGMEM alle Daten zur Kompile Zeit wissen...

von Clemens L. (c_l)


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
  };

von Draco (Gast)


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

von Frank M. (ukw) (Moderator) Benutzerseite


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.

von Frank M. (ukw) (Moderator) Benutzerseite


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 :)

von Draco (Gast)


Lesenswert?

Frank M. schrieb:
> Außer Du hast tatsächlich mehr als 255 Elemente im Array, was Du uns
> dann aber verschwiegen hast :)

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"!

von Frank M. (ukw) (Moderator) Benutzerseite


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.

von Draco (Gast)


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....

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

> 'conf_des[25]'

Wie hier schon geschrieben wurde, haste dich wohl vertippt.
Fehlermeldungen sind nicht zum überfliegen da, sondern zum analysieren!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hm, eine Erklärung habe ich dafür jedenfalls nicht.

Vielleicht nur bei Ansicht des tatsächlichen Sources... - aber egal. :-)

: Bearbeitet durch Moderator
von Draco (Gast)


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
  };

von Falk B. (falk)


Lesenswert?

@  Draco (Gast)

>Nein halt, der Fehler war hier beim Aptippen.

FAIL! Das tut man nicht! NIEMALS!

https://www.mikrocontroller.net/articles/Netiquette#.C3.84u.C3.9Fere_Form

"Quelltext nie abtippen, sonder immer das direkt kopierte Original 
posten, anderenfalls schleichen sich neue Fehler ein oder die 
existierenden werden nicht abgeschrieben."

von Huh (Gast)


Lesenswert?

Draco schrieb:
> Nein halt, der Fehler war hier beim Aptippen.

Genau aus diesem Grunde wurde schon unzählige Male gesagt: Code nicht 
abtippen, sondern reinkopieren! Du bist der beste Beweis dafür, daß 
diese Mahnung völlig berechtigt ist! :-)

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.