This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Part Number: MSP432P401R
Tool/software: Code Composer Studio
Hi,
i am using the MSp432 to read a sensor on I2C (EUSCI_B1_BASE) and on the same time read an other sensor on SPI (EUSCI_A1_BASE + DMA_CH2_EUSCIA1TX + DMA_CH3_EUSCIA1RX).
The Sensor_SPI gives me an interrupt on GPIO, i activate the DMA_CH2_EUSCIA1TX and get the DMA_CH3_EUSCIA1RX interurpt that data is ready to be read.
This is working fine.
The SPI_I2C gives an interrupt on GPIO and here i set a flag to read the data later. So on the I2C by reading the values if have to use EUSCIB1_IRQHandler to EUSCI_B_I2C_RECEIVE_INTERRUPT0 or EUSCI_B_I2C_TRANSMIT_INTERRUPT0. And here is the problem that it gets stock here:
I2C_masterSendMultiByteStopWithTimeout(EUSCI_B1_BASE,1000); or I2C_masterSendMultiByteStopWithTimeout(EUSCI_B1_BASE,1000);
if the Sensor_SPI is running simultaneously.
If i dont use the DMA on SPI and just set a flag and read the value later it works but i miss some Sensor_SPI data. The DMA set up is the bestone because i dont loose any information but it conflicts with my I2C EUSCIB1_IRQHandler some how.
Any idea?
I am concerned about the logic of the API and I will look into this further. So you are not using interrupts when calling the API?
Thanks,
Chris
bool I2C_masterSendMultiByteStopWithTimeout(uint32_t moduleInstance, uint32_t timeout) { ASSERT(timeout > 0); //If interrupts are not used, poll for flags if (!BITBAND_PERI(EUSCI_B_CMSIS(moduleInstance)->IE, EUSCI_B_IE_TXIE0_OFS)) { //Poll for transmit interrupt flag. while ((!BITBAND_PERI(EUSCI_B_CMSIS(moduleInstance)->IFG, EUSCI_B_IFG_TXIFG0_OFS)) && --timeout) ; //Check if transfer timed out if (timeout == 0) return false; } //Send stop condition. BITBAND_PERI(EUSCI_B_CMSIS(moduleInstance)->CTLW0, EUSCI_B_CTLW0_TXSTP_OFS) = 1; return 0x01; }
Hi Chris,
i am using I2C Interrupt. Here is my code:
bool readBurstI2C_1(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint32_t ui32ByteCount) { /* Todo: Put a delay */ /* Wait until ready */ int counterGetOut=0; while (MAP_I2C_isBusBusy(EUSCI_B1_BASE)) { counterGetOut++; if(counterGetOut>=10000) return false; } /* Assign Data to local Pointer */ pData_1 = Data; /* Disable I2C module to make changes */ MAP_I2C_disableModule(EUSCI_B1_BASE); /* Setup the number of bytes to receive */ i2cConfig1.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; g_ui32ByteCount_1 = ui32ByteCount; burstMode_1 = true; MAP_I2C_initMaster(EUSCI_B1_BASE, (const eUSCI_I2C_MasterConfig *)&i2cConfig1); /* Load device slave address */ MAP_I2C_setSlaveAddress(EUSCI_B1_BASE, ui8Addr); /* Enable I2C Module to start operations */ MAP_I2C_enableModule(EUSCI_B1_BASE); /* Enable master STOP and NACK interrupts */ MAP_I2C_enableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_STOP_INTERRUPT +EUSCI_B_I2C_NAK_INTERRUPT); /* Set our local state to Busy */ ui8Status_1 = eUSCI_BUSY_1; /* Send start bit and register */ MAP_I2C_masterSendMultiByteStart(EUSCI_B1_BASE,ui8Reg); /* Enable master interrupt for the remaining data */ MAP_Interrupt_enableInterrupt(INT_EUSCIB1); /* NOTE: If the number of bytes to receive = 1, then as target register is being shifted * out during the write phase, UCBxTBCNT will be counted and will trigger STOP bit prematurely * If count is > 1, wait for the next TXBUF empty interrupt (just after reg value has been * shifted out */ counterGetOut=0; while(ui8Status_1 == eUSCI_BUSY_1) { if(MAP_I2C_getInterruptStatus(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0)) { ui8Status_1 = eUSCI_IDLE_1; } else { counterGetOut++; if(counterGetOut>=4800) return false; } } ui8Status_1 = eUSCI_BUSY_1; /* Turn off TX and generate RE-Start */ MAP_I2C_masterReceiveStart(EUSCI_B1_BASE); /* Enable RX interrupt */ MAP_I2C_enableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0); /* Wait for all data be received */ counterGetOut=0; while(ui8Status_1 == eUSCI_BUSY_1) { __no_operation(); counterGetOut++; if(counterGetOut>=4800) return false; } /* Disable interrupts */ MAP_I2C_disableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_STOP_INTERRUPT +EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_RECEIVE_INTERRUPT0); MAP_Interrupt_disableInterrupt(INT_EUSCIB1); if(ui8Status_1 == eUSCI_NACK_1) { return(false); } else { return(true); } }
And here is my Interrupt routine code for I2C:
void EUSCIB1_IRQHandler(void) { uint_fast16_t status; status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B1_BASE); MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, status); if (status & EUSCI_B_I2C_NAK_INTERRUPT) { /* Generate STOP when slave NACKS */ // MAP_I2C_masterSendMultiByteStop(EUSCI_B1_BASE); /* Clear any pending TX interrupts */ MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0); /* Set our local state to NACK received */ ui8Status_1 = eUSCI_NACK_1; } if (status & EUSCI_B_I2C_START_INTERRUPT) { /* Change our local state */ ui8Status_1 = eUSCI_START_1; } if (status & EUSCI_B_I2C_STOP_INTERRUPT) { /* Change our local state */ ui8Status_1 = eUSCI_STOP_1; } if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0) { if (burstMode_1) { //ui8DummyRead_2= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE); /* RX data */ *pData_1++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE); g_ui32ByteCount_1--; if (g_ui32ByteCount_1 == 1) { burstMode_1 = false; /* Generate STOP */ //MAP_I2C_masterSendMultiByteStop(EUSCI_B1_BASE); I2C_masterSendMultiByteStopWithTimeout(EUSCI_B1_BASE,1000);//1000 } } else { //*pData_1++ = EUSCI_B_CMSIS(EUSCI_B1_BASE)->RXBUF & 0x00FF; //MAP_I2C_masterSendMultiByteStop(EUSCI_B1_BASE); I2C_masterSendMultiByteStopWithTimeout(EUSCI_B1_BASE,1000);//1000 *pData_1++ = UCB1RXBUF; } } if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0) { ui8Status_1 = eUSCI_IDLE_1;//ui8Status_1 == eUSCI_IDLE_1; } }
Any idea? Is there a way to do this on DMA or improve this?
Edit: The only way to make I2C work with SPI simultaneously, i really have to disable GPIO Interrupt from SPI once i use I2C and after enable it again
**Attention** This is a public forum