2016-07-27 6 views
0

Ich versuche, ein Flag zu verwenden, um zu sehen, ob ein Ereignis beendet ist. Über den Debugger habe ich gesehen, dass der Interrupt korrekt ausgelöst wird und den Wert transmitCompleteI2c auf 1 setzt. Wenn ich zur if-Anweisung zurückkehre, die prüft, ob das Flag auf 1 gesetzt wurde oder nicht, wurde es zurückgesetzt zu 0.C++ - Variable geändert während Interrupt zurückgesetzt nach Interrupt

Die einzigen 2 Orte, wo ich den Wert von transmitCompleteI2c ändern, sind nach der if-Anweisung und in der Interrupt-Routine.

Ich führe die folgenden Bits Code. Die Deklaration von transmitCompleteI2c erfolgt in der Header-Datei der Klasse. fireEvent() ist eine Mitgliedsfunktion der Klasse 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; 
} 

Nach einiger umfangreichen Graben, es stellte sich heraus, dass die Adresse der Interrupt-Routine ein transmitCompleteI2c schreibt nicht die gleiche wie die Variable in der Klasse ist. Auch nach dem Umbenennen der Variablen passiert es immer noch. Im Folgenden finden Sie die Header-Datei und den Quellcode meiner Klasse.

Headerdatei:

#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);  

}; 

Implementierung: Initialisierung Funktion:

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; 
} 

Daten schreiben Funktion:

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; 
} 

Interrupt-Routine:

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

Warum verwenden Sie invertierte Logik für sendeComplete? Wäre es nicht sinnvoller, es als bool zu deklarieren und nach Abschluss der Übertragung auf wahr zu setzen? Natürlich hilft das nicht wirklich bei deinem Problem, aber trotzdem ... –

+0

@ H.Guijt Ja, das stimmt. Ändern Sie es in der Frage und Code für bessere Lesbarkeit – Etruscian

+0

Dieser Teil des Codes zeigt sich nicht mit evedence, ist dieser Thread sicher? Eine solche Verwendung von Variablen provoziert Gefahren. –

Antwort

2

„... es soll in der gleichen Klasse sein“

aber transmitCompleteI2c ist kein statisches Element, so hat es das gleiche Objekt sein, nicht nur die gleiche Klasse . Jede Instanz von I2c erhält eine eigene Kopie jedes nicht statischen Datenelements.

Sie können es nur statisch machen, wenn Sie wissen, dass nur eine Kopie erforderlich ist (dies macht es tatsächlich zu einem globalen, obwohl immer noch nur zugänglich durch) - aber vergessen Sie nicht, es braucht eine einzige Nicht-Inline-Definition.

Alternativ müssen Sie herausfinden, welche I2c Objekte existieren und wo sie erstellt werden. Sie können alle Konstruktor- und Zuweisungsoperator-Überladungen mit der Protokollierung implementieren (oder Haltepunkte setzen), wenn Sie Schwierigkeiten haben, herauszufinden, wo sie erstellt werden.

+0

Richtig, aber das erklärt nicht, warum genau das in einer anderen Klasse mit dem gleichen Code funktioniert, abgesehen von einigen protokollspezifischen Änderungen . – Etruscian

+1

Ich dachte, du hast gesagt, dass es mit dem _same_ Code funktioniert hat? Wie auch immer, die Antwort liegt in dem, was Instanzen dieser Klasse erstellt, speichert, kopiert usw., nicht innerhalb der Klasse selbst. – Useless

+0

Diese Klasse hat vorher mit demselben Code funktioniert. In meinem Kommentar zu Ihrer Lösung habe ich über eine andere Klasse gesprochen, die ebenfalls den gleichen Code hat, aber ein anderes Protokoll implementiert. – Etruscian