'Allocate only as many bytes needed by enum types' Problem

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the Allocate only as many bytes needed by enum types (-fshort -enums)  is checked, the firmware compiles - but the program does not work.

 

Am using AS7 with ATMega328p, with -Os optimisation. (though this also occurred on AS6)

 

Just wondered if there were known reasons why this would not work, for example the enums have to be declared in a certain way?

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

define "does not work" 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

iBeta666 wrote:
If the Allocate only as many bytes needed by enum types (-fshort -enums)  is checked, the firmware compiles - but the program does not work.

Does it work if the option is not checked?

 

If it does, then use the debugger to step through the two version and find where it fails ...

 

Just wondered if there were known reasons why this would not work, 

Probably your code is making unsafe assumptions about the size of an enum - and that breaks when you change the size of the enum ...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just to note that the effect of -fshort-enums is simply this:

#include <avr/io.h>

enum {
	FSTATE1 = 17,
	FSTATE2 = 23
} foo;

enum {
	BSTATE1 = 12345,
	BSTATE2 = 22222
} bar;

int main(void){
	PORTB = sizeof(foo);
	PORTB = sizeof(bar);
	return 0;
}
C:\SysGCC\avr\bin>avr-gcc -Os -mmcu=atmega16 -g avr.c -o avr.elf

C:\SysGCC\avr\bin>
C:\SysGCC\avr\bin>avr-objdump.exe -S avr.elf
...
        PORTB = sizeof(foo);
  7c:   82 e0           ldi     r24, 0x02       ; 2
  7e:   88 bb           out     0x18, r24       ; 24
        PORTB = sizeof(bar);
  80:   88 bb           out     0x18, r24       ; 24

So in the "normal" case both of these enums are 2 bytes (16 bits) so 0x02 is written twice. Now with -fshort-enums:

C:\SysGCC\avr\bin>avr-gcc -Os -mmcu=atmega16 -fshort-enums -g avr.c -o avr.elf

C:\SysGCC\avr\bin>
int main(void){
        PORTB = sizeof(foo);
  7c:   81 e0           ldi     r24, 0x01       ; 1
  7e:   88 bb           out     0x18, r24       ; 24
        PORTB = sizeof(bar);
  80:   82 e0           ldi     r24, 0x02       ; 2
  82:   88 bb           out     0x18, r24       ; 24

So sizeof(foo) == 1 and sizeof(bar) = 2.

 

It can hold FSTATE1/FSTATE2 in 1 byte because the only elements are 17 and 23 but bar requires 2 bytes per entry to hold 12345 and 22222.

 

As far as the programmer is concerned this should not matter. There is no reason the programmer ever really needs to know the width that an enum is held in and for small resource micros there may be a distinct advantage in holding the enum in just 1 byte if it can be achieved.

 

So I do wonder what exactly you are doing with your enums that might expose their storage width? Obviously if you did something really dire like:

typedef enum {
    STATE1 = 17,
    STATE2 = 23
} e_type;

void some_fn(void) {
    union {
        e_type state;
        uint16_t n;
    } joined;
    
    joined.state = STATE2;
    TCNT1 = joined.n;
}

then without -fshort-enums this would be predictable as the:

    joined.state = STATE2;

should write 2 bytes with the upper one being 0x00. But built with -fshort-enums the upper byte of joined.n is potentially some garbage value that was on the stack when some_fn() was called.

 

But if you are doing anything like this (horrendous!) code you should be taken out and summarily executed.

 

"Normal" use of enums should not be sensitive to their storage width which is why -fshort-enums is (usually) a viable option!

 

[PS I had to try pretty hard to think up some evil scenario which might be sensitive to and expose the width of an enum - only unions and type punning sprung to mind]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Note the the OP didn't actually say that the code has ever worked at all - even without -fshort-enums 

 

Hence my request for that clarification.

 

clawson wrote:
[PS I had to try pretty hard to think up some evil scenario which might be sensitive to and expose the width of an enum - only unions and type punning sprung to mind]

Possibly also using enums in bitfields ... ?

 

It could also be just pure coincidence ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for not making it clear, the program did and does work, as long as the enum flag is not set.

Thanks for the info Clawson, hopefully I've dodged the firing squad; there are no unions defined anywhere. And I'm pretty sure am not using enums in bitfields.

The enums in the program are defined as below:

enum VRState
{
	NotWaiting,
	Waiting,
	Error
};
enum OneWireInterComms
{
	NoData=0x00,
	SendMessage=0x0C,
	PIRActive=0x0D,
	LightsActive=0x0E,
	SetTime=0x0F
};

It is strange, I sort of remember having problems with the short enums in other programs but was not so bothered if it was left off. In this case the 500B spared would be pretty useful. The program is quite long, and it's possible I forgot something weird. Maybe should try and debug, or maybe make a shorter test case first?

 

There are lots of 3rd party libraries referenced but would not think that would matter.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

iBeta666 wrote:
maybe make a shorter test case first?

Yes.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

iBeta666 wrote:
Maybe should try and debug

There's no "maybe" about it: it's a bug and you need to get rid of it - that is debugging!!

 

The debugger is (as the name suggests) a great tool for this; but the most important & powerful tool is the one between your ears!

 

As clawson noted in the very first reply, your problem description is almost completely uninformative:

 

clawson wrote:
define "does not work"

 

So you need to look at the symptoms of the "not working" and think about what could possibly be going wrong.

 

This should help you narrow down your search for the bug

 

http://www.8052.com/faqs/120313

 

See also: http://www.ganssle.com/articles/...

 

You've mentioned 1-Wire - so have you looked at the signals on the wire to see if they're correct?

 

or maybe make a shorter test case first?

That's a good approach - but you need some basis for selecting what to leave out in your "shortening" ...

 

 

There are lots of 3rd party libraries referenced but would not think that would matter.

Are you sure that none of them relies upon  -fshort-enums  not being set ... ?

 

Or, to put it the other way around, do any of them require that enums be the "standard" size?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
or maybe make a shorter test case first? That's a good approach - but you need some basis for selecting what to leave out in your "shortening" ...

Taking out piece after piece and run a test after each piece has been removed. When "not working" (whatever that is) turns into "working" then he _might_ be close. (This method does not even require a debugger.)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

iBeta666 wrote:
The enums in the program are defined as below:
It's where they are used, how and for what that is important. Not the original declarations.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I define my enum as

 

enum __attribute__ ((__packed__)) myenum {

  value1,

  value2,

};

 

This will make the enum 1 byte, as long as there are less than 255 elements.

 

Of course, if you give specific values to an enum, the compiler will assume its size depending on the values.

E.g.

 

enum __attribute__ ((__packed__)) myenum {

  value1 =255,

  value2,

};

 

will make the enum 2 bytes.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any particular reason for preferring  __attribute__ ((__packed__)) over  -fshort-enums ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

Any particular reason for preferring  __attribute__ ((__packed__)) over  -fshort-enums ?

 

I like things to be explicit in the code, if possible, without looking at makefiles or obscure GUI's where you set things with tickboxes.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK; fair enough.

 

But not relevant to this thread.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

-fshort-enums is equivalent to the attribute definition, but with a different scope. In a previous message, someone asked if the -fshort-enums was indeed set, well, if you use attribute packed you're sure it's set, Another question was if -fshort-enums caused other enums to be 1 byte while the code assumed to be 2. With the attribute you control which and what.

 

Thanks for thinking it's not relevant to this thread.