Part Number: MSPM0G3507
Other Parts Discussed in Thread: SYSCONFIG
Tool/software:
As the title, the MCU was used as a slave, and I2C could be read and written by the external host device normally.
However, accidentally pulling the SCL low for a short period of time (about 1 second) and then releasing it, the SCL surprisingly cannot be restored(keep low forever).
After investigation, it was found that there is an issue with M0G3507 (restarting the host device is ineffective, restarting the slave will restore).
Turn on all interrupt flags, unable to respond, even TimeoutA setting cannot respond.
At present, I don't know the cause of this problem, and 3507, as a slave, does not have a flag bit to perceive this anomaly.
Observing phenomenon M0G3507, the slave has pulled SCL low(0 level).

SYSCONFIG_WEAK void SYSCFG_DL_I2C_init(void) {
DL_I2C_setClockConfig(I2C_INST,
(DL_I2C_ClockConfig *) &gI2CClockConfig);
DL_I2C_disableAnalogGlitchFilter(I2C_INST);
/* Configure Target Mode */
DL_I2C_setTargetOwnAddress(I2C_INST, I2C_TARGET_OWN_ADDR);
DL_I2C_setTargetTXFIFOThreshold(I2C_INST, DL_I2C_TX_FIFO_LEVEL_BYTES_1);
DL_I2C_setTargetRXFIFOThreshold(I2C_INST, DL_I2C_RX_FIFO_LEVEL_BYTES_1);
DL_I2C_enableTargetTXEmptyOnTXRequest(I2C_INST);
DL_I2C_enableTargetClockStretching(I2C_INST);
/* Configure Interrupts */
DL_I2C_enableInterrupt(I2C_INST,
DL_I2C_INTERRUPT_TARGET_RXFIFO_TRIGGER |
DL_I2C_INTERRUPT_TARGET_START |
DL_I2C_INTERRUPT_TARGET_STOP);
/* Enable module */
DL_I2C_enableTarget(I2C_INST);
}
/*
* Copyright (c) 2021, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ti_msp_dl_config.h"
/* Maximum size of TX packet */
#define I2C_TX_MAX_PACKET_SIZE (16)
/* Maximum size of RX packet */
#define I2C_RX_MAX_PACKET_SIZE (16)
/* Data sent to Controller in response to Read transfer */
uint8_t gTxPacket[I2C_TX_MAX_PACKET_SIZE] = {0x00};
/* Counters for TX length and bytes sent */
uint32_t gTxLen, gTxCount;
uint32_t gTxFillNum;
/* Data received from Controller during a Write transfer */
uint8_t gRxPacket[I2C_RX_MAX_PACKET_SIZE];
/* Counters for TX length and bytes sent */
uint32_t gRxLen, gRxCount;
int main(void)
{
SYSCFG_DL_init();
/* Set LED to indicate start of transfer */
DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
/*
* Fill FIFO with data.
* Note that transactions are initiated by the Controller, so this example
* only fills the buffer and the Target device will send this data when
* requested by the Controller.
* The TX FIFO is initialized to zero and then it will echo the data sent by
* Controller.
*/
gTxCount = 0;
gTxLen = I2C_TX_MAX_PACKET_SIZE;
DL_I2C_setTimeoutACount(I2C_INST,2);
DL_I2C_setTimeoutBCount(I2C_INST,2);
DL_I2C_enableTimeoutA(I2C_INST);
//DL_I2C_enableTimeoutB(I2C_INST);
DL_I2C_disableTargetTXEmptyOnTXRequest(I2C_INST);
DL_I2C_enableInterrupt(I2C_INST, DL_I2C_INTERRUPT_TARGET_RXFIFO_OVERFLOW|
DL_I2C_TARGET_INTERRUPT_OVERFLOW|
DL_I2C_INTERRUPT_TARGET_TXFIFO_UNDERFLOW|
DL_I2C_INTERRUPT_TARGET_TXFIFO_EMPTY |
DL_I2C_INTERRUPT_TIMEOUT_A |
DL_I2C_INTERRUPT_TIMEOUT_B|
DL_I2C_INTERRUPT_TARGET_PEC_RX_ERROR|
DL_I2C_INTERRUPT_TARGET_RX_DONE|
DL_I2C_INTERRUPT_TARGET_ARBITRATION_LOST|
DL_I2C_INTERRUPT_TARGET_GENERAL_CALL|
DL_I2C_INTERRUPT_TARGET_STOP|
DL_I2C_INTERRUPT_TARGET_RXFIFO_FULL|
DL_I2C_INTERRUPT_TARGET_TXFIFO_TRIGGER|
DL_I2C_INTERRUPT_TARGET_TX_DONE
);
/* Initialize variables to receive data inside RX ISR */
gRxCount = 0;
gRxLen = I2C_RX_MAX_PACKET_SIZE;
DL_I2C_enableTargetACKOverride(I2C_INST);
NVIC_EnableIRQ(I2C_INST_INT_IRQN);
DL_SYSCTL_enableSleepOnExit();
/* Go to STOP, the device will wake-up on address match */
while (1) {
__WFI();
}
}
int aa;
int f1= 0;
int f2= 0;
int tmt_flag= 0;
int rvflag= 0;
void I2C_INST_IRQHandler(void)
{
static bool dataRx = false;
aa = DL_I2C_getPendingInterrupt(I2C_INST);
switch (aa) {
case DL_I2C_IIDX_TARGET_START:
/* Initialize RX or TX after Start condition is received */
gTxCount = 0;
gRxCount = 0;
dataRx = false;
rvflag= 0;
/* Flush TX FIFO to refill it */
DL_I2C_flushTargetTXFIFO(I2C_INST);
break;
case DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER:
/* Store received data in buffer */
dataRx = true;
while (DL_I2C_isTargetRXFIFOEmpty(I2C_INST) != true) {
if (gRxCount < gRxLen) {
gRxPacket[gRxCount++] = DL_I2C_receiveTargetData(I2C_INST);
} else {
/* Prevent overflow and just ignore data */
DL_I2C_receiveTargetData(I2C_INST);
}
if(gRxCount >= 2)
{
DL_I2C_enableTargetACKOverride(I2C_INST);
DL_I2C_setTargetACKOverrideValue(I2C_INST,DL_I2C_TARGET_RESPONSE_OVERRIDE_VALUE_NACK);
f1 = 1;
}
else
{
DL_I2C_enableTargetACKOverride(I2C_INST);
DL_I2C_setTargetACKOverrideValue(I2C_INST,DL_I2C_TARGET_RESPONSE_OVERRIDE_VALUE_ACK);
f2 = 1;
}
}
break;
case DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER:
/* Fill TX FIFO if there are more bytes to send */
if (gTxCount < gTxLen) {
gTxFillNum = DL_I2C_fillTargetTXFIFO(
I2C_INST, &gTxPacket[gTxCount], 1);
gTxCount += gTxFillNum;
} else {
/*
* Fill FIFO with 0x00 if more data is requested than
* expected gTxLen
*/
while (DL_I2C_transmitTargetDataCheck(I2C_INST, 0x88) != false)
;
}
break;
case DL_I2C_IIDX_TARGET_STOP:
/* If data was received, echo to TX buffer */
if (dataRx == true) {
for (uint16_t i = 0;
(i < gRxCount) && (i < I2C_TX_MAX_PACKET_SIZE); i++) {
gTxPacket[i] = gRxPacket[i];
DL_I2C_flushTargetTXFIFO(I2C_INST);
}
dataRx = false;
}
/* Toggle LED to indicate successful RX or TX */
DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
break;
case DL_I2C_IIDX_TARGET_TXFIFO_EMPTY:
/* Fill TX FIFO if there are more bytes to send */
if (gTxCount < 8) {
gTxFillNum = DL_I2C_fillTargetTXFIFO(
I2C_INST, &gTxPacket[gTxCount], 1);
gTxCount += gTxFillNum;
} else {
/*
* Fill FIFO with 0x00 if more data is requested than
* expected gTxLen
*/
while (DL_I2C_transmitTargetDataCheck(I2C_INST, 0x99) != false)
;
}
break;
case DL_I2C_IIDX_TARGET_RX_DONE:
rvflag++;
break;
/* Not used for this example */
case DL_I2C_IIDX_TARGET_RXFIFO_FULL:
/* Not used for this example */
case DL_I2C_IIDX_TARGET_GENERAL_CALL:
/* Not used for this example */
case DL_I2C_IIDX_TARGET_EVENT1_DMA_DONE:
/* Not used for this example */
case DL_I2C_IIDX_TARGET_EVENT2_DMA_DONE:
/* Not used for this example */
break;
case DL_I2C_IIDX_TARGET_PEC_RX_ERROR:
aa = 100;
break;
case DL_I2C_IIDX_TARGET_ARBITRATION_LOST:
case DL_I2C_IIDX_TIMEOUT_A:
case DL_I2C_IIDX_TIMEOUT_B:
case DL_I2C_IIDX_TARGET_TXFIFO_UNDERFLOW:
case DL_I2C_IIDX_TARGET_RXFIFO_OVERFLOW:
case DL_I2C_IIDX_INTERRUPT_OVERFLOW:
tmt_flag = 1;
break;
default:
break;
}
}




