Part Number: MSPM0G1507
H iexperts,
This is a continuation of the thread below.
:(1) MSPM0G1507: When communicating in Fast-mode (400kHz), the controller side shifts the data by 1 byte. - Arm-based microcontrollers forum - Arm-based microcontrollers - TI E2E support forums
I have confirmed the customer’s actual usage. The MSPM0G1507 will be used as the target device, and the controller may perform both normal START/STOP communication and repeated START communication.
In the actual use case, this is not an echo operation. As shown in the figure below, the data received from the controller is treated as address information, and the target returns the data stored in its address space starting from the address indicated by the last received data byte. Therefore, each time the target receives data, it needs to move the corresponding data into the TXFIFO in advance.
With that in mind, although this is a repeated question:
Q: When using repeated START, are there any concerns with moving data into the TXFIFO at the timing of the RxFIFO trigger (threshold = 1) as a method of preparing the TXFIFO before the repeated START trigger occurs? If there is any other recommended approach, please let me know.
For reference, I modified the program original thread provided as attached so that the data is moved into the TXFIFO at the timing of the RxFIFO trigger (threshold = 1). I would appreciate it if you could let me know whether there are any concerns with this method or whether there is another recommended approach.



/*
* 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;
uint8_t TX_Flag;
/* 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.
*/
TX_Flag = 0;
gTxCount = 0;
gTxLen = I2C_TX_MAX_PACKET_SIZE;
DL_I2C_enableInterrupt(I2C_INST, DL_I2C_INTERRUPT_TARGET_TXFIFO_TRIGGER);
/* Initialize variables to receive data inside RX ISR */
gRxCount = 0;
gRxLen = I2C_RX_MAX_PACKET_SIZE;
NVIC_EnableIRQ(I2C_INST_INT_IRQN);
/* Calling WFI after calling DL_SYSCTL_enableSleepOnExit will result in
* only ISR code to be executed. This is done to showcase the device's
* low power consumption when sleeping.
*/
DL_SYSCTL_enableSleepOnExit();
while (1) {
__WFI();
}
}
void I2C_INST_IRQHandler(void)
{
static bool dataRx = false;
DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
switch (DL_I2C_getPendingInterrupt(I2C_INST)) {
case DL_I2C_IIDX_TARGET_START:
/* Initialize RX or TX after Start condition is received */
gRxCount = 0;
dataRx = false;
/* Flush TX FIFO to refill it */
if(TX_Flag == 0)
{
DL_I2C_flushTargetTXFIFO(I2C_INST);
gTxCount = 0;
}
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 (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);
}
gTxCount = 0;
gTxCount += DL_I2C_fillTargetTXFIFO(
I2C_INST, &gTxPacket[gTxCount], (gTxLen - gTxCount));
TX_Flag = 1;
}
break;
case DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER:
/* Fill TX FIFO if there are more bytes to send */
if (gTxCount < gTxLen) {
gTxCount += DL_I2C_fillTargetTXFIFO(
I2C_INST, &gTxPacket[gTxCount], (gTxLen - gTxCount));
} else {
/*
* Fill FIFO with 0x00 if more data is requested than
* expected gTxLen
*/
while (DL_I2C_transmitTargetDataCheck(I2C_INST, 0x00) != false)
;
}
DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_PIN_0_PIN);
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);
}
gTxCount = 0;
gTxCount += DL_I2C_fillTargetTXFIFO(
I2C_INST, &gTxPacket[gTxCount], (gTxLen - gTxCount));
TX_Flag = 1;
dataRx = false;
}else {
TX_Flag = 0;
}
/* Toggle LED to indicate successful RX or TX */
break;
case DL_I2C_IIDX_TARGET_RX_DONE:
/* 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 */
default:
break;
}
DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
}
Best regards,
O.H