I'm passing enumeration constants as bit-flags to a function that expects the enumeration type as input, like this:
// Enumeration type
typedef enum
{
LED_RED = (1 << 0),
LED_GREEN = (1 << 1),
LED_YELLOW = (1 << 2),
LED_ORANGE = (1 << 3),
} LedType;
...
// Function declaration
void setOnLed(LedType led);
...
// Function call
setOnLed(LED_RED | LED_GREEN | LED_YELLOW);
When I call the function, I get a warning:
warning: #188-D: enumerated type mixed with another type
The warning is because LED_RED | LED_GREEN | LED_YELLOW
is converted to an integer and is not a LedType
.
I could avoid the warning by adding LED combinations to the LedType
enumeration but that means I have to add all possible combinations... and if I add more LED options to the enum
, it will become really messy...
I could use arrays as an input to the function but that will require more code when calling the function, I prefer a simple function call to set LED's.
I am programming an ARM based micro-controller (STM32) using Keil µVision IDE.
Is there a simple safe way to avoid this warning or another way to encapsulate all the LED's in one meaningful type/object so I can easily pass them to a function and process them in a loop?
I'm writing a program for an ARM based MCU which is connected to several LED's. In many places in the program, we will torn on/off, toggle and blink different combinations of the LED's. To make this clean and simple, I want to write several functions that get as input any combination of the LED's and do the same operations on all.
I created a struct
named LedConfig
with the hardware configurations of a LED and an array of LedConfig
that contains the configuration of each LED:
typedef struct
{
// Hardware configurations of a LED
...
} LedConfig;
...
LedConfig LedArry[LEDS_LED_COUNT] =
{
[0] = { /* Red LED config */ },
[1] = { /* Green LED config */ },
[2] = { /* Yellow LED config */ },
[3] = { /* Orange LED config */ }
};
Now, I would like a simple way to pass several LED's to a function and process them in a loop.
I created a number of bit flags for each LED:
// Number of LED's defined in the system
#define LED_COUNT 4
// LED flags, for usage in LED's function
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_YELLOW (1 << 2)
#define LED_ORANGE (1 << 3)
Defined a function:
void setOnLed(uint32_t led)
{
uint32_t bitMask = 1;
for(int i = 0; i < LED_COUNT; i++)
{
if(led & bitMask)
{
LedConfig* ledConfig = &LedArry[i];
// Turn on LED ...
}
bitMask <<= 1;
}
}
Now I can pass the LED's to the function with bitwise or operation:
setOnLed(LED_RED | LED_GREEN | LED_YELLOW);
This works fine but...
I would prefer to use an enum
instead of defines for LED flags, in order to encapsulate theme in one meaningful type/object.
I replaced the defines with an enumeration:
typedef enum
{
LED_RED = (1 << 0),
LED_GREEN = (1 << 1),
LED_YELLOW = (1 << 2),
LED_ORANGE = (1 << 3),
} LedType;
And modified setOnLed
function input to get the enumeration type:
void setOnLed(LedType led)
{
// ...
}
When I call the function with several LED's:
setOnLed(LED_RED | LED_GREEN | LED_YELLOW);
I get the warning:
warning: #188-D: enumerated type mixed with another type
Note: uint32_t
is from stdint.h and is an unsigned 32-bit integer.
I would prefer to use an enum instead of defines for LED flags because I prefer to encapsulate theme in one meaningful type/object.
This is perfectly fine but keep two things in mind:
LED_RED
in your case, is always of type int
which is signed.LedType
in your case is implementation-defined. The compiler can pick a smaller integer type if the values used would fit inside one.Generally, you'll want to avoid signed types in embedded systems, because of integer promotion and various hiccups with bitwise operators.
One such hiccup is left-shifting a signed integer constant 1
. This is of type int
and signed, so on a 32 bit system, 1 << 31
would mean an undefined behavior bug. Therefore, always unsign suffix your integer constants: always use 1u << n
instead of 1 << n
.
I get the warning:
warning: #188-D: enumerated type mixed with another type
Yeah because the function expects a uint32_t
but you pass a int
, since all operands in the expression LED_RED | LED_GREEN | LED_YELLOW
are int
- they are enumeration constants as described above. You should rewrite the function to take LedType
as parameter instead.
Example:
// led.h
typedef enum
{
LED_NONE = 0u,
LED_RED = 1u << 0,
LED_GREEN = 1u << 1,
LED_YELLOW = 1u << 2,
LED_ORANGE = 1u << 3,
LED_ALL = LED_RED | LED_GREEN | LED_YELLOW | LED_ORANGE;
} led_t;
#define LED_PORT PORTX
void set_led (led_t leds);
// led.c
#include "led.h"
void set_led (led_t leds)
{
// this assuming you'll want to use the function both to set and clear leds
uint32_t led_port = LED_PORT;
led_port &= (uint32_t) ~LED_ALL;
led_port |= (uint32_t) leds;
LED_PORT = (uint32_t) leds;
}
The (uint32_t)
casts are strictly speaking not necessary but will sate pedantic compilers and MISRA-C checkers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With