C++ 变量在中断后的中断重置期间发生变化

标签 c++ c++11 interrupt

我正在尝试使用标志来查看事件是否已结束。

通过调试器,我看到中断正确触发并将 transmitCompleteI2c 的值设置为 1。当我返回检查标志是否已设置为的 if 语句时1,已重置为0。

我更改 transmitCompleteI2c 值的唯一 2 个位置是在 if 语句之后和中断例程中。

我正在运行以下代码。 transmitCompleteI2c 的声明是在类的头文件中完成的。 fireEvent() 是类 I2c 的成员函数。

volatile uint8_t transmitCompleteI2c;

void I2c::foo() {
    if (transmitCompleteI2c) {
        transmitCompleteI2c = 0;

        // trigger event which sets transmitComplete back to 0 when done
        fireEvent();
    }
}

void I2c::sendHandler(XIic *InstancePtr) {
    transmitCompleteI2c = 1;
}

经过深入挖掘后,发现中断例程写入 transmitCompleteI2c 的地址与类中的变量不同。即使在重命名变量之后,它仍然在发生。下面是我的类的头文件和源代码。

头文件:

#define SLAVE_ADDRESS   0xA0/2
#define SEND_COUNT      16
#define RECEIVE_COUNT   16
#define IIC_INTR_ID     XPAR_FABRIC_AXI_IIC_0_IIC2INTC_IRPT_INTR
#define IIC_DEVICE_ID   XPAR_AXI_IIC_0_DEVICE_ID
#define INTC_DEVICE_ID  XPAR_SCUGIC_SINGLE_DEVICE_ID


class I2c{
private:
    void sendHandler(void* InstancePtr, int);
    void receiveHandler(XIic* InstancePtr, int);
    void statusHandler(XIic* InstancePtr, int);

    XIic_Config* configPtr;
    const XScuGic& intcInterrupt;
    XIic iicDevice;
    int status;
    uint8_t writeBuffer[SEND_COUNT];
    uint8_t readBuffer[RECEIVE_COUNT];
    volatile uint8_t transmitCompleteI2c, receiveComplete;
    volatile bool test;    

public:
    I2c() : intcInterrupt{IntcInstance} {};
    uint8_t initialize();
    int writeData(u16 ByteCount);
    int readData(u8 *BufferPtr, u16 ByteCount);    

};

实现: 初始化函数:

uint8_t I2c::initialize() {
    // init driver
    configPtr = XIic_LookupConfig(IIC_DEVICE_ID);
    XIic_CfgInitialize(&iicDevice, configPtr, configPtr->BaseAddress);


    //init interrupt system
    XScuGic_SetPriorityTriggerType((XScuGic*) &intcInterrupt, IIC_INTR_ID, 0xA0, 0x3);

    status = XScuGic_Connect((XScuGic*) &intcInterrupt, IIC_INTR_ID, (Xil_ExceptionHandler) XIic_InterruptHandler, &iicDevice);

    XScuGic_Enable((XScuGic*) &intcInterrupt, IIC_INTR_ID);

    Xil_ExceptionInit();
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler, &IntcInstance);

    Xil_ExceptionEnable();

    // set transmit flag
    transmitCompleteI2c = true;
    xil_printf("%08x\n", &transmitCompleteI2c);

    // attach interrupts to i2c device
    XIic_SetSendHandler(&iicDevice, &iicDevice, (XIic_Handler) (&I2c::sendHandler));
    XIic_SetRecvHandler(&iicDevice, &iicDevice, (XIic_Handler) &I2c::receiveHandler);
    XIic_SetStatusHandler(&iicDevice, &iicDevice, (XIic_StatusHandler) &I2c::statusHandler);

    // set slave address
    status = XIic_SetAddress(&iicDevice, XII_ADDR_TO_SEND_TYPE, SLAVE_ADDRESS);

    // start device
    status = XIic_Start(&iicDevice);
    if (status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    return 0;
}

写数据函数:

int I2c::writeData(u16 ByteCount) {

    xil_printf("%08x\n", &transmitCompleteI2c);

    /*
     * Set flag
     */
    transmitCompleteI2c = false;

    /*
     * Send the data
     */
    status = XIic_MasterSend(&iicDevice, &writeBuffer[0], 6);
    if (status != XST_SUCCESS) {
        xil_printf("%d\n", status);
        return XST_FAILURE;
    }

    return XST_SUCCESS;
}

中断程序:

void I2c::sendHandler(void *InstancePtr, int byteCount) {
    transmitCompleteI2c = true;
    xil_printf("%08x\n", &transmitCompleteI2c);
}

最佳答案

"...it should all be in the same class"

但是 transmitCompleteI2c 不是静态成员,所以它必须是同一个对象,而不仅仅是同一个类。 I2c 的每个实例都有自己的每个非静态数据成员的拷贝。

如果您知道只需要一个拷贝,您可以将其设置为静态(这有效地使它成为一个全局的,尽管仍然只能通过 I2c 访问)——但不要忘记它需要一个非-内联定义。

或者,您需要找出存在哪些 I2c 对象,以及它们的创建位置。如果您无法确定它们的创建位置,您可以使用日志记录(或设置断点)来实现所有构造函数和赋值运算符重载。

关于C++ 变量在中断后的中断重置期间发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38610541/

相关文章:

c++ - Lambda 返回引用会导致段错误 - 为什么?

python - SIGINT 在 python 中不可捕获

javascript - 在 Node.js C++ 插件中发出事件

c++ - 原子变量是无锁的吗?

c++ - openCV中SIFT检测到的关键点,其大小是相关区域的半径还是直径?

c++ - std::future_error:无关联状态

java - 音乐播放时中断线程

linux - 为什么在有可用的 PIT 时需要 TSC

c++ - 从流中读取以初始化只读变量

c++ - 如何在C中写入特定地址的数据