Volatile Pointer to a function displaying a compilation error when used without a typedef; need help w / "void (* volatile userFunc) (void)"

I am writing Arduino library using C ++ classes. Inside the class, I have a private member variable that is a function pointer.

The problem is that I need the pointer to be volatile since the function pointer will be set outside the ISR and can be changed at runtime, but the function will be called inside the ISR. Hence, I think I need a volatile pointer to a non-volatile function, right?

Anyway, I am creating a mechanism to provide a custom function that will be called periodically by my library.

Here's the basics:

It just shows the main parts that you can see.

.h file

class myLib
{
  public:
  void attachOverflowInterrupt(void (*myFunc)());

  private:
  volatile void (*userOverflowFunction)(void);
}  

      

.cpp file

void myLib::attachOverflowInterrupt(void (*myFunc)())
{
  //ensure atomic access
  uint8_t SREGbak = SREG; //back up interrupt state
  noInterrupts(); //interrupts off

  userOverflowFunction = myFunc; //attach function //<--the part that matters to my problem here

  SREG = SREGbak; //restore interrupt state 
}

//inside the interrupt, their function is called essentially like this:
this->userOverflowFunction();

      

Arduino.ino file (only the main parts shown)

void doSomething()
{
}

myLib1.attachOverflowInterrupt(doSomething);

      

THIS CODE WILL NOT Compile. I am getting this error:

error: invalid conversion from 'void (*)()' to 'volatile void (*)()' [-fpermissive] userOverflowFunction = myFunc; //attach function

      

If I do this in a class instead, it compiles:

class myLib
{
  public:
  void attachOverflowInterrupt(void (*myFunc)());
  //volatile void (*userOverflowFunction)(void); //compile error
  void (* volatile userOverflowFunction)(void); //<---compiles
} 

      

OR, if I do this instead, it compiles:

typedef void (*voidFuncPtr)(void);

class myLib
{
  public:
  void attachOverflowInterrupt(void (*myFunc)());
  //volatile void (*userOverflowFunction)(void); //compile error
  //void (* volatile userOverflowFunction)(void); //compiles
  volatile voidFuncPtr userOverflowFunction; //<---compiles
} 

      

So what is the difference between these three things that make the first one fail, but the second one compiles?

volatile void (*userOverflowFunction)(void); //compile error
void (* volatile userOverflowFunction)(void); //compiles
volatile voidFuncPtr userOverflowFunction; //compiles

      

Background read I did:

Additional question:

The first background link above states:
"Volatile pointers to non-volatile data are very rare (I think I've used them once), but I'd better go and give you the syntax:"

int * volatile p;

      

So when would you use this technique above? In my case?

+3


source to share


1 answer


Problem

The statement volatile void (*userOverflowFunction)(void);

states that you have a pointer to a function that returns a type volatile void

.

While volatile void

quite conceptual (easier to understand what is volatile int

), it is still a valid return type and does not match the return type doSomething()

.

Decision

You said you want the pointer to be volatile.



Translating this to C ++ gives: void (* volatile userOverflowFunction)(void);

and here you have your first conclusion.

The second detection you describe matches the type definition of a function pointer and then says that it is a mutable pointer of that type. Both are equivalent.

Edit: additional notes

The approach you are using is perfectly logical: your function is not mutable (as Kerrek already pointed out in the comments), but your interupt handler should receive a pointer value that can be mutable in a mutable way.

You may also be interested in learning about std::signal

. Since your function pointer is not volatile std::sig_atomic_t

, you should consider making it atomic using your second approach:std::atomic<voidFuncPtr> userOverflowFunction;

+3


source







All Articles