Topic : Make Default Enum Type Unsigned

Forum : ST7/STM8

Original Post
Post Information Post
April 18, 2012 - 2:34pm

Hello Forum:

I have come across something unexpected when working with enumerated values with the Raisonance compiler. Long story short, I was wondering if there was a way to tell the compiler to treat enumerations as unsigned rather than signed values? I had expected using the ET(CHAR) and UNSIGNEDCHAR directives together would have this effect, but it does not.

The code snippet below shows the issue I have been seeing. This code is in a packet handler in a link that has fixed packet type priorities. When my current state is idle and I receive a command packet (and I expect 0x80 to be greater than 0x01), I do not do any processing on the packet.

typedef enum
   IdleEvent = 0x01,
   AcknowledgementEvent = 0x40,
   CommandEvent = 0x80,
   MaxEventType = 0x81
} EventType;

typedef struct
   EventType LinkState;
   /* ... */
} LinkEventParameters;

typedef struct
   EventType PacketType;
   uint8_t* PacketBuffer;
   /* ... */
} ReceivedPacketInfo;

static LinkEventParameters DataLinkEventParams;

static void doPacketProcessing(const ReceivedPacketInfo * const packetInfo)
   if (DataLinkEventParams.LinkState < packetInfo->PacketType)
      /* Do work */
   else if (DataLinkEventParams.LinkState == packetInfo->PacketType)
      /* Do different work */
   /* else, do no work */

Here is the assembly generated by the compiler:

; FUNCTION ?doPacketProcessing?MY_MODULE?S (BEGIN)
              ; Register XW is assigned to parameter packetInfo
0000 88                                PUSH   A
0001 B600       F                   LD     A,DataLinkEventParams
0003 F1                                CP     A,(X)
0004 2E03                            JRSGE  ?ELSE_0036 ; Doing a signed compare!
              ; SOURCE LINE # 609 
                                             ; Do Work
0009         ?ELSE_0036:
              ; SOURCE LINE # 611 
0009 B600       F                      LD     A,DataLinkEventParams
000B F1                                   CP     A,(X)
000C 265E                              JRNE   ?NXT_0039

Note that I have been able to workaround this problem by casting EventType to a uint8_t before doing the compare, but I would rather not have to do this.

Any help would be appreciated.

Post Information Post
April 19, 2012 - 9:47am
Raisonance Support Team


There are several ways to answer your question:

- The C standard mandates that enumerations are integers. So no, you cannot have unsigned values.

- Our compiler can reduce the enumeration type size to a char, which is a Raisonance extension to the C standard (as we are on a 8-bit architecture). This is what you played with with the ET(CHAR) directive. If you use ET(INT), your code should be OK, as the enumerations will then be handled as 16-bit signed integers.

However, the main answer I would give would be more like a coding advice. We are on very limited systems (STM8) and you have to adapt you C programming style for these deeply embedded architectures. For this reason, you should use enumerations only for identifiers that have interchangeable values.
What I mean is that enumerations should be used as placeholders only, NOT TO HOLD ACTUAL VALUES.
This is because enumerations load the compiler with a lot of extra burden; using macros will let the compiler optimize in a much nicer way.

In your case, the best compiler code will be generated by something like:

#define IDLEEVENT               0X01;
#define COMMANDEVENT            0X80;
#define MAXEVENTTYPE            0X81;

Lots of users are rewriting the ST firmware libraries this way, as it provides much better code performance.

Best Regards,