I'm trying to use a flag to see if an event has finished.
Via the debugger, I have seen that the interrupt triggers correctly and does set the value of transmitCompleteI2c
to 1. When I return to the if statement which checks whether or not the flag has been set to 1, it has been reset to 0.
The only 2 locations where i alter the value of transmitCompleteI2c
are after the if statement and in the interrupt routine.
I'm running the following bits of code. The declaration of transmitCompleteI2c
is done in the header file of the class. fireEvent()
is a member function of the class 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;
}
After some extensive digging, it turned out that the address the interrupt routine writes a transmitCompleteI2c
to is not the same as the variable in the class. Even after renaming the variable, it is still happening. Below are the header file and source code of my class.
Header file:
#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);
};
Implementation: Initialization function:
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;
}
Write data function:
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);
}