Part Number: MSPM0G3507-Q1
I am running into an issue where I am trying to use the MSPM0G3507-Q1 with TI-Drivers and FreeRTOS. Specifically, I am trying to pass in a 16K buffer to the I2C_transfer function to do a continuous Write ... data ... STOP transaction.
The problem is that in the middle of the transaction, the MSPM0+ seems to be giving a repeated start at the bounds of the burst lengths (255).... which my peripheral device doesn't like:

Looking into the implemntation code (specifically I2CMSPM0.c), I think the issue is in the I2CMSPM0_primeWriteBurst function:
static void I2CMSPM0_primeWriteBurst(
I2CMSPM0_Object *object, I2CMSPM0_HWAttrs const *hwAttrs)
{
/* Wait until bus is available */
I2C_waitTillBusAvailable(hwAttrs);
/* Disable the burst before setting up the new transaction */
DL_I2C_disableControllerBurst(hwAttrs->i2c);
/* Determine the size of this burst */
if (object->writeCount > I2CMSPM0_MAX_BURST) {
object->burstCount = I2CMSPM0_MAX_BURST;
} else {
object->burstCount = object->writeCount;
}
/* Write burst length */
DL_I2C_setTransactionLength(hwAttrs->i2c, object->burstCount);
/* If we will be sending multiple bursts */
if (object->readCount || object->writeCount > I2CMSPM0_MAX_BURST) {
DL_I2C_disableStopCondition(hwAttrs->i2c);
} else {
DL_I2C_enableStopCondition(hwAttrs->i2c);
}
/* Only generate a start condition if the burst hasn't started */
if (!object->burstStarted) {
object->burstStarted = true;
}
/*Before filling the FIFO, we need to clear the interrupt else it will trigger interrupt immediately*/
DL_I2C_clearInterruptStatus(
hwAttrs->i2c, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
/* Fill transmit FIFO. This will modify the object counts */
I2CMSPM0_fillTransmitFifo(object, hwAttrs);
/* Enable TXFIFOEMPTY interrupt and other standard transfer interrupts */
DL_I2C_enableInterrupt(hwAttrs->i2c,
DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER |
DL_I2C_INTERRUPT_CONTROLLER_TX_DONE |
DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY | I2CMSPM0_TRANSFER_INTS);
/* Set the target Address */
DL_I2C_setTargetAddress(
hwAttrs->i2c, object->currentTransaction->targetAddress);
/* Set the controller direction */
DL_I2C_setControllerDirection(
hwAttrs->i2c, DL_I2C_CONTROLLER_DIRECTION_TX);
/* Enable the start condition */
DL_I2C_enableStartCondition(hwAttrs->i2c);
/* Disable the manual ACK, hardware will ack automatically */
DL_I2C_disableControllerACK(hwAttrs->i2c);
/* Enable the burst run */
DL_I2C_enableControllerBurst(hwAttrs->i2c);
}
Specifically, burstStarted gets set, but it doesn't actually get checked/used anywhere. The DL_I2C_enableStartCondition function always gets called regardless. If I change it to this:
/*
* ======== I2CMSPM0_primeWriteBurst =======
*/
static void I2CMSPM0_primeWriteBurst(
I2CMSPM0_Object *object, I2CMSPM0_HWAttrs const *hwAttrs)
{
/* Wait until bus is available */
I2C_waitTillBusAvailable(hwAttrs);
/* Disable the burst before setting up the new transaction */
DL_I2C_disableControllerBurst(hwAttrs->i2c);
/* Determine the size of this burst */
if (object->writeCount > I2CMSPM0_MAX_BURST) {
object->burstCount = I2CMSPM0_MAX_BURST;
} else {
object->burstCount = object->writeCount;
}
/* Write burst length */
DL_I2C_setTransactionLength(hwAttrs->i2c, object->burstCount);
/* If we will be sending multiple bursts */
if (object->readCount || object->writeCount > I2CMSPM0_MAX_BURST) {
DL_I2C_disableStopCondition(hwAttrs->i2c);
} else {
DL_I2C_enableStopCondition(hwAttrs->i2c);
}
/* Only generate a start condition if the burst hasn't started */
if(object->burstStarted == true)
{
DL_I2C_disableStartCondition(hwAttrs->i2c);
}
else
{
DL_I2C_enableStartCondition(hwAttrs->i2c);
}
if (!object->burstStarted) {
object->burstStarted = true;
}
/*Before filling the FIFO, we need to clear the interrupt else it will trigger interrupt immediately*/
DL_I2C_clearInterruptStatus(
hwAttrs->i2c, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
/* Fill transmit FIFO. This will modify the object counts */
I2CMSPM0_fillTransmitFifo(object, hwAttrs);
/* Enable TXFIFOEMPTY interrupt and other standard transfer interrupts */
DL_I2C_enableInterrupt(hwAttrs->i2c,
DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER |
DL_I2C_INTERRUPT_CONTROLLER_TX_DONE |
DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY | I2CMSPM0_TRANSFER_INTS);
/* Set the target Address */
DL_I2C_setTargetAddress(
hwAttrs->i2c, object->currentTransaction->targetAddress);
/* Set the controller direction */
DL_I2C_setControllerDirection(
hwAttrs->i2c, DL_I2C_CONTROLLER_DIRECTION_TX);
/* Enable the start condition */
/* Disable the manual ACK, hardware will ack automatically */
DL_I2C_disableControllerACK(hwAttrs->i2c);
/* Enable the burst run */
DL_I2C_enableControllerBurst(hwAttrs->i2c);
}
.... specifically adding this:
/* Only generate a start condition if the burst hasn't started */
if(object->burstStarted == true)
{
DL_I2C_disableStartCondition(hwAttrs->i2c);
}
else
{
DL_I2C_enableStartCondition(hwAttrs->i2c);
}
if (!object->burstStarted) {
object->burstStarted = true;
}
.... everything appears to work and I can write the entire 16K without issue. I just copy the I2CMSPM0.c file into my workspace and all the symbols overwrite the ones from the SDK library.
I just wanted to make sure I wasn't missing anything or misusing the driver in the first place. For firmware updates, I generally have to write >256byte transactions without repeated starts/stops.
Best Regards,
Tim