I am working with an ARM microcontroller and I have kind of a statemachine with several hundred states. In order to be able to overview it, I have written the code so that it has a 1:1 correspondence with a flowchart specification. I have removed irrelevant code, but basically the code works like this:
Bool_t (*returnTrueOrFalseFunctionPtr) (void);
void (*actionFunctionPtr) (int);
struct myStruct_s {
returnTrueOrFalseFunctionPtr trueOrFalse;
struct myStruct_s* whereToGoIfTrue;
struct myStruct_s* whereToGoIfFalse;
actionFunctionPtr actionsToPerformInThisState[5];
int actionArguments[5];
};
static struct myStruct_s myStateMachine1[];
static struct myStruct_s myStateMachine2[];
static struct myStruct_s myStateMachine3[];
static struct myStruct_s myStateMachine4[];
define myStateMachine1 ms1
define myStateMachine2 ms2
define myStateMachine3 ms3
define myStateMachine4 ms4
static struct myStruct_s myStateMachine1[] = {
{evaluateSomething, &ms1[1], &ms1[3], {startMotor,increaseSpeed, NULL, NULL, NULL, 3,5, 0, 0,0},
{evaluateSomething, &ms1[2], &ms2[0], {stopMotor, openExhaust, decreaseSpeed,NULL, NULL, 1,20,13,0,0},
{evaluateSomething, &ms1[0], &ms1[2], {openRelay, writeStatusToLog,increaseSpeed,NULL, NULL, 4,5, 87,0,0},
{evaluateSomething, &ms1[4], &ms2[1], {blah blah blah... },
{evaluateSomething, &ms2[1], &ms2[2], {blah blah blah... },
};
struct myStruct_s myStateMachine2[] = {
{evaluateSomething, &ms2[1], &ms2[3], { blah blah blah... },
{evaluateSomething, &ms2[2], &ms3[0], { blah blah blah... },
{evaluateSomething, &ms3[1], &ms3[3], { blah blah blah... },
{evaluateSomething, &ms2[4], &ms4[1], { blah blah blah... },
{evaluateSomething, &ms4[0], &ms2[2], { blah blah blah... },
};
I am very happy with this code format, it make it very easy for me to follow where I am in the statemachine/flowchart and decide where to go next. My problem is that I need to port this code to a microcontroller that has little memory, so I would like to memory-optimize the code heavily. I have already replaced my action function pointers with an enum instead:
enum actionsToPerformInThisState_e {
startMotor_,
stopMotor_,
openRelay_,
openExhaust_,
writeStatusToLog_,
decreaseSpeed_,
increaseSpeed_,
NULL_
};
struct myStruct_s {
returnTrueOrFalseFunctionPtr trueOrFalse;
struct myStruct_s* whereToGoIfTrue;
struct myStruct_s* whereToGoIfFalse;
actionsToPerformInThisState_e actionToPerformInThisState0 : 3;
actionsToPerformInThisState_e actionToPerformInThisState1 : 3;
actionsToPerformInThisState_e actionToPerformInThisState2 : 3;
actionsToPerformInThisState_e actionToPerformInThisState3 : 3;
actionsToPerformInThisState_e actionToPerformInThisState4 : 3;
int actionArguments[5];
};
What else can I do to reduce memory usage? Since most states don't use all 5 actions, I would like to have variable number of actions, but the elements in the array must be of same size, or can anybody think of a workaround (I can't place the actions outside the array and have a pointer to them because then the nice readability is lost). What about all pointers (each occupy a whopping 4 bytes!!!) to next states, can anybody think of another way to accomplish this linking? Other suggestions?
-- modified 9-Mar-18 15:17pm.
|