2

The following piece of code which is 2 dimensional array throws an error #29 expected an expression.

typedef  enum 
{
    BATTERY_POW = 0,
    USB_POW = 1,
    END_STATE = 2
} BMTState_e;   

typedef enum //event enums
{  
    NO_EVENT = 0,
    BOOT_EVENT =1,
    //I/O events
    POW_GOOD_LOW =2,
    POW_GOOD_HIGH = 3,
    VBUS_POW_LOW = 4,
    VBUS_POW_HIGH =5
}BMTEvent_e;

The structure is defined as

typedef struct  //state machine definition
{
    void (*funcPtr)();
    BMTState_e nextState;
}BMTAction_t;
BMTState_e BMTGlobal_State ; //global state

The function is defined as

void BMTTest()
{
 //do nothing for time being
}
BMTAction_t  action[END_STATE][END_EVENT]={
   [BATTERY_POW][NO_EVENT]    = {BMTTest,BATTERY_POW}
   [BATTERY_POW][BOOT_EVENT]    = {BMTTest,BATTERY_POW},
   [BATTERY_POW][POW_GOOD_LOW]  = {BMTTest,USB_POW},
   [BATTERY_POW][POW_GOOD_HIGH] = {BMTTest,BATTERY_POW}
   [BATTERY_POW][VBUS_POW_LOW]  = {BMTTest,BATTERY_POW},
   [BATTERY_POW][VBUS_POW_HIGH] = {BMTTest,USB_POW},
   [USB_POW][BOOT_EVENT]    = {BMTTest,USB_POW_}
   [USB_POW][BOOT_EVENT]    = {BMTTest,USB_POW},
   [USB_POW][POW_GOOD_LOW]  = {BMTTest,USB_POW},
   [USB_POW][POW_GOOD_HIGH] = {BMTTest,BATTERY_POW}
   [USB_POW][VBUS_POW_LOW]  = {BMTTest,BATTERY_POW},
   [USB_POW][VBUS_POW_HIGH] = {BMTTest,USB_POW}
}; 

void BMT_HandleEvent(BMTEvent_e event)
{
  BMTAction_t stAction;


   if(event != NO_EVENT)
   {
      stAction.funcPtr = action[BMTGlobal_State][event].funcPtr;
      stAction.nextState = action[BMTGlobal_State][event].nextState;
      printf("current State =%d, event = %d, nextState = %d",BMTGlobal_State, event,stAction.nextState );

      if(NULL!= stAction.funcPtr)
        stAction.funcPtr();
        BMTGlobal_State = stAction.nextState;
    }

}

int main()
{
BMTEvent_e = BOOT_EVENT;
if(retVal)
    {
    BMTGlobal_State = BATTERY_POW;
    }
else // PG is low so check VBUS signal 
    {
retVal = GPIO_Read_Pin(USB_VBUS_PWR_PIN);
if(retVal)
        {
        BMTGlobal_State = USB_POW;
        }
else
        {
        BMTGlobal_State = CRADLE_POW;
        }
    }
event = BOOT_EVENT;
while (1)
    {
    BMT_HandleEvent(event);
    } 
}

The idea is to execute the state machine based on the events received. The 2D array list the current state and all possible events for the state, once an event is received a function pointer will be invoked and the state will transition to the next state.

I am using MicroC/OS2 with GreenHills compiler/tools. I would appreciate your response.

I followed Keith's recommendation

BMTAction_t  action[END_STATE][END_EVENT] = {
                  {{NULL,BATTERY_POW}}, //0
                  {{BMTProcess_BatteryPowBoot,BATTERY_POW}},//   1
                  {{BMTProcess_PowGoodLow,BATTERY_POW}},//2
                  {{BMTProcess_PowGoodHigh,BATTERY_POW}}, //3
                  {{BMTProcess_VBUSPowerLow,BATTERY_POW}}, //4
                  {{BMTProcess_VBUSPowerHigh,BATTERY_POW}},//5 
};

The compiler gives error at line

"{{BMTProcess_PowGoodHigh,BATTERY_POW}}, //3" 
"error # 146 too many initializer values"
John Burger
  • 3,662
  • 1
  • 13
  • 23
user1867459
  • 423
  • 2
  • 8
  • 27

4 Answers4

5

That's not the right syntax for designated initializer. You can only specify one index at a time.

I was incorrect; multiple designators are permitted. In fact, your code compiles without error using gcc -std=c99 -pedantic -Wall -Wextra after I add a few declarations.

typedef enum { BATTERY_POW, END_STATE } BMTState_e;
typedef enum { BOOT_EVENT, POW_GOOD_LOW, POW_GOOD_HIGH, END_EVENT } BMTEvent_e;

void BMTTest(void);

typedef struct  //state machine definition
{
    void (*funcPtr)();
    BMTState_e nextState;
}BMTAction_t;

BMTAction_t  action[END_STATE][END_EVENT]={
    [BATTERY_POW][BOOT_EVENT]    = {BMTTest,BATTERY_POW},
    [BATTERY_POW][POW_GOOD_LOW]  = {BMTTest,BATTERY_POW},
    [BATTERY_POW][POW_GOOD_HIGH] = {BMTTest,BATTERY_POW}
}; 

Most likely your compiler doesn't understand designated initializers. (They were added to the language by the 1999 standard, and even today not all compilers support them.)

If it doesn't, you'll need to remove the bracketed expressions (and make sure you have the elements in the right order). Probably something like:

BMTAction_t  action0[END_STATE][END_EVENT] = {
    {{ BMTTest, BATTERY_POW }},
    {{ BMTTest, BATTERY_POW }},
    {{ BMTTest, BATTERY_POW }}
};
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Hi Ken, thanks for the response,I found that the code compiled after following your instruction, but How does it follow the state machine upon event change. – user1867459 Feb 02 '15 at 14:47
  • Hi Ken, The code compiled after following your instruction with removing the bracketed part ([BATTERY_POW][BOOT_EVENT]), but How does it follow the state machine upon event change. i.e. for all three events under state BATTERY_POW the same function "BMTest" and the same end state "BATTERY_POW" is set. If that is the case does the first function BMTest corresponds to BOOT_EVENT in the state BATTERY_POW and the second function BMTest corresponds to the state BATTERY_POW and POW_GOOD_LOW event and so on? So do I have to do this for all the states and events associated with the state? – user1867459 Feb 02 '15 at 14:56
  • @user1867459: (It's Keith, not Ken.) I'm not sure I understand the question. You just need to rewrite the initialization so it assigns the same values to the same elements. – Keith Thompson Feb 02 '15 at 16:49
  • Hi Keith, First of all my apologies for the typo.The moment, I add more events in the event enum the code breaks. typedef enum { BOOT_EVENT, POW_GOOD_LOW, POW_GOOD_HIGH, NO_EVENT, STAT_REQ_EVENT, END_EVENT } BMTEvent_e; BMTAction_t action[END_STATE][END_EVENT]= { {{BMTTest,BATTERY_POW}}, {{BMTTest,BATTERY_POW}}, {{BMTTest,BATTERY_POW}}, {{BMTTest,BATTERY_POW}},//Here it throws error {{BMTTest,BATTERY_POW}}, }; The compiler throws "error too many initializer values". So I was trying to understand how to initialize this 2D array? finally, I would like to have more states and more enums. – user1867459 Feb 02 '15 at 17:45
  • You just have to provide initializers in order for each element at each level. You can omit trailing elements. You can't *skip* elements other than trailing ones unless you use designated initializers, which your compiler apparently doesn't support. I can't really go into more detail than that without seeing the actual code *in the question*. – Keith Thompson Feb 02 '15 at 18:17
  • the comment box doesn't allow me to copy paste the entire code. How do I send the code? – user1867459 Feb 02 '15 at 19:06
  • @user1867459: Edit the question. (Comments are meant to be ephemeral anyway; administrators can delete them without notice.) – Keith Thompson Feb 02 '15 at 19:08
  • I just tried to provide the overall code that explains what i would like to achieve. – user1867459 Feb 02 '15 at 19:50
  • 1
    Thought I would put you in the bottom of that 100k group ;-) – chux - Reinstate Monica Feb 04 '15 at 15:47
  • 1
    @user1867459: chux's comment was addressed to me; his upvote on my answer pushed me over 100,000 reputation points. I had mentioned elsewhere that I was about to go from the very top of the under-100k group to the very bottom of the over-100k group. – Keith Thompson Feb 06 '15 at 15:31
0

Keith answer helped me figure out the correct initialization. I had to list all the possible events and associated function pointer for a given state inside the {{ }}.

This is like to initializing elements of row[0][0] and row [0][1] I had to list all the elements inside the top level double curly braces something like

 { **{{**values/function/events associated with row [0][0],{values/function/events associated with row [0][1] }}, 
//now do the same for row 1. 
**{{**values/function/events associated with row [1][0],{values/function/events associated with row [1][1] **}}** }; //end of the array

BMTAction_t  action[END_STATE][END_EVENT] = {
                 //STATE = BATTERY_POW
                  {{NULL,BATTERY_POW}, //0
                  {BMTProcess_BatteryPowBoot,BATTERY_POW},//   1
                  {BMTProcess_PowGoodLow,BATTERY_POW},//2
                  {BMTProcess_PowGoodHigh,BATTERY_POW}, //3
                  {BMTProcess_VBUSPowerLow,BATTERY_POW}, //4
                  {BMTProcess_VBUSPowerHigh,BATTERY_POW}},//5 
                  //STATE = USB_POW
                  {{NULL,USB_POW}, //0
                  {BMTProcess_BatteryPowBoot,USB_POW},//   1
                  {BMTProcess_PowGoodLow,USB_POW},//2
                  {BMTProcess_PowGoodHigh,USB_POW}, //3
                  {BMTProcess_VBUSPowerLow,USB_POW}, //4
                  {BMTProcess_VBUSPowerHigh,USB_POW}}//5 
                };
user1867459
  • 423
  • 2
  • 8
  • 27
0

The initialization that you were using will work with the greenhills compiler if you use the -c99 option.

I had to make a few minor changes to your code to get it to compile:

  • Add the END_EVENT enum
  • Add some commas in between the items of the action declaration.
  • Fixed typo USB_POW_ to USB_POW

Here's the modified code:

#include <stdio.h>
typedef enum {
    BATTERY_POW = 0,
    USB_POW = 1,
    END_STATE = 2
} BMTState_e;

typedef enum {
    NO_EVENT = 0,
    BOOT_EVENT =1,
    //I/O events
    POW_GOOD_LOW =2,
    POW_GOOD_HIGH = 3,
    VBUS_POW_LOW = 4,
    VBUS_POW_HIGH =5,
    END_EVENT = 6

} BMTEvent_e;

typedef struct {
    void (*funcPtr)();
    BMTState_e nextState;
} BMTAction_t;

void BMTTest()
{
 //do nothing for time being
}
BMTAction_t  action[END_STATE][END_EVENT]={
[BATTERY_POW][NO_EVENT]    = {BMTTest,BATTERY_POW},
[BATTERY_POW][BOOT_EVENT]    = {BMTTest,BATTERY_POW},
[BATTERY_POW][POW_GOOD_LOW]  = {BMTTest,USB_POW},
[BATTERY_POW][POW_GOOD_HIGH] = {BMTTest,BATTERY_POW},
[BATTERY_POW][VBUS_POW_LOW]  = {BMTTest,BATTERY_POW},
[BATTERY_POW][VBUS_POW_HIGH] = {BMTTest,USB_POW},
[USB_POW][BOOT_EVENT]    = {BMTTest,USB_POW},
[USB_POW][BOOT_EVENT]    = {BMTTest,USB_POW},
[USB_POW][POW_GOOD_LOW]  = {BMTTest,USB_POW},
[USB_POW][POW_GOOD_HIGH] = {BMTTest,BATTERY_POW},
[USB_POW][VBUS_POW_LOW]  = {BMTTest,BATTERY_POW},
[USB_POW][VBUS_POW_HIGH] = {BMTTest,USB_POW}
};
int main()
{
    return 1;
}

Here's the compiler output without -c99:

$ ccppc test.c
"test.c", line 30: error #29: expected an expression
  [BATTERY_POW][NO_EVENT]    = {BMTTest,BATTERY_POW},
  ^

"test.c", line 31: error #29: expected an expression
  [BATTERY_POW][BOOT_EVENT]    = {BMTTest,BATTERY_POW},
  ^

"test.c", line 32: error #29: expected an expression
  [BATTERY_POW][POW_GOOD_LOW]  = {BMTTest,USB_POW},
  ^

"test.c", line 33: error #29: expected an expression
  [BATTERY_POW][POW_GOOD_HIGH] = {BMTTest,BATTERY_POW},
  ^

"test.c", line 34: error #29: expected an expression
  [BATTERY_POW][VBUS_POW_LOW]  = {BMTTest,BATTERY_POW},
  ^

"test.c", line 35: error #29: expected an expression
  [BATTERY_POW][VBUS_POW_HIGH] = {BMTTest,USB_POW},
  ^

"test.c", line 36: error #29: expected an expression
   [USB_POW][BOOT_EVENT]    = {BMTTest,USB_POW},
   ^

"test.c", line 37: error #29: expected an expression
  [USB_POW][BOOT_EVENT]    = {BMTTest,USB_POW},
  ^

"test.c", line 38: error #29: expected an expression
  [USB_POW][POW_GOOD_LOW]  = {BMTTest,USB_POW},
  ^

"test.c", line 39: error #29: expected an expression
  [USB_POW][POW_GOOD_HIGH] = {BMTTest,BATTERY_POW},
  ^

"test.c", line 40: error #29: expected an expression
  [USB_POW][VBUS_POW_LOW]  = {BMTTest,BATTERY_POW},
  ^

"test.c", line 41: error #29: expected an expression
  [USB_POW][VBUS_POW_HIGH] = {BMTTest,USB_POW}
  ^

And with -c99:

$ ccppc -c99 test.c
Tim
  • 4,790
  • 4
  • 33
  • 41
0

You do realise that your code includes the following:

   [USB_POW][BOOT_EVENT]    = {BMTTest,USB_POW_}
   [USB_POW][BOOT_EVENT]    = {BMTTest,USB_POW},

Even I'd be confused by that. Did you mean the first to be NO_EVENT?

John Burger
  • 3,662
  • 1
  • 13
  • 23