如题,本来MCU作为从机,I2C可以正常被外部主机读写,但是无意中把SCL短时间内拉低(如1秒),然后松开,SCL居然无法恢复。
经排查是3507这边的问题(重启主机无效,重启从机恢复)。
开启所有中断标志位,无法响应,甚至TimeoutA设置也无法响应。
目前看不知道这个问题出现的原因,且3507作为从机自身也没有标志位可感知此异常:

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.
如题,本来MCU作为从机,I2C可以正常被外部主机读写,但是无意中把SCL短时间内拉低(如1秒),然后松开,SCL居然无法恢复。
经排查是3507这边的问题(重启主机无效,重启从机恢复)。
开启所有中断标志位,无法响应,甚至TimeoutA设置也无法响应。
目前看不知道这个问题出现的原因,且3507作为从机自身也没有标志位可感知此异常:

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;
}
}