如题,本来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; } }