Пиша библиотека на Arduino, използвайки C++ класове. Вътре в класа имам частна членска променлива, която е указател към функция.
Проблемът е, че имам нужда указателят да е непостоянен, тъй като указателят към функцията ще бъде зададен извън ISR и може да бъде променен по време на изпълнение на програмата, но функцията ще бъде извикана вътре< /em> ISR. Следователно мисля, че имам нужда от летлив указател към енергонезависима функция, така ли е?
Както и да е, това, което правя, е да създавам механизъм за разрешаване на персонализирана потребителска функция, която ще се извиква периодично от моята библиотека.
Ето основните неща:
Това само показва основните части, които трябва да видите.
.h файл
class myLib
{
public:
void attachOverflowInterrupt(void (*myFunc)());
private:
volatile void (*userOverflowFunction)(void);
}
.cpp файл
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 файл (показани са само основните части)
void doSomething()
{
}
myLib1.attachOverflowInterrupt(doSomething);
ТОЗИ КОД НЕ СЕ КОМПИЛИРА. Получавам тази грешка:
error: invalid conversion from 'void (*)()' to 'volatile void (*)()' [-fpermissive] userOverflowFunction = myFunc; //attach function
Ако обаче направя това в класа вместо това, той компилира:
class myLib
{
public:
void attachOverflowInterrupt(void (*myFunc)());
//volatile void (*userOverflowFunction)(void); //compile error
void (* volatile userOverflowFunction)(void); //<---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
}
И така, каква е разликата между тези три неща, която кара първото да се провали, но последните 2 се компилират?
volatile void (*userOverflowFunction)(void); //compile error
void (* volatile userOverflowFunction)(void); //compiles
volatile voidFuncPtr userOverflowFunction; //compiles
Направих фоново четене:
- http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword
- Защо е точка-към-волатилен указател, като volatile int * p, полезно?
Допълнителен въпрос:
Първата фонова връзка по-горе гласи:
„Променливите указатели към енергонезависими данни са много редки (мисля, че съм ги използвал веднъж), но по-добре да продължа и да ви дам синтаксиса:“
int * volatile p;
И така, кога бихте използвали горната техника? В моя случай?