Array of function pointers in flash

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

It's me again, playing with forces beyond my understanding

I have a function pointer:

void (*OpMode)(char);

And I have a piece of code that handles menu options like so:

		switch(cmd)
		{
		case 0 : 
			OpMode = Idle ;
			break ;
		case 1 :
			OpMode = SetClock ;
			break ;
		case 2 :
			OpMode = ViewSequence ;
			break ;
		case 3 :
			OpMode = ViewSchedule ;
			break ;
		}

I have in mind that this would be smaller, cleaner, and more sexy if I made an array of functions in flash so I could assign OpMode = FlashArray[cmd] or somesuch. Of course, I could be completely off my nut.

My thinking is:

void (*CommandFunction[4])(char) = {Idle, SetClock,ViewSequence, ViewSchedule};

But how do I put this to __flash? (It's already about 40 bytes smaller than the switch statement.)

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

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

Torby wrote:
But how do I put this to __flash?
Do yourself a favour and make a typedef of the function pointer first. That simplifies all further code using it.

typedef void (*CmdFunc_t)(char);

const CmdFunc_t __flash CommandFunction[4] = { Idle, SetClock, ViewSequence, ViewSchedule };


    CmdFunc_t OpMode = CommandFunction[cmd];
    OpMode(arg);

Stefan Ernst

Last Edited: Thu. Nov 21, 2013 - 12:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yep, that's pretty much how I do embedded menus.
I typically use a double subscript array that looks like this:

	static char (*const menu_fn[4][2])(void) =
	{
		{SetMenu, SetMenu},   // Menu1 MAIN  (Root)
		{SelInput,Nothing},   // Menu2 Inputs Menu  (SL-1)
		{Address, SetBaud},   // Menu3 ModBus Setup (SL-1)
		{SetType, OffsetN}    // Menu4 Inputs Setup    (SL-2)
	};

This syntax is for imagecraft however. The "const" could be replaced with "__flash" but I have a setting that does it.

The way the double subscript array works is that each row is a menu and each column is a menu option. You then just keep track of which menu you are currently "in" and use the selection information to chose which function in that row to execute.

The drawback with using this method, is that all menu functions much have the same prototype signature (not big deal) but also the array is fixed in size and so not dynamic. (no good for file sys browsing) Also there is some overhead in the array size where unused options are present though again only a few bytes per option.

Note the SetMenu() function is used to navigate thru by selecting the submenus and the Nothing() function fills the array when less than maximum number of options are available.

Steve

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

Quote:

The "const" could be replaced with "__flash"

In avr-gcc that supports __flash, you must always use "const" as well as __flash not just as an alternative to it.

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

Quote:

CmdFunc_t OpMode = CommandFunction[cmd];

Do yourself another favour and check limits first. And perhaps even ensure that all the function pointers are "good" (or at least not null).

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Ah. With a typedef, it does let me put the const in __flash.

Thanks.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

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

Quote:

With a typedef, it does let me put the const in __flash.

I think you'll find that it was possible without typedef. It's just it's a far more complex and involved syntax (I had to look this one up as I'd always have used the much easier typedef):

void Idle(char c) {};
void SetClock(char c) {};
void ViewSequence(char c) {};
void ViewSchedule(char c) {};

#if 0
  typedef void (*CmdFunc_t)(char);
  const CmdFunc_t __flash CommandFunction[4] = { Idle, SetClock, ViewSequence, ViewSchedule };
  CmdFunc_t OpMode;
#else
  void(* const __flash CommandFunction[4])(char) = { Idle, SetClock, ViewSequence, ViewSchedule };
  void (*OpMode)(char);
#endif

int main(void) {
  int cmd = 2;
  OpMode = CommandFunction[cmd];
}

both these (#if 0/1) generate the same .s file.

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

Um. I think I'll stick with the typedef.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

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

hehe

 

And thank you all for answering the same question when I asked it again

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead.