ISM330BX + MSPM0G3519 over I²C: Software Hang/Reset with Both Polling and Interrupt-Based Communication
- August 4, 2026
- 4 replies
- 74 views
Configuration:
- I2C address: 0x6A
- Bus speed: 100kHz (standard mode)
- ODR: 1920Hz for both XL and GY (
ISM330BX_XL_ODR_AT_1920Hz,ISM330BX_GY_ODR_AT_1920Hz) - Full scale: ±125dps gyro, ±4G accel
- Reading a 14-byte burst starting at register 0x20 (TEMP + GYRO + ACCEL) once every 10ms, from our control loop.
- The application currently checks the IMU every 10ms.
My intention is:
- Every 10ms, determine whether a fresh IMU sample is available.
- If fresh data is available, start one interrupt-driven burst read (gyro + accel).
- When the transfer completes, update the application variables once.
- Ignore intermediate samples produced by the IMU between 10ms periods.
Polling-based implementation
Initially, we have implemented the IMU driver using a polling-based I²C implementation (partially based on an open-source GitHub driver). During long-duration testing, the application hung/resetting inside the blocking I²C loops. Code for this method is attached in attachment 1.
Interrupt-based implementation
To overcome the blocking behavior, we redesigned the IMU driver using an interrupt-driven (non-blocking) I²C implementation. Although this implementation eliminates the blocking polling loops, the application still hangs/resets during long-duration testing. The code for this implementation is attached as Attachment 2.
Sysconfig settings (I2C):
I2C1.basicEnableController = true;
I2C1.$name = "I2C_2";
I2C1.advDigitalGlitchFilter = "CLOCKS_1";
I2C1.enableDMAEvent1 = false;
I2C1.enableDMAEvent2 = false;
I2C1.basicTargetSecAddressEnable = true;
I2C1.intController = ["ARBITRATION_LOST","NACK","RXFIFO_TRIGGER","RX_DONE","TXFIFO_TRIGGER","TX_DONE"];
I2C1.timeoutACount = 2;
I2C1.peripheral.$assign = "I2C2";
I2C1.peripheral.sdaPin.$assign = "PC3";
I2C1.peripheral.sclPin.$assign = "PC2";
I2C1.sdaPinConfig.hideOutputInversion = scripting.forceWrite(false);
I2C1.sdaPinConfig.onlyInternalResistor = scripting.forceWrite(false);
I2C1.sdaPinConfig.passedPeripheralType = scripting.forceWrite("Digital");
I2C1.sdaPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric20";
I2C1.sclPinConfig.hideOutputInversion = scripting.forceWrite(false);
I2C1.sclPinConfig.onlyInternalResistor = scripting.forceWrite(false);
I2C1.sclPinConfig.passedPeripheralType = scripting.forceWrite("Digital");
I2C1.sclPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric21";
Questions
- Based on the attached polling-based and interrupt-driven implementations, is there any issue in our overall communication sequence or software architecture that could lead to intermittent software hangs or resets?
- Is the current approach of checking the
STATUS_REG (0x1E)every 10ms before initiating a burst read the recommended method for synchronizing with the ISM330BX, or is there a better approach? - When executing the I²C read operation in the 10 ms task,
DL_I2C_getControllerStatus(),DL_I2C_startFlushControllerTXFIFO(), andDL_I2C_isControllerTXFIFOEmpty()intermittently fail. Why does this happen, and what modifications are required to resolve the issue? - Are there any specific timing requirements, delays, register access sequences, or configuration settings that should be considered when communicating with the ISM330BX over I²C to ensure reliable operation?
- After reviewing the attached code, are there any portions of the implementation that should be modified or improved to align with ST's recommended software practices for the ISM330BX?
