使用volatile类成员进行中断处理

时间:2016-07-27 10:49:41

标签: c++ embedded interrupt

让我们假设它是一些ARM控制器的嵌入式开发。让我们假设我们有一些变量,可以从中断或" mainThread" - (它是"主循环"还是RTOS线程)。在C世界中,在这种情况下应使用volatile关键字,代码可能如下所示:

/* Some subsystem .C file */
static volatile uint8_t state;

void on_main_thread(void) {
    state = 1;     /* Changing state in this context */
}

void on_interrupt(void) {
    state = 0;     /* Changing state from interrupt */
}

uint8_t get_state(void) {
    return state;  /* Getting the state in whatever context */
}
在这种情况下,

volatile关键字至关重要。现在我们公司将一些代码重写为C ++,同样的子系统示例如下所示(我在这里使用枚举来强调问题)

class SomeSubsystem
{
public:
    enum class States
    {
        Off,
        Idle,
        Up,
        Down,
    };


    States getState() const { return mState; }

    void onMainThread(void) {
           mState = States::Idle;     // Changing state in this context
    }

    // Somehow this function is called from the interrupt
    void onInterrupt(void) {
           mState = States::Up;     // Changing state from interrupt
    }
private:
    States mState;   // <-- Here! Volatile? 
//...
};

现在States mState应该是易变的,因为它在不同的上下文之间共享。但是,如果将其设置为不稳定...那么volatile就像瘟疫一样对C ++类起作用,而且必须挥发一切。比如volatile enum class StatesgetState() volatile等。这对我来说并不好看(我错了吗?)

因此。在C ++中处理这种情况的正确方法是什么?

P.S。我会尝试定义这种情况&#34; as:&#34;可能使用来自不同上下文的类成员,如中断和正常的代码执行&#34;

2 个答案:

答案 0 :(得分:1)

如果您只需要在程序中使用SomeSubsystem的单个实例(根据您发布的C代码,我认为这是可行的)。

如果需要多个实例,则可以将mState修改为States数组或某些类似的结构。

class SomeSubsystem
{
public:
    enum class States
    {
        Off,
        Idle,
        Up,
        Down,
    };


    States getState() const { return mState; }

    void onMainThread(void) {
           mState = States::Idle;     // Changing state in this context
    }

    // Somehow this function is called from the interrupt
    void onInterrupt(void) {
           mState = States::Up;     // Changing state from interrupt
    }
// Make mState public in order to access it from the rest of your code
// Otherwise, keep it private and create static set/get functions
public:
    static volatile States mState;   // <-- Here! Volatile? 
//...
};

然后在某处(例如,在SomeSubsystem.cpp中)定义mState

volatile SomeSubsystem::States SomeSubsystem::mState = SomeSubsystem::States::Off;

现在您可以像这样在代码中的任何位置访问mState

SomeSubsystem::mState = SomeSubsystem::States::Off;

答案 1 :(得分:1)

我相信,如果类对象本身是volatile,则只需要volatile限定方法即可。但是,我认为只要设置相关的成员变量volatile就不会有任何问题。我已经在something similar上成功完成了该操作(即,它已编译/运行),达到您要实现的目标。例如:

class SomeSubsystem
{
public:
    ...
    void onMainThread(void); // no volatile qualification necessary
    void onInterrupt(void);  // "
private:
    States volatile mState;  // only make the relevant member variables volatile
}

SomeSubsystem aSubsystem;    // don't make the object volatile
...
aSubsystem.onMainThread();
aSubsystem.onInterrupt();