3

我在寫一個使用C++類的Arduino庫。在類內部,我有一個私有成員變量,它是一個指向函數的指針。指向函數的volatile指針,顯示使用時沒有使用typedef時的編譯錯誤;需要幫助w /「void(* volatile userFunc)(void)」

的問題是,我需要的指針是易失性,因爲指針指向功能將被設置一個ISR,並且可以在程序執行期間被改變,但該函數將被稱爲內部一個ISR。因此,我認爲我需要一個非易失性函數的volatile指針,對嗎?

無論如何,我正在做的是創建一個機制,允許自定義用戶函數,這將定期由我的庫調用。

這裏的基礎知識:

這恰恰說明了主要部分給你看。

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 
} 

那麼,這三件事情之間的區別是什麼,使得第一件失敗,而後者則編譯?

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

背景閱讀中,我已經做了:

  1. http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword
  2. Why is a point-to-volatile pointer, like "volatile int * p", useful?

其他問題:

上述狀態的第一個背景鏈接:
「揮發性足尖RS非易失性數據是非常罕見的(我想我已經使用過一次),但我還是繼續前進,給你的語法:」

int * volatile p; 

所以,當你將使用此技術之上?在我的情況?

+1

有沒有這樣的事情作爲「非易失性函數」。除了非靜態類成員函數,函數不能被限定。 (甚至對於NSMF,該限定適用於隱式實例參數,而不適用於函數本身。) –

+1

編譯器錯誤*被打印。*不被拋出。不工作和不編譯有一個主要的區別。 – EJP

+0

@EJP,點了。 –

回答

3

問題

聲明volatile void (*userOverflowFunction)(void);說,你有一個指針返回類型volatile void的功能。

雖然volatile void是相當的概念(它更容易理解什麼是volatile int),這又是一個有效的返回類型,並且它不匹配的doSomething()返回類型。

解決方案

你說你想要的指針揮發。

用C++翻譯這個結果給出:void (* volatile userOverflowFunction)(void);,這裏有你的第一個發現。

第二次找到你描述的對應於定義一個函數指針類型,然後說它是一個該類型的易失性指針。兩者都是相同的。

編輯:補充說明

您使用的方法是完全的邏輯:你的功能不揮發物(如Kerrek已經在評論中指出的),但你的interupt處理程序需要獲取的價值可能已經以易變的方式改變的指針。

您可能也有興趣閱讀關於std::signal的閱讀。由於你的函數指針不是volatile std::sig_atomic_t,你應該考慮使用你的第二種方法使它成爲原子的:std::atomic<voidFuncPtr> userOverflowFunction;

+0

Christophe,很好的回答,謝謝!volatile指針的設置使得指針變得非常易變,這讓我很困惑,我從來沒有想到,函數可以返回volatile數據類型, ,因爲我以前從未需要它。 –

+0

至於確保原子訪問,此代碼運行在8位Atmel AVR微控制器(ATmega328)上,並且可用的C庫在AVR-Libc中定義。訪問std :: signal a據我所知。相反,確保原子訪問的方式是禁用中斷。我繼續並將代碼添加回到我的問題中來證明這一點。另外,AVR-libc提供了一個原子塊宏來確保原子讀寫訪問:http://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html。但是,在ISR內部,中斷在輸入後會自動禁用。 –

+1

...原子訪問已被確保。 –