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.

MSP432 I2C DMA transfer issue



Hello,

I am trying to send data over I2C via DMA in a loop. MSP432 board is in master mode and aardwark dongle is configured in slave mode.

I have modified the example dma_eusci_i2c_loopback to send data of 1024 bytes in a for loop. In the first loop, all 1024 bytes is sent successfully. On the subsequent tries, sometimes 5 or 6 bytes are sent (with the first byte missing). If I change the speed to 400kbpsm, sometimes, the dma isr doesnt get called. Always the first transfer is a success.

I have attached my code here. Appreciate the help. Thanks.

/*
 * -------------------------------------------
 *    MSP432 DriverLib - v2_20_00_08 
 * -------------------------------------------
 *
 * --COPYRIGHT--,BSD,BSD
 * Copyright (c) 2014, 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.
 * --/COPYRIGHT--*/
/*******************************************************************************
 * MSP432 DMA - eUSCI I2C Transfer Using DMA
 *
 * Description: In this code example, the MSP432 's DMA controller is used in 
 * conjunction with an I2C loopback configuration to demonstrate how to use
 * hardware triggered DMA transfers. Two DMA transfers are setup using two 
 * different channels. Channel 2 is used for the DMA transfer and Channel 5 is
 * used for the DMA receive. Once the transfers are setup and initialized, the
 * device is put to sleep. While sleeping, the DMA controller will automatically
 * transfer the data from the const array and out through the uESCI B1 I2C
 * module as a master. The slave, which is setup on eUSCI B2, will automatically
 * trigger the DMA controller to place the incoming data in a RAM buffer called
 * recBuffer. When the DMA transfer is complete, an interrupt will be fired and
 * the master will send a stop condition out over the I2C Line.
 *
 * This program runs infinitely until manually halted by the user.
 *
 *                MSP432P401
 *             ------------------
 *         /|\|                  | <10k Pull-Up> 
 *          | |                  |   | |
 *          --|RST    P6.5 (SDA) |---|---------
 *            |       P6.4 (SCL) |----------  |
 *            |                  |         |  |  
 *            |       P3.6 (SCL) |----------  |
 *            |       P3.7 (SCL) |-------------
 *            |                  |
 *
 * Author: Timothy Logan
 ******************************************************************************/
/* DriverLib Includes */
#include "driverlib.h"

/* Standard Includes */
#include <stdint.h>

#include <string.h>
#include <stdbool.h>

/* Statics */
static uint8_t recBuffer[1024];
static volatile bool sendStopCondition;

/* I2C Configuration Parameter */
const eUSCI_I2C_MasterConfig i2cMasterConf =
{
        EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
        3000000,                                // SMCLK = 3MHz
        EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 100khz
        0,                                      // No Auto Stop
        EUSCI_B_I2C_NO_AUTO_STOP                // No Auto Stop
};

/* DMA Control Table */
#ifdef ewarm
#pragma data_alignment=256
#else
#pragma DATA_ALIGN(controlTable, 256)
#endif
uint8_t controlTable[256];

/* Extern */
extern uint8_t data_array[];
void read_from_slave(unsigned char addr, void *destAddress, int transferSize);
void send_to_slave(unsigned char addr, void *srcAddress, int transferSize);

// dma to aardwark works using this B0 module only.
#define EUSCI_BX_MODULE		EUSCI_B0_MODULE

#define DMA_CHX_EUSCIBXTX	DMA_CH0_EUSCIB0TX0
#define DMA_CHX_EUSCIBXRX	DMA_CH1_EUSCIB0RX0

#define DMA_CHANNEL_TX		0
#define DMA_CHANNEL_RX		1

#define DMA_INTTX			DMA_INT1
#define DMA_INTRX			DMA_INT2

void loop(void) {
    while(1)
    {
        if(sendStopCondition)
        {
        	break;
        }
        MAP_PCM_gotoLPM0InterruptSafe();
    }
}

int main(void)
{
    /* Halting Watchdog */
    MAP_WDT_A_holdTimer();

    /* Initializing I2C Master on EUSCIB1  at 400Khz */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
            GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
    MAP_I2C_initMaster(EUSCI_BX_MODULE, &i2cMasterConf);

    MAP_I2C_enableModule(EUSCI_BX_MODULE);

    /* Configuring DMA module */
    MAP_DMA_enableModule();
    MAP_DMA_setControlBase(controlTable);

    /* Assigning Channel 0 and 1 */
    MAP_DMA_assignChannel(DMA_CHX_EUSCIBXTX);
    MAP_DMA_assignChannel(DMA_CHX_EUSCIBXRX);

     /* Disabling channel attributes */
    MAP_DMA_disableChannelAttribute(DMA_CHX_EUSCIBXTX,
                                     UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                     UDMA_ATTR_HIGH_PRIORITY |
                                     UDMA_ATTR_REQMASK);
    MAP_DMA_disableChannelAttribute(DMA_CHX_EUSCIBXRX,
                                     UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                     UDMA_ATTR_HIGH_PRIORITY |
                                     UDMA_ATTR_REQMASK);

    /* Setting Control Indexes */
    MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXTX,
            UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXRX,
            UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);

    /* Assigning/Enabling Interrupts */
    MAP_DMA_assignInterrupt(DMA_INTTX, DMA_CHANNEL_TX);
    MAP_DMA_assignInterrupt(DMA_INTRX, DMA_CHANNEL_RX);

    // enable interrupts
    MAP_Interrupt_enableInterrupt(DMA_INTTX);
    MAP_Interrupt_enableInterrupt(DMA_INTRX);

	/* Enabling master interrupts */
	MAP_Interrupt_enableMaster();

	int i, j;
	for (i = 0; i < 5; i ++) {
		sendStopCondition = false;
		MAP_Interrupt_enableSleepOnIsrExit();
		send_to_slave(0x48, data_array, 1024);
		loop ();
		// sleep
		for(j = 0; j < 100000; j ++);
	}

    sendStopCondition = false;
}

void send_to_slave(unsigned char addr, void *srcAddress, int transferSize)
{
	// set slave address
    MAP_I2C_setSlaveAddress(EUSCI_BX_MODULE, addr);
    // set in transmit mode
    MAP_I2C_setMode(EUSCI_BX_MODULE, EUSCI_B_I2C_TRANSMIT_MODE);

    // tx channel
    MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXTX,
            UDMA_MODE_BASIC, srcAddress,
            (void*) MAP_I2C_getTransmitBufferAddressForDMA(EUSCI_BX_MODULE), transferSize);

    MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXTX,
            UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);

	/* Clear flag */
	MAP_DMA_clearInterruptFlag(DMA_CHANNEL_TX);
	/* enable interrupt */
	MAP_DMA_enableInterrupt(DMA_INTTX);
    MAP_Interrupt_enableInterrupt(DMA_INTTX);

    /* Now that the DMA is primed and setup, enabling the channels. The EUSCI
     * hardware should take over and transfer/receive all bytes */
    MAP_DMA_enableChannel(DMA_CHANNEL_TX);

    /* Sending the start condition */
    MAP_I2C_masterSendStart(EUSCI_BX_MODULE);
    while(!MAP_I2C_masterIsStartSent(EUSCI_BX_MODULE));
}

void read_from_slave(unsigned char addr, void *destAddress, int transferSize)
{
	// set slave address
	MAP_I2C_setSlaveAddress(EUSCI_BX_MODULE, addr);
    /* Set in receive mode */
    MAP_I2C_setMode(EUSCI_BX_MODULE, EUSCI_B_I2C_RECEIVE_MODE);

    // rx channel
    MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXRX,
            UDMA_MODE_BASIC, (void*)MAP_I2C_getReceiveBufferAddressForDMA(EUSCI_BX_MODULE),
			destAddress, transferSize);

	/* Clear flag */
	MAP_DMA_clearInterruptFlag(DMA_CHANNEL_RX);
	/* enable interrupt */
	MAP_DMA_enableInterrupt(DMA_INTRX);
	MAP_Interrupt_enableInterrupt(DMA_INTRX);

    /* Now that the DMA is primed and setup, enabling the channels. The EUSCI
     * hardware should take over and transfer/receive all bytes */
	MAP_DMA_enableChannel(DMA_CHANNEL_RX);

	// Sending the receive
	MAP_I2C_masterReceiveStart(EUSCI_BX_MODULE);
}

static int euscib1_isr_count = 0;
void euscib1_isr(void)
{
	euscib1_isr_count ++;
}

static int euscib2_isr_count = 0;
void euscib2_isr(void)
{
	euscib2_isr_count ++;
}

/* Completion interrupt for eUSCIB1 RX */
void dma_2_interrupt(void)
{
	/* Clear flag */
	MAP_DMA_clearInterruptFlag(DMA_CHANNEL_RX);

	/* Disabling the completion interrupt and disabling the DMA channels */
    MAP_DMA_disableChannel(DMA_CHANNEL_RX);

    MAP_DMA_disableInterrupt(DMA_INTRX);
    MAP_I2C_masterReceiveMultiByteStop(EUSCI_BX_MODULE);
}

/* Completion interrupt for eUSCIB1 TX */
void dma_1_interrupt(void)
{
	/* Clear flag */
	MAP_DMA_clearInterruptFlag(DMA_CHANNEL_TX);

	/* Disabling the completion interrupt and disabling the DMA channels */
    MAP_DMA_disableChannel(DMA_CHANNEL_TX);

    MAP_DMA_disableInterrupt(DMA_INTTX);
    MAP_I2C_masterSendMultiByteStop(EUSCI_BX_MODULE);
    while(!MAP_I2C_masterIsStopSent(EUSCI_BX_MODULE));
    sendStopCondition = true;
//    MAP_I2C_disableModule(EUSCI_BX_MODULE);
}

  • Karthik,

    It sounds like you might be running into DMA12 within the Erratasheet for MSP432. Please refer to the document attached below and confirm whether or not this is the same issue you are experiencing. If so, apply the workaround and see if that solves your problem. Hope this helps!

    www.ti.com/.../slaz610c.pdf

    Best regards,
    Michael Arriete
  • Hi Michael,
    Many Thanks. This fixed the issue.

    With the changes mentioned in the errata, the first transfer was getting interrupted (only sending 1 or 0 bytes). This was fixed by clearing the interrupts before enabling DMA (as in the isr routine). Now all transfers are ok. Thanks again!
  • Hi Michael,

    Further to the transfer, I did the same for the receive. The receive DMA isr is not getting hit. I have updated as per the errata for I2C read. 

    Receive function / configuration is 

    void read_from_slave(unsigned char addr, void *destAddress, int transferSize)
    {
        // set slave address
        MAP_I2C_setSlaveAddress(EUSCI_BX_MODULE, addr);
        /* Set in receive mode */
        MAP_I2C_setMode(EUSCI_BX_MODULE, EUSCI_B_I2C_RECEIVE_MODE);
    
        // rx channel
        MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXRX,
                UDMA_MODE_BASIC, (void*)MAP_I2C_getReceiveBufferAddressForDMA(EUSCI_BX_MODULE),
                destAddress, transferSize);
    
        /* Disabling the completion interrupt and disabling the DMA channels */
        MAP_DMA_disableChannel(DMA_CHANNEL_RX);
    
        // as per DMA12, disable interrupt first
        MAP_DMA_disableInterrupt(DMA_INTRX);
    
        /* Clear flag */
        MAP_DMA_clearInterruptFlag(DMA_CHANNEL_RX);
    
        // Sending the receive
        MAP_I2C_masterReceiveStart(EUSCI_BX_MODULE);
        // do i need this?
    //  while(!MAP_I2C_masterIsStartSent(EUSCI_BX_MODULE));
    
        /* Now that the DMA is primed and setup, enabling the channels. The EUSCI
         * hardware should take over and transfer/receive all bytes */
        // as per DMA12, enable interrupt at the end
        MAP_DMA_enableChannel(DMA_CHANNEL_RX);
    
        // as per DMA12, enable interrupt at the end
        MAP_DMA_enableInterrupt(DMA_INTRX);
        MAP_Interrupt_enableInterrupt(DMA_INTRX);
    }

    DMA isr is as below.

    void dma_2_interrupt(void)
    {
        /* Disabling the completion interrupt and disabling the DMA channels */
        MAP_DMA_disableChannel(DMA_CHANNEL_RX);
    
        // as per DMA12, disable interrupt first
        MAP_DMA_disableInterrupt(DMA_INTRX);
    
        /* Clear flag */
        MAP_DMA_clearInterruptFlag(DMA_CHANNEL_RX);
    
        MAP_I2C_masterReceiveMultiByteStop(EUSCI_BX_MODULE);
    //    while(!MAP_I2C_masterIsStopSent(EUSCI_BX_MODULE));
    
        sendStopCondition = true;
    }

    Full code is attached here.

    /*
     * -------------------------------------------
     *    MSP432 DriverLib - v2_20_00_08 
     * -------------------------------------------
     *
     * --COPYRIGHT--,BSD,BSD
     * Copyright (c) 2014, 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.
     * --/COPYRIGHT--*/
    /*******************************************************************************
     * MSP432 DMA - eUSCI I2C Transfer Using DMA to Arrdvark
     *
     * Description: In this code example, the MSP432 's DMA controller is used in 
     * conjunction with an I2C loopback configuration to demonstrate how to use
     * hardware triggered DMA transfers. Two DMA transfers are setup using two 
     * different channels. Channel 2 is used for the DMA transfer and Channel 5 is
     * used for the DMA receive. Once the transfers are setup and initialized, the
     * device is put to sleep. While sleeping, the DMA controller will automatically
     * transfer the data from the const array and out through the uESCI B1 I2C
     * module as a master. The slave, which is setup on eUSCI B2, will automatically
     * trigger the DMA controller to place the incoming data in a RAM buffer called
     * recBuffer. When the DMA transfer is complete, an interrupt will be fired and
     * the master will send a stop condition out over the I2C Line.
     *
     * This program runs infinitely until manually halted by the user.
     *
     *                MSP432P401
     *             ------------------
     *         /|\|                  | <10k Pull-Up> 
     *          | |                  |   | |
     *          --|RST    P1.6 (SDA) |---|---------------SDA Arrdvark
     *            |       P1.7 (SCL) |-------------------SCL Arrdvark
     *            |                  |
     *            |       P3.6 (SCL) |
     *            |       P3.7 (SCL) |
     *            |                  |
     *
     * Author: Timothy Logan
     ******************************************************************************/
    /* DriverLib Includes */
    #include "driverlib.h"
    
    /* Standard Includes */
    #include <stdint.h>
    
    #include <string.h>
    #include <stdbool.h>
    
    /* Statics */
    static uint8_t recBuffer[1024];
    static volatile bool sendStopCondition;
    
    /* I2C Configuration Parameter */
    const eUSCI_I2C_MasterConfig i2cMasterConf =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            3000000,                                // SMCLK = 3MHz
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 100khz
            0,                                      // No Auto Stop
            EUSCI_B_I2C_NO_AUTO_STOP                // No Auto Stop
    };
    
    /* DMA Control Table */
    #ifdef ewarm
    #pragma data_alignment=256
    #else
    #pragma DATA_ALIGN(controlTable, 256)
    #endif
    uint8_t controlTable[256];
    
    /* Extern */
    extern uint8_t data_array[];
    void read_from_slave(unsigned char addr, void *destAddress, int transferSize);
    void send_to_slave(unsigned char addr, void *srcAddress, int transferSize);
    
    // dma to aardwark works using this B0 module only.
    #define EUSCI_BX_MODULE     EUSCI_B0_MODULE
    
    #define DMA_CHX_EUSCIBXTX   DMA_CH0_EUSCIB0TX0
    #define DMA_CHX_EUSCIBXRX   DMA_CH1_EUSCIB0RX0
    
    #define DMA_CHANNEL_TX      0
    #define DMA_CHANNEL_RX      1
    
    #define DMA_INTTX           DMA_INT1
    #define DMA_INTRX           DMA_INT2
    
    void loop(void) {
        while(1)
        {
            if(sendStopCondition)
            {
                break;
            }
            MAP_PCM_gotoLPM0InterruptSafe();
        }
    }
    
    int main(void)
    {
        /* Halting Watchdog */
        MAP_WDT_A_holdTimer();
    
        /* Initializing I2C Master on EUSCIB1  at 400Khz */
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
                GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
        MAP_I2C_initMaster(EUSCI_BX_MODULE, &i2cMasterConf);
    
        MAP_I2C_enableModule(EUSCI_BX_MODULE);
    
        /* Configuring DMA module */
        MAP_DMA_enableModule();
        MAP_DMA_setControlBase(controlTable);
    
        /* Assigning Channel 0 and 1 */
        MAP_DMA_assignChannel(DMA_CHX_EUSCIBXTX);
        MAP_DMA_assignChannel(DMA_CHX_EUSCIBXRX);
    
         /* Disabling channel attributes */
        MAP_DMA_disableChannelAttribute(DMA_CHX_EUSCIBXTX,
                                         UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                         UDMA_ATTR_HIGH_PRIORITY |
                                         UDMA_ATTR_REQMASK);
        MAP_DMA_disableChannelAttribute(DMA_CHX_EUSCIBXRX,
                                         UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                         UDMA_ATTR_HIGH_PRIORITY |
                                         UDMA_ATTR_REQMASK);
    
        /* Setting Control Indexes */
        MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXTX,
                UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
        MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXRX,
                UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    
        /* Assigning/Enabling Interrupts */
        MAP_DMA_assignInterrupt(DMA_INTTX, DMA_CHANNEL_TX);
        MAP_DMA_assignInterrupt(DMA_INTRX, DMA_CHANNEL_RX);
    
        /* Enabling master interrupts */
        MAP_Interrupt_enableMaster();
    
        int i, j;
    //  for (i = 0; i < 5; i ++) {
    //      sendStopCondition = false;
    //      MAP_Interrupt_enableSleepOnIsrExit();
    //      send_to_slave(0x48, data_array, 1024);
    //      loop ();
    //      // sleep
    ////        for(j = 0; j < 100000; j ++);
    //  }
    
    //  for(j = 0; j < 500000; j ++);
    
        sendStopCondition = false;
        for (i = 0; i < 5; i ++) {
            sendStopCondition = false;
            MAP_Interrupt_enableSleepOnIsrExit();
            read_from_slave(0x48, recBuffer, 16);
            loop ();
            // sleep
            for(j = 0; j < 100000; j ++);
        }
    }
    
    void send_to_slave(unsigned char addr, void *srcAddress, int transferSize)
    {
        // set slave address
        MAP_I2C_setSlaveAddress(EUSCI_BX_MODULE, addr);
        // set mode to transmit
        MAP_I2C_setMode(EUSCI_BX_MODULE, EUSCI_B_I2C_TRANSMIT_MODE);
    
        // tx channel configuration
        MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXTX,
                UDMA_MODE_BASIC, srcAddress,
                (void*) MAP_I2C_getTransmitBufferAddressForDMA(EUSCI_BX_MODULE), transferSize);
    
        MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXTX,
                UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    
        /* Disabling the completion interrupt and disabling the DMA channels */
        MAP_DMA_disableChannel(DMA_CHANNEL_TX);
    
        // as per DMA12, disable interrupt first
        MAP_DMA_disableInterrupt(DMA_INTTX);
    
        /* Clear flag */
        MAP_DMA_clearInterruptFlag(DMA_CHANNEL_TX);
    
        /* Sending the start condition */
        MAP_I2C_masterSendStart(EUSCI_BX_MODULE);
        while(!MAP_I2C_masterIsStartSent(EUSCI_BX_MODULE));
    
        // as per DMA12, enable interrupt at the end
        MAP_DMA_enableChannel(DMA_CHANNEL_TX);
    
        // as per DMA12, enable interrupt at the end
        MAP_DMA_enableInterrupt(DMA_INTTX);
        MAP_Interrupt_enableInterrupt(DMA_INTTX);
    }
    
    void read_from_slave(unsigned char addr, void *destAddress, int transferSize)
    {
        // set slave address
        MAP_I2C_setSlaveAddress(EUSCI_BX_MODULE, addr);
        /* Set in receive mode */
        MAP_I2C_setMode(EUSCI_BX_MODULE, EUSCI_B_I2C_RECEIVE_MODE);
    
        // rx channel
        MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CHX_EUSCIBXRX,
                UDMA_MODE_BASIC, (void*)MAP_I2C_getReceiveBufferAddressForDMA(EUSCI_BX_MODULE),
                destAddress, transferSize);
    
        /* Disabling the completion interrupt and disabling the DMA channels */
        MAP_DMA_disableChannel(DMA_CHANNEL_RX);
    
        // as per DMA12, disable interrupt first
        MAP_DMA_disableInterrupt(DMA_INTRX);
    
        /* Clear flag */
        MAP_DMA_clearInterruptFlag(DMA_CHANNEL_RX);
    
        // Sending the receive
        MAP_I2C_masterReceiveStart(EUSCI_BX_MODULE);
        // do i need this?
    //  while(!MAP_I2C_masterIsStartSent(EUSCI_BX_MODULE));
    
        /* Now that the DMA is primed and setup, enabling the channels. The EUSCI
         * hardware should take over and transfer/receive all bytes */
        // as per DMA12, enable interrupt at the end
        MAP_DMA_enableChannel(DMA_CHANNEL_RX);
    
        // as per DMA12, enable interrupt at the end
        MAP_DMA_enableInterrupt(DMA_INTRX);
        MAP_Interrupt_enableInterrupt(DMA_INTRX);
    }
    
    static int euscib1_isr_count = 0;
    void euscib1_isr(void)
    {
        euscib1_isr_count ++;
    }
    
    static int euscib2_isr_count = 0;
    void euscib2_isr(void)
    {
        euscib2_isr_count ++;
    }
    
    /* Completion interrupt for eUSCIB1 RX */
    void dma_2_interrupt(void)
    {
        /* Disabling the completion interrupt and disabling the DMA channels */
        MAP_DMA_disableChannel(DMA_CHANNEL_RX);
    
        // as per DMA12, disable interrupt first
        MAP_DMA_disableInterrupt(DMA_INTRX);
    
        /* Clear flag */
        MAP_DMA_clearInterruptFlag(DMA_CHANNEL_RX);
    
        MAP_I2C_masterReceiveMultiByteStop(EUSCI_BX_MODULE);
    //    while(!MAP_I2C_masterIsStopSent(EUSCI_BX_MODULE));
    
        sendStopCondition = true;
    }
    
    /* Completion interrupt for eUSCIB1 TX */
    void dma_1_interrupt(void)
    {
        /* Disabling the completion interrupt and disabling the DMA channels */
        MAP_DMA_disableChannel(DMA_CHANNEL_TX);
    
        // as per DMA12, disable interrupt first
        MAP_DMA_disableInterrupt(DMA_INTTX);
    
        /* Clear flag */
        MAP_DMA_clearInterruptFlag(DMA_CHANNEL_TX);
    
        MAP_I2C_masterSendMultiByteStop(EUSCI_BX_MODULE);
        while(!MAP_I2C_masterIsStopSent(EUSCI_BX_MODULE));
    
        sendStopCondition = true;
    }
    
    /* Completion interrupt for eUSCIB1 TX */
    void dma_err_interrupt(void)
    {
        sendStopCondition = true;
    }
    

**Attention** This is a public forum