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 Timer Interrupt Problem

Hello!

I am currently working on an audio project using the MSP432P401R launchpad, and I've been having some trouble using the timer Interrupts on the device. For this application, we would like to sample the input at 44.1 kHz. Our current setup involves interfacing a 16-bit ADC via the SPI interface on the MSP432 and setting up the timer interrupt to read from the ADC at the desired frequency.

However, we have run into a problem where the timer interrupt, although being set up to run at the given frequency, will be unable to run at this frequency due to a software bottleneck. The reason we believe it is a software bottleneck is due to the fact that when more/less code is being executed inside the timer interrupt ISR, the frequency decreases/increases respectively. Currently, our ISR is simply toggling a pin, then reading from an ADC, then writing to a DAC, then clearing the ISR flag.

Some things we have tried to do to increase the MSP432's performance include trying to set it to 32-bit mode within project properties and turning on full project optimizations. The 32-bit mode did not work due to the "target processor option" not being correct (I am not sure exactly what this means, but it is the option directly above the 16/32 bit option in Code Composer's Project Properties) and the full optimizations got rid of some functionality.

We are using Code Composer 6 for this project. Any debugging tips would be appreciated!

Thank you!

-Daniel

  • Daniel,
    Could you provide the ISR code? This might be helpful to characterize how many instructions are taking place within the ISR. Additionally, instead of toggling a pin via the ISR could you use the capture/compare output of the timer to drive the pin? Similarly, could you use interrupts (enable recieve interrupt) to handle the SPI data from the ADC.

    Regards,
    Chris
  • Hello Daniel,

    Are you using the default DCO of 3 MHz? You can increase this to 48 MHz by increasing VCORE and altering the CSCTL registers, please refer to the TI code example msp432p401_cs_03.c. You can also try increasing the SPI clock speed to read ADC values more quickly. If these suggestions do not help then you might want to consider using the DMA to drive SPI communication or DAC control, TI provides DriverLib examples for accomplishing this (it can be quite a difficult concept to grasp). Here's a DMA SPI loopback example for the MSP432: dev.ti.com/.../

    Regards,
    Ryan

  • Hi Chris,

    Thank you for the response. I have posted some of the relevant code below, including the ISR, and the function definitions of the other functions being called within the ISR. As a note, whenever I comment out the ADC and DAC functions, the interrupt does speed up, however only a little bit. When I leave it with just the GPIO toggling function and the flag clearing, the ISR frequency is still way below what the timer interrupt was configured to.

    In addition, I did try your method of using the capture/compare output to drive the pin. The output of this pin was indeed at the correct frequency, which leads me to believe it has something to do with software being executed in the ISR.

    Thank you very much!

    Some source code is below:

    /*Timer_A1 Interrupt that will be used to sample from the ADC*/
    void TA1_0_IRQHandler(void)
    {

    GPIO_toggleOutputOnPin(GPIO_PORT_P5,GPIO_PIN0);

    audioData = readAdc();

    writeToDac(audioData);

    Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_0);

    }

    uint16_t readAdc(void)
    {

    /*Use the GPIO chip select to initiate the transfer of data from the ADC by pulling the pin low */
    GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN0);

    /*Transmit and Receive operations happen concurrently. Therefore, transferring dummy bits to activate the clock is necessary*/
    while (!(SPI_getInterruptStatus(EUSCI_B2_BASE, EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    SPI_transmitData(EUSCI_B2_BASE,txData);

    // while(!(SPI_getInterruptStatus(EUSCI_B2_BASE, EUSCI_B_SPI_RECEIVE_INTERRUPT)));

    //Gather the data from the ADC (8 bits)
    rxData1 = SPI_receiveData(EUSCI_B2_BASE);

    while (!(SPI_getInterruptStatus(EUSCI_B2_BASE, EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    SPI_transmitData(EUSCI_B2_BASE,txData);

    //Gather the data from the ADC (8 bits)
    rxData2 = SPI_receiveData(EUSCI_B2_BASE);

    while (!(SPI_getInterruptStatus(EUSCI_B2_BASE, EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    SPI_transmitData(EUSCI_B2_BASE,txData);

    //Gather the data from the ADC (8 bits)
    rxData3 = SPI_receiveData(EUSCI_B2_BASE);

    /*Mask the first 6 bits and shift */
    rxData1 = (rxData1 & 0x3) << 16;

    /*Shift the second 8 bits*/
    rxData2 = rxData2 << 8;

    /*Eliminate the last 2 bits of the third byte and shift */
    rxData3 = (rxData3 & 0xFC);

    /*Consolidate the data and output the complete 16 bits word*/
    adcData = (rxData1 | rxData2 | rxData3) >> 2;

    /*End the transfer process by pulling GPIO high */
    GPIO_setOutputHighOnPin(GPIO_PORT_P3,GPIO_PIN0);

    //return adcData;
    return adcData;
    }

    void writeToDac(uint16_t txData)
    {

    uint8_t lowByte = txData & 0xFF;
    uint8_t highByte = (txData & 0xFF00) >> 8;

    /*Pull the chip select low */
    GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN2);

    /* Poll the transmit interrupt flag*/
    while (!(SPI_getInterruptStatus(EUSCI_B1_BASE, EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    /*transmit the high byte*/
    SPI_transmitData(EUSCI_B1_BASE,highByte);

    /* Poll the transmit interrupt flag*/
    while (!(SPI_getInterruptStatus(EUSCI_B1_BASE, EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    /*transmit the low byte*/
    SPI_transmitData(EUSCI_B1_BASE,lowByte);


    int i;
    for(i=0;i<25;i++);

    /*Finish the transmission*/
    GPIO_setOutputHighOnPin(GPIO_PORT_P6,GPIO_PIN2);

    }
  • Hi Ryan,

    I am actually using the HXFT external crystal and the clock driving the timer is running at 48 MHz currently, however, I could try using the DCO and increasing VCORE. I can also try increasing the SPI clock speed although I am not sure how that would help the bottleneck occurring in the ISR when there is only a GPIO toggling function (using GPIO_toggleOutputOnPin() function from driverlib). I will check out the resources you suggested for accessing the DMA, although I was intending for that to be the last resort as I know how complicated it can be.

    Thank you for the resources!

    -Daniel
  • Daniel,

    Have you made any progress on your efforts? If so, can you share with us the solution you incorporated? If not, do you require any further support?

    Regards,
    Ryan
  • Hi.

    I apologize for the late response. I did end up solving the issue. Essentially, I removed all Driverlib functions that I was calling within the interrupt, and replaced them with simple bitwise functions. This completely solved the issue.

    Thank you very much for all of your help!

    -Daniel
  • /*
     * -------------------------------------------
     *    MSP432 DriverLib - v3_30_00_18
     * -------------------------------------------
     *
     * --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 - Scatter-Gather between eUSCIB2 memory and eUSCIB1
     *
     * Description: In this code example, two software initiated DMA transfers are
     * setup and executed.  The scatter-gather transfers initiated from software
     * perform two tasks.  The first task is to read three bytes from the eUSCIB2
     * SPI and the second task is to transmit two bytes from the eUSCIB1 SPI.
     * In addition to the SPI communication the tasks also manage the chip select
     * via the port registers.
     * During the first interrupt a simple computation is performed to transfer
     * the information read to the information transmitted.
     *
     *              MSP432P401
     *             ------------------
     *         /|\|                  |
     *          | |                  |
     *          --|RST           P3.0|--> CS
     *            |     P3.5(eUSCIB2)|--> CLK
     *            |              P3.6|--> SIMO
     *            |              P3.7|<-- SOMI
     *            |                  |
     *            |              P6.1|--> CS
     *            |     P6.3(eUSCIB1)|--> CLK
     *            |              P6.4|--> SIMO
     *            |              P6.5|<-- SOMI
     *
     ******************************************************************************/
    
    #include "msp.h"
    /* Standard Includes */
    #include <stdint.h>
    #include <string.h>
    #include <stdbool.h>
    
    /* DriverLib Includes */
    #include "driverlib.h"
    
    #define RX_TASKS	9
    #define TX_TASKS	7
    
    /* SPI Configuration Parameter */
    const eUSCI_SPI_MasterConfig spiMasterConfig_B2 =
    {
    	EUSCI_B_SPI_CLOCKSOURCE_SMCLK, 3000000, 1000000,
        EUSCI_B_SPI_MSB_FIRST,
        EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,
        EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH,
    	EUSCI_B_SPI_3PIN
    };
    
    /* SPI Configuration Parameter */
    const eUSCI_SPI_MasterConfig spiMasterConfig_B1 =
    {
    	EUSCI_B_SPI_CLOCKSOURCE_SMCLK, 3000000, 1000000,
        EUSCI_B_SPI_MSB_FIRST,
        EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,
        EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH, EUSCI_B_SPI_3PIN
    };
    
    /* DMA Control Table */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024)
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment=1024
    #elif defined(__GNUC__)
    __attribute__ ((aligned (1024)))
    #elif defined(__CC_ARM)
    __align(1024)
    #endif
    static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[16];  // 8 primary and 8 alternate
    
    uint8_t outputLow = 0;
    uint8_t ADC_CS = BIT0;  //P3.0 is Chip Select; P3.5,P3.6,P3.7 are CLK, SIMO, SOMI
    uint8_t DAC_CS = BIT1;  //P6.1 for convenience on launchpad
    uint8_t dummyTX = 0xa5;
    uint8_t dummyRX;
    uint8_t rxBuffer[3];
    uint8_t txBuffer[2];
    
    /*
     * ADC_DMA Sequence: This sequence sets CS, reads data, and clears CS
     * The 'MEM' instructions are automatic while the 'PER' requires a
     * peripheral trigger, which is the EUSCI_B2_RX.  The trigger is configured
     * before the sequence is started.
     */
    DMA_ControlTable spiAdcDmaSeq[RX_TASKS] =
    {
    	// Task1, Dummy read RX buffer to clear IFG
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &EUSCI_B2_SPI->RXBUF /* MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_DST_INC_NONE, &dummyRX,
    				UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
    	// Task2, Clear Chip select
        DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &outputLow,
    				UDMA_DST_INC_NONE, &P3->OUT,
    				UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
        // Task3, load TX buffer to initiate SPI
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &dummyTX,
    				UDMA_DST_INC_NONE, &EUSCI_B2_SPI->TXBUF /* MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_ARB_4, (UDMA_MODE_PER_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
    	// Task4, read RX buffer to clear IFG
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &EUSCI_B2_SPI->RXBUF /* MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_DST_INC_NONE, &rxBuffer[0],
    				UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
    	// Task5, load TX buffer to initiate SPI
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &dummyTX,
    				UDMA_DST_INC_NONE, &EUSCI_B2_SPI->TXBUF /* MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_ARB_4, (UDMA_MODE_PER_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
        // Task6, read RX buffer to initiate SPI
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &EUSCI_B2_SPI->RXBUF /* MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_DST_INC_NONE, &rxBuffer[1],
    				UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
    	// Task7, load TX buffer to initiate SPI
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &dummyTX,
    				UDMA_DST_INC_NONE, &EUSCI_B2_SPI->TXBUF /* MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_ARB_4, (UDMA_MODE_PER_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
    	// Task8, read RX buffer to initiate SPI
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &EUSCI_B2_SPI->RXBUF /* MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_DST_INC_NONE, &rxBuffer[2],
    				UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
        // Task 9, set GPIO, chip select
        DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &ADC_CS,
    				UDMA_DST_INC_NONE, &P3->OUT,
    				UDMA_ARB_4, UDMA_MODE_BASIC)
    };
    
    /*
     * DAC_DMA Sequence: This sequence sets CS, reads data, and clears CS
     * The 'MEM' instructions are automatic while the 'PER' requires a
     * peripheral trigger, which is the EUSCI_B1_TX. The trigger is configured
     * before the sequence is started.
     */
    DMA_ControlTable spiDacDmaSeq[TX_TASKS] =
    {
    	// Task1, Dummy read RX buffer to clear IFG
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &EUSCI_B1_SPI->RXBUF /* MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_DST_INC_NONE, &dummyRX,
    				UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
    	// Task2, Clear Chip select P6.2
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &outputLow,
    				UDMA_DST_INC_NONE, &P6->OUT,
    				UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
        // Task3, load TX buffer to initiate SPI
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &txBuffer[0],
    				UDMA_DST_INC_NONE, &EUSCI_B1_SPI->TXBUF /* MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_B1_BASE) */,
    				UDMA_ARB_4, (UDMA_MODE_PER_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
    	// Task4, Dummy read RX buffer to clear IFG, wait for RXIFG trigger
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &EUSCI_B1_SPI->RXBUF /* MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_DST_INC_NONE, &dummyRX,
    				UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
    	// Task 5, load TX buffer to initiate SPI
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &txBuffer[1],
    				UDMA_DST_INC_NONE, &EUSCI_B1_SPI->TXBUF /* MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_B1_BASE) */,
    				UDMA_ARB_4, (UDMA_MODE_PER_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
    	/*
    	 * Task 6, Dummy read RX buffer to clear IFG
    	 * This delay ensures that the chip select happens after the last byte is tranmitted
    	 */
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &EUSCI_B1_SPI->RXBUF /* MAP_SPI_getReceiveBufferAddressForDMA(EUSCI_B2_BASE) */,
    				UDMA_DST_INC_NONE, &dummyRX,
    				UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
        // Task 7, set GPIO, chip select
    	DMA_TaskStructEntry(1, UDMA_SIZE_8,
    				UDMA_SRC_INC_NONE, &DAC_CS,
    				UDMA_DST_INC_NONE, &P6->OUT,
    				UDMA_ARB_4, UDMA_MODE_BASIC)
    };
    
    void main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;           // Stop watchdog timer
        /*
         * Configuring P1.1 as an input and enabling interrupts
         */
        MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);
        MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
        MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);
        MAP_Interrupt_enableInterrupt(INT_PORT1);
    
        /*
         * DAC SPI
         * Configure CLK, MOSI & MISO for SPI0 (EUSCI_B1)
         * P6.3 UCB1CLK
         * P6.4 SIMO
         * P6.5 SOMI
         *
         */
        MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6,
                GPIO_PIN3 | GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION);
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,
                GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION);
        /*
         * ADC SPI
         * Configure CLK, MOSI & MISO for SPI0 (EUSCI_B2)
         * 3.5 CLK
         * 3.6 SIMO
         * 3.7 SOMI
         */
        MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3,
                GPIO_PIN5 | GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION);
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3,
                GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
    
        /* Configure CS pin P3.0 */
        P3->OUT |= BIT0;
        P3->DIR |= BIT0;
        /* Configure CS pin P6.1 */
        P6->OUT |= BIT1;
        P6->DIR |= BIT1;
        /* Debug Port P1.0       */
        P1->DIR |= BIT0;
    
        /*
         * LDO, Vcore0 (default)
         * 24Mhz MCLK,
         * 3Mhz SMCLK
         */
    
        MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_24);
        MAP_CS_initClockSignal(CS_MCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1);
        MAP_CS_initClockSignal(CS_SMCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_8);
    
        /* Configuring SPI module */
        MAP_SPI_initMaster(EUSCI_B2_BASE, &spiMasterConfig_B2);
        MAP_SPI_initMaster(EUSCI_B1_BASE, &spiMasterConfig_B1);
    
        /* Enable the SPI module */
        MAP_SPI_enableModule(EUSCI_B2_BASE);
        MAP_SPI_enableModule(EUSCI_B1_BASE);
    
        MAP_SPI_clearInterruptFlag(EUSCI_B2_BASE,EUSCI_B_SPI_RECEIVE_INTERRUPT);
        MAP_SPI_clearInterruptFlag(EUSCI_B1_BASE,EUSCI_B_SPI_RECEIVE_INTERRUPT);
    
        /* Configuring DMA module */
        MAP_DMA_enableModule();
        MAP_DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable);
    
        /*
         * Assign DMA triggers
         * channel 2 to EUSCI_B1_TX0
         * channel 5 to EUSCI_B2_RX0
         */
        MAP_DMA_assignChannel(DMA_CH3_EUSCIB1RX0);
        MAP_DMA_assignChannel(DMA_CH5_EUSCIB2RX0);
    
        /* Enable DMA interrupt */
        MAP_DMA_assignInterrupt(INT_DMA_INT1, 5);  // Channel 5 is the ADC (RX)
        MAP_DMA_assignInterrupt(INT_DMA_INT2, 3);  // Channel 3 is the DAC (TX)
    
        while(1)
        {
            //MAP_PCM_gotoLPM0();
        	P1->OUT ^= BIT0;
        }
    }
    
    /* Completion interrupt for DMA */
    void DMA_INT1_IRQHandler(void)
    {
        MAP_DMA_disableChannel(5);
        MAP_DMA_disableInterrupt(INT_DMA_INT1);
        MAP_Interrupt_disableInterrupt(INT_DMA_INT1);
        MAP_SPI_clearInterruptFlag(EUSCI_B2_BASE,EUSCI_B_IFG_RXIFG0);
        MAP_DMA_clearInterruptFlag(5);
    	/*
    	 * Translate ADC data to DAC data
    	 * 0 -> MSB (transmit first)
    	 * 1 -> LSB (transmit second)
    	 */
    	txBuffer[0] = (rxBuffer[0] & 0x3) << 6;
    	txBuffer[0] |= (rxBuffer[1] & 0xFC) >> 2;
    	txBuffer[1] = (rxBuffer[1] & 0x3) << 6;
    	txBuffer[1] |= (rxBuffer[2] & 0xFC) >> 2;
    
    	MAP_SPI_clearInterruptFlag(EUSCI_B1_BASE,EUSCI_B_SPI_RECEIVE_INTERRUPT);
    	MAP_DMA_setChannelScatterGather(DMA_CH3_EUSCIB1RX0,TX_TASKS,(void*)&spiDacDmaSeq[0],0);
        MAP_DMA_clearInterruptFlag(DMA_CH3_EUSCIB1RX0 & 0x0F);
        /* Assigning/Enabling Interrupts */
        MAP_DMA_enableInterrupt(INT_DMA_INT2);
        MAP_Interrupt_enableInterrupt(INT_DMA_INT2);
        MAP_DMA_enableChannel(3);
        EUSCI_B1_SPI->IFG |= EUSCI_B_IFG_RXIFG0;
    }
    
    void DMA_INT2_IRQHandler(void)
    {
        MAP_DMA_disableChannel(3);
        MAP_DMA_disableInterrupt(INT_DMA_INT2);
        MAP_Interrupt_disableInterrupt(INT_DMA_INT2);
        MAP_SPI_clearInterruptFlag(EUSCI_B1_BASE,EUSCI_B_IFG_RXIFG0);
        MAP_DMA_clearInterruptFlag(3);
    	P1->OUT ^= BIT0;
    }
    
    void PORT1_IRQHandler(void)
    {
        uint32_t status;
    
        status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
        MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);
    
        /* Toggling the output on the LED */
        if(status & GPIO_PIN1)
        {
        	rxBuffer[0] = 0;
        	rxBuffer[1] = 0;
        	rxBuffer[2] = 0;
    
        	txBuffer[0] = 0;
        	txBuffer[1] = 0;
    
            /*
             * Start SPI read
             */
            //MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P5, GPIO_PIN5);
        	while(status & GPIO_PIN1)
        	{
        	    status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
        	    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);
        	}
            /*
             * Peripheral trigger.  Memory Scatter Gather
             */
            MAP_DMA_setChannelScatterGather(DMA_CH5_EUSCIB2RX0,RX_TASKS,(void*)&spiAdcDmaSeq[0],0);
            MAP_DMA_clearInterruptFlag(DMA_CH5_EUSCIB2RX0 & 0x0F);
            /* Assigning/Enabling Interrupts */
            MAP_DMA_enableInterrupt(INT_DMA_INT1);
            MAP_Interrupt_enableInterrupt(INT_DMA_INT1);
            MAP_DMA_enableChannel(5);
            /*
             * MAP_DMA_requestSoftwareTransfer(5);  The DMA channel5 is set to
             * trigger off of theEUSCIB0RX IFG.  This did not really happen but is
             * forced manually to start the scatter-gather sequence.  Because the
             * setting is 'memory' scatter-gather all triggers (transitions) from
             * primary to auxialry actions will be automatic.  The auxilary action
             * triggers are defined in the task list.
             */
            EUSCI_B2_SPI->IFG |= EUSCI_B_IFG_RXIFG0;
        }
    }
    

    /*
     * -------------------------------------------
     *    MSP432 DriverLib - v3_10_00_09
     * -------------------------------------------
     *
     * --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--*/
    //*****************************************************************************
    //
    // Copyright (C) 2012 - 2015 Texas Instruments Incorporated - http://www.ti.com/
    //
    // 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.
    //
    // MSP432 Family Interrupt Vector Table for CGT
    //
    //****************************************************************************
    
    #include <stdint.h>
    
    /* Forward declaration of the default fault handlers. */
    static void resetISR(void);
    static void nmiISR(void);
    static void faultISR(void);
    static void defaultISR(void);
    
    
    /* External declaration for the reset handler that is to be called when the */
    /* processor is started                                                     */
    extern void _c_int00(void);
    
    /* External declaration for system initialization function                  */
    extern void SystemInit(void);
    
    /* Linker variable that marks the top of the stack. */
    extern unsigned long __STACK_END;
    
    
    /* External declarations for the interrupt handlers used by the application. */
    extern void DMA_INT1_IRQHandler(void);
    extern void DMA_INT2_IRQHandler(void);
    extern void PORT1_IRQHandler(void);
    
    /* Interrupt vector table.  Note that the proper constructs must be placed on this to  */
    /* ensure that it ends up at physical address 0x0000.0000 or at the start of          */
    /* the program if located at a start address other than 0.                            */
    #pragma RETAIN(interruptVectors)
    #pragma DATA_SECTION(interruptVectors, ".intvecs")
    void (* const interruptVectors[])(void) =
    {
        (void (*)(void))((uint32_t)&__STACK_END),
                                                /* The initial stack pointer */
        resetISR,                               /* The reset handler         */
        nmiISR,                                 /* The NMI handler           */
        faultISR,                               /* The hard fault handler    */
        defaultISR,                             /* The MPU fault handler     */
        defaultISR,                             /* The bus fault handler     */
        defaultISR,                             /* The usage fault handler   */
        0,                                      /* Reserved                  */
        0,                                      /* Reserved                  */
        0,                                      /* Reserved                  */
        0,                                      /* Reserved                  */
        defaultISR,                             /* SVCall handler            */
        defaultISR,                             /* Debug monitor handler     */
        0,                                      /* Reserved                  */
        defaultISR,                             /* The PendSV handler        */
        defaultISR,                             /* The SysTick handler       */
        defaultISR,                             /* PSS ISR                   */
        defaultISR,                             /* CS ISR                    */
        defaultISR,                             /* PCM ISR                   */
        defaultISR,                             /* WDT ISR                   */
        defaultISR,                             /* FPU ISR                   */
        defaultISR,                             /* FLCTL ISR                 */
        defaultISR,                             /* COMP0 ISR                 */
        defaultISR,                             /* COMP1 ISR                 */
        defaultISR,                             /* TA0_0 ISR                 */
        defaultISR,                             /* TA0_N ISR                 */
        defaultISR,                             /* TA1_0 ISR                 */
        defaultISR,                             /* TA1_N ISR                 */
        defaultISR,                             /* TA2_0 ISR                 */
        defaultISR,                             /* TA2_N ISR                 */
        defaultISR,                             /* TA3_0 ISR                 */
        defaultISR,                             /* TA3_N ISR                 */
        defaultISR,                             /* EUSCIA0 ISR               */
        defaultISR,                             /* EUSCIA1 ISR               */
        defaultISR,                             /* EUSCIA2 ISR               */
        defaultISR,                             /* EUSCIA3 ISR               */
        defaultISR,                             /* EUSCIB0 ISR               */
        defaultISR,                             /* EUSCIB1 ISR               */
        defaultISR,                             /* EUSCIB2 ISR               */
        defaultISR,                             /* EUSCIB3 ISR               */
    //	ADC14_IRQHandler,                       /* ADC14 ISR                 */
        defaultISR,                             /* ADC14 ISR                 */
        defaultISR,                             /* T32_INT1 ISR              */
        defaultISR,                             /* T32_INT2 ISR              */
        defaultISR,                             /* T32_INTC ISR              */
        defaultISR,                             /* AES ISR                   */
        defaultISR,                             /* RTC ISR                   */
        defaultISR,                             /* DMA_ERR ISR               */
        defaultISR,                             /* DMA_INT3 ISR              */
    //    defaultISR,                             /* DMA_INT2 ISR              */
    	DMA_INT2_IRQHandler,                    /* DMA_INT2 ISR              */
    //	defaultISR,                             /* DMA_INT1 ISR              */
        DMA_INT1_IRQHandler,                    /* DMA_INT1 ISR              */
        defaultISR,                             /* DMA_INT0 ISR              */
    	PORT1_IRQHandler,                       /* PORT1 ISR                 */
    //    defaultISR,                             /* PORT1 ISR                 */
        defaultISR,                             /* PORT2 ISR                 */
        defaultISR,                             /* PORT3 ISR                 */
        defaultISR,                             /* PORT4 ISR                 */
        defaultISR,                             /* PORT5 ISR                 */
        defaultISR,                             /* PORT6 ISR                 */
        defaultISR,                             /* Reserved 41               */
        defaultISR,                             /* Reserved 42               */
        defaultISR,                             /* Reserved 43               */
        defaultISR,                             /* Reserved 44               */
        defaultISR,                             /* Reserved 45               */
        defaultISR,                             /* Reserved 46               */
        defaultISR,                             /* Reserved 47               */
        defaultISR,                             /* Reserved 48               */
        defaultISR,                             /* Reserved 49               */
        defaultISR,                             /* Reserved 50               */
        defaultISR,                             /* Reserved 51               */
        defaultISR,                             /* Reserved 52               */
        defaultISR,                             /* Reserved 53               */
        defaultISR,                             /* Reserved 54               */
        defaultISR,                             /* Reserved 55               */
        defaultISR,                             /* Reserved 56               */
        defaultISR,                             /* Reserved 57               */
        defaultISR,                             /* Reserved 58               */
        defaultISR,                             /* Reserved 59               */
        defaultISR,                             /* Reserved 60               */
        defaultISR,                             /* Reserved 61               */
        defaultISR,                             /* Reserved 62               */
        defaultISR                              /* Reserved 63               */
    };
    
    
    /* This is the code that gets called when the processor first starts execution */
    /* following a reset event.  Only the absolutely necessary set is performed,   */
    /* after which the application supplied entry() routine is called.  Any fancy  */
    /* actions (such as making decisions based on the reset cause register, and    */
    /* resetting the bits in that register) are left solely in the hands of the    */
    /* application.                                                                */
    void resetISR(void)
    {
        SystemInit();
    
        /* Jump to the CCS C Initialization Routine. */
        __asm("    .global _c_int00\n"
              "    b.w     _c_int00");
    }
    
    /* This is the code that gets called when the processor receives a NMI.  This  */
    /* simply enters an infinite loop, preserving the system state for examination */
    /* by a debugger.                                                              */
    static void nmiISR(void)
    {
        /* Fault trap exempt from ULP advisor */
        #pragma diag_push
        #pragma CHECK_ULP("-2.1")
    
        /* Enter an infinite loop. */
        while(1)
        {
        }
    
        #pragma diag_pop
    }
    
    
    /* This is the code that gets called when the processor receives a fault        */
    /* interrupt.  This simply enters an infinite loop, preserving the system state */
    /* for examination by a debugger.                                               */
    static void faultISR(void)
    {
        /* Fault trap exempt from ULP advisor */
        #pragma diag_push
        #pragma CHECK_ULP("-2.1")
    
        /* Enter an infinite loop. */
        while(1)
        {
        }
    
        #pragma diag_pop
    }
    
    
    /* This is the code that gets called when the processor receives an unexpected  */
    /* interrupt.  This simply enters an infinite loop, preserving the system state */
    /* for examination by a debugger.                                               */
    static void defaultISR(void)
    {
        /* Fault trap exempt from ULP advisor */
        #pragma diag_push
        #pragma CHECK_ULP("-2.1")
    
        /* Enter an infinite loop. */
        while(1)
        {
        }
    
        #pragma diag_pop
    }
    

    Daniel,

       I thought it might be beneficial, to the larger community, to provide an (alternative) example where the functions that you describe were completed by the DMA.  In the attached example the scatter-gather method is used to communicate with the ADC on EUSCIB2 via SPI and then to the DAC on EUSCIB1 via SPI.

    Best Regards,

    Chris

**Attention** This is a public forum