Я пишу библиотеку Arduino, используя классы С++. Внутри класса у меня есть частная переменная-член, которая является указателем на функцию.
Проблема в том, что мне нужно, чтобы указатель был изменчивым, поскольку указатель на функцию будет установлен вне 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;
Итак, когда бы вы использовали эту вышеописанную технику? В моем случае?