function pointer

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

Hi..all,

I have some problem on function pointer in winavr. On 8051 C compiler I can do...

/* Pointer to the function (must be a 'void (void)'function) */
void (code * pFunc)(void);

How to do like this on winavr ?

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

Here's an example:

void Ds1306DisplayDate (u08 year, u08 month, u08 date, void(*fn)(char)) {
  if ((month >> 4) == 0)
    (*fn) (' ');
  else
    (*fn) ((month >> 4)+'0');
  (*fn) ((month & 0x0F)+'0');
  (*fn) ('/');
  (*fn) ((date >> 4)+'0');
  (*fn) ((date & 0x0F)+'0');
  (*fn) ('/');
  (*fn) ((year >> 4)+'0');
  (*fn) ((year & 0x0F)+'0');
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

firmware wrote:

/* Pointer to the function (must be a 'void (void)'function) */
void (code * pFunc)(void);

How to do like this on winavr ?


Lose the word 'code' in there. As I don't know the 8051 compiler I've no idea what purpose it might serve but it's the bit of that which is non-standard.

Cliff

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

clawson wrote:
Lose the word 'code' in there. As I don't know the 8051 compiler I've no idea what purpose it might serve but it's the bit of that which is non-standard.
I don't know the compiler, either. My guess was it was a non-standard extension to inform the compiler the pointer referred to the flash (code) memory space.

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

Quote:
I don't know the compiler, either. My guess was it was a non-standard extension to inform the compiler the pointer referred to the flash (code) memory space.

Yes, "code" for 8051 C complier refer to flash memory. I would like to instead this. I just found, It seem can do like..
Quote:
void (PROGMEM * pFunc)(void);

thanks.

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

Obviously, the object being pointed to is a function, so it implicitly must reside in Flash.

But, do you want the pointer itself to physically reside in Flash too? If not, then the "PROGMEM" in that declaration is a useless deviance from Standard C, and can appropriately be omitted.

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

Quote:
But, do you want the pointer itself to physically reside in Flash too? If not, then the "PROGMEM" in that declaration is a useless deviance from Standard C, and can appropriately be omitted.

Yes, I want to point in flash, need to be point to the function.

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

Just so we're clear, there is a difference between a pointer residing in Flash, and pointing to something in Flash.

The first case would be implemented like this:

void (* pFunc)(void) PROGMEM = &myfunc;

And it results in a function pointer that resides in Flash, and therefore its target can never change and must be initialized at compile time. (In this case, it is initialized to point to the hypothetical function "myfunc".)

The second case would be implemented like this:

void (* pFunc)(void);

And it results in a function pointer that resides in SRAM, therefore its target can change at will while the program runs and it doesn't necessarily have to be initialized.

In both cases, the target of the pointer must, by definition, be a function residing in Flash due to the nature of the AVR architecture.

Regardless, the "(PROGMEM * pFunc)" syntax is always unnecessary in AVR-GCC, and since it is a deviance from Standard C it should be avoided.

It's probably just a problem of us misunderstanding each other's English usage.

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

I need to do like this...

void(PROGMEM *pTask)(void);
void Add_Task(void (PROGMEM* pFunction)());	
void LED_Flash_Update (void);
 
void main()
{
  Add_Task(LED_Flash_Update);

  while(1) 
  {
    (*pTask)(); 
  }
}
//////////////////////////////////////////////////////
void Add_Task(void (PROGMEM* pFunction)())
{
  pTask = pFunction;
}
//////////////////////////////////////////////////////
void LED_Flash_Update (void) {
	PORTB ^= (1<<PB0);
}

In my full version of software, I need to change "Add_Task(LED_Flash_Update)" function for point to others function many times.

I try to test 2 ways.
First : use void(PROGMEM *pTask)(void);
second : use void(*pTask)(void);

Both are work. Which way is better ?

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

firmware wrote:
I try to test 2 ways.
First : use void(PROGMEM *pTask)(void);
second : use void(*pTask)(void);

Both are work. Which way is better ?

lfmorrison already answered that:
lfmorrison wrote:
Regardless, the "(PROGMEM * pFunc)" syntax is always unnecessary in AVR-GCC, and since it is a deviance from Standard C it should be avoided.
Additionally, the example usage I posted on this thread does not use the unnecessary and non-standard PROGMEM qualifier.

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

Quote:
Regardless, the "(PROGMEM * pFunc)" syntax is always unnecessary in AVR-GCC, and since it is a deviance from Standard C it should be avoided.

Regards,
Steve A.

The Board helps those that help themselves.

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

strange, why I never got any warning from compiler when use "void(PROGMEM *pTask)(void)" .

Thanks.

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

Not too strange. Invalid constructs do not always cause problems. However, different versions of WinAVR might either give you compile-time warnings or errors, or silently compile malfunctioning code. Its behavior with the non-standard construct you created is not specified.