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: Data Transfer over UART Using DMA Ping-Pong Mode

Hello,

I am exploring how to send data over the UART interface (EUSCI_A0_MODULE) of the MSP432 launchpad using DMA. To this end, I have successfully tested the data transfer from the uC to the host PC using the  'UDMA_MODE_BASIC' mode. Then I programmed the transfer using the  'UDMA_MODE_PINGPONG'. Despite all my efforts I could not make the DMA work in this particular mode. Here is the source code that I am running on the launchpad: 

#include "rom_map.h"
#include "driverlib.h"
#include <stdint.h>
#include <stdbool.h>
#include <string.h>


#define zCHAN_DMA_UART_TX  DMA_CHANNEL_0

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

//*****************************************************************************
// UART Parameters
//*****************************************************************************
#define zUART_BAUD_RATE 4000000
/* UART Configuration Parameter. 'zUART_BAUD_RATE' baud rate. 
 * Rf. online calculator provided by TI at:
 * software-dl.ti.com/.../index.html
 */
const eUSCI_UART_Config uartConfig =
{
		EUSCI_A_UART_CLOCKSOURCE_SMCLK,                 // SMCLK Clock Source
		12,                                             // BRDIV = 12
		0,                                              // UCxBRF = 0
		0,                                              // UCxBRS = 0
		EUSCI_A_UART_NO_PARITY,                         // No Parity
		EUSCI_A_UART_LSB_FIRST,                         // LSB First
		EUSCI_A_UART_ONE_STOP_BIT,                      // One stop bit
		EUSCI_A_UART_MODE,                              // UART mode
		EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION  // NO Oversampling
};

//*****************************************************************************
// Ping-pong Data buffers
//*****************************************************************************
#define SIZE_BUFF_A_TX 512
#define SIZE_BUFF_B_TX 512
static uint8_t zUI8_BUFF_A_TX[SIZE_BUFF_A_TX];
static uint8_t zUI8_BUFF_B_TX[SIZE_BUFF_B_TX]; 

//*****************************************************************************
// Function 
//*****************************************************************************
void ConfigSysClk(void)
{
	/* Enabling FPU for DCO Frequency calculation */
	MAP_FPU_enableModule();

	/* Setting DCO to 48MHz (upping Vcore) */
	MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
	MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);

	/* wait for the module to initialize */
	uint32_t indConfgClk;
	for(indConfgClk=0;indConfgClk<1000;indConfgClk++);
}

void ConfigLED_Pins(void)
{
	/* LED1: RED */
	MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
	MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);

	/* LED RGB: P2.0: RED, P2.1: GREEN, P2.2: BLUE */
	MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
	MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);

	MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
	MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);

	MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
	MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);

}

void ConfigUart(void)
{
	/* Selecting P1.2 and P1.3 in UART mode */
	MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);

	/* Configuring UART Module */
	MAP_UART_initModule(EUSCI_A0_MODULE, &uartConfig);

	/* Enable UART module */
	MAP_UART_enableModule(EUSCI_A0_MODULE);

	MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
}

void ConfigDma4Uart(void)
{
	/* Configuring DMA module */
	MAP_DMA_enableModule();
	MAP_DMA_setControlBase(controlTable);

	/* Assigning Channel 0 to EUSCIA0TX*/
	MAP_DMA_assignChannel(DMA_CH0_EUSCIA0TX);

	/* Disabling channel attributes of alternate DMA channel which will not be used in the basic DMA mode */
	MAP_DMA_disableChannelAttribute(DMA_CH0_EUSCIA0TX,  UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

	/* Setting control parameters: 'UDMA_SIZE_8' and 'UDMA_SRC_INC_8' are selected coz UART TX/RX data buffer size limited to one character */
	// primary channel
	MAP_DMA_setChannelControl(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,  UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
	// secondary channel
	MAP_DMA_setChannelControl(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,  UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    

	/* Setting channel transfers */
	// primary channel
	MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
			(void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE), SIZE_BUFF_A_TX);
	// secondary channel
	MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
			(void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE), SIZE_BUFF_B_TX);


	/* Assigning interrupts */
	MAP_DMA_assignInterrupt(DMA_INT1, zCHAN_DMA_UART_TX);

	/* Enable intrrupts for both DMA channels */
	MAP_Interrupt_enableInterrupt(DMA_INT1);

	/* Enable DMA channel */
	MAP_DMA_enableChannel(zCHAN_DMA_UART_TX);
}


//*****************************************************************************
// ISR routine for 'DMA_INT1'
//*****************************************************************************
void DMA_UART_TX_IntHndlr(void)
{
	uint32_t ui32Mode;
    
	// Check if the ping-pong "A" transfer is complete.  
	ui32Mode = MAP_DMA_getChannelMode( DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT );
	if(ui32Mode == UDMA_MODE_STOP)
	{
		MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN1);

		MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
					(void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE), SIZE_BUFF_A_TX);
	}

	// Check if the ping-pong "B" transfer is complete. 
	ui32Mode = MAP_DMA_getChannelMode( DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT );
    if(ui32Mode == UDMA_MODE_STOP)
	{
		MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN2);
        
		MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
				(void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE), SIZE_BUFF_B_TX);
	}
}


//*****************************************************************************
// ISR for DMA errors (DMA_ERR ISR)
//*****************************************************************************
void uDMAErrorHandler(void)
{
	uint32_t ui32Status;

	// Check for uDMA error bit
	ui32Status = MAP_DMA_getErrorStatus( );

	// If there is a uDMA error, then clear the error and increment the error counter
	if(ui32Status)
	{
		MAP_DMA_clearErrorStatus();

		// toggle an LED to indicate DMA error
		MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
	}
}


int main(void)
{
	/* Halting WDT  */
	MAP_WDT_A_holdTimer();
    
    /* Initializing buffers */
    memset(zUI8_BUFF_A_TX, 'A', SIZE_BUFF_A_TX);
    memset(zUI8_BUFF_B_TX, 'B', SIZE_BUFF_B_TX);

	/*Config Sys Clk*/
	ConfigSysClk();

	/* Config LED */
	ConfigLED_Pins();

	/* Config UART */
	ConfigUart();

	/* Config DMA */
	ConfigDma4Uart();

    /* Config LPM */
	MAP_PCM_gotoLPM0();
	__no_operation();
}

When I run this program on the uC, and from the host PC connect to the Application/User COM port of the launchpad, I do not receive anything. Could someone point out where is the problem in the code.

Kind regards

Jatala

  • Is there someone who have used the DMA ping-pong mode on the MSP432.
  • Jatala,

    I am working through the code that you posted right now. Hopefully I will have an answer/solution soon.

    Best Regards,
    Tim

  • Jatala,

    I was able to find the part on your code that is causing the problem. The order that you have to enable the DMA interrupts versus the DMA channel is very specific/tricky for the ARM uDMA controller on MSP432. In your current code, you have the following.

    	/* Enable intrrupts for both DMA channels */
    	MAP_Interrupt_enableInterrupt(DMA_INT1);
    
    	/* Enable DMA channel */
    	MAP_DMA_enableChannel(zCHAN_DMA_UART_TX);

    Since the "trigger" for this DMA is the UART transfer buffer being empty, immediately after the interrupts are enabled for DMA_INT1 the processor ends up in a deadlock situation where it constantly is servicing DMA_UART_TX_IntHndlr. The way that the uDMA controller is setup causes the interrupt to be asserted in this situation. In this case, the second line which enables the DMA channel is never actually executed and we are infinitely stuck between these two lines of code (which is why you never see anything on the host UART end). To fix your problem, you should swap the order of the two lines to the following:

        /* Enable DMA channel */
        MAP_DMA_enableChannel(zCHAN_DMA_UART_TX);
    
        /* Enable intrrupts for both DMA channels */
        MAP_Interrupt_enableInterrupt(DMA_INT1);

    Find attached the modified version of your code that I used to get the ping pong mode working. Note that I reduced the baud rate for the UART and the MCLK frequency to make sure that my PC's terminal would be able to keep up. Generally we recommend baud rates of 38400 or lower if you are using the LaunchPad's back channel UART (I used 9600 to be completely safe).

    Also an issue with the code is you are missing the following line of code:

        /* Making it so that we go back to sleep when interrupts end */
        MAP_Interrupt_enableSleepOnIsrExit();

    By default, ARM exits low power mode after it services an ISR. Since your code does not have a dedicated while loop in main, this causes the main loop to return and halt execution of the code. The above line makes it so that the CPU will stay in low power mode after servicing an ISR and in your case never leave the main function.

    Please let me know if this answers your questions and if you got this working on your end. I have tested on my system and see 512 'A' characters being transmitted over UART followed by 512 'B' characters. This happens indefinitely. If you want to stop the transfer, disable the DMA channel (and interrupts) inside the DMA ISR by using the following two lines of code:

        MAP_DMA_disableChannel(0);
        MAP_DMA_disableInterrupt(INT_DMA_INT1);

    I have filed an issue in our internal system and a "ping pong" mode example will be included with the next release of MSP432 DriverLib.

    Best Regards,

    dma_ping_pong_example.c
    #include "rom_map.h"
    #include "driverlib.h"
    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    
    #define zCHAN_DMA_UART_TX  DMA_CHANNEL_0
    
    //*****************************************************************************
    // DMA Control Table
    //*****************************************************************************
    #ifdef ewarm
    #pragma data_alignment=1024
    #else
    #pragma DATA_ALIGN(controlTable, 1024)
    #endif
    uint8_t controlTable[1024];
    
    //*****************************************************************************
    // UART Parameters
    //*****************************************************************************
    #define zUART_BAUD_RATE 9600
    /* UART Configuration Parameter. 'zUART_BAUD_RATE' baud rate.
     * Rf. online calculator provided by TI at:
     * <a href="http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html">software-dl.ti.com/.../index.html</a>
     */
    const eUSCI_UART_Config uartConfig =
    {
    EUSCI_A_UART_CLOCKSOURCE_SMCLK,                 // SMCLK Clock Source
            78,                                     // BRDIV = 78
            2,                                       // UCxBRF = 2
            0,                                       // UCxBRS = 0
            EUSCI_A_UART_NO_PARITY,                         // No Parity
            EUSCI_A_UART_LSB_FIRST,                         // LSB First
            EUSCI_A_UART_ONE_STOP_BIT,                      // One stop bit
            EUSCI_A_UART_MODE,                              // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION  // NO Oversampling
            };
    
    //*****************************************************************************
    // Ping-pong Data buffers
    //*****************************************************************************
    #define SIZE_BUFF_A_TX 512
    #define SIZE_BUFF_B_TX 512
    static uint8_t zUI8_BUFF_A_TX[SIZE_BUFF_A_TX];
    static uint8_t zUI8_BUFF_B_TX[SIZE_BUFF_B_TX];
    
    //*****************************************************************************
    // Function
    //*****************************************************************************
    void ConfigSysClk(void)
    {
        /* Enabling FPU for DCO Frequency calculation */
        MAP_FPU_enableModule();
    
        /* Setting DCO to 48MHz (upping Vcore) */
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
    
        /* wait for the module to initialize */
        uint32_t indConfgClk;
        for (indConfgClk = 0; indConfgClk < 1000; indConfgClk++)
            ;
    }
    
    void ConfigLED_Pins(void)
    {
        /* LED1: RED */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
    
        /* LED RGB: P2.0: RED, P2.1: GREEN, P2.2: BLUE */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);
    
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
    
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);
    
    }
    
    void ConfigUart(void)
    {
        /* Selecting P1.2 and P1.3 in UART mode */
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
                GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
    
        /* Configuring UART Module */
        MAP_UART_initModule(EUSCI_A0_MODULE, &uartConfig);
    
        /* Enable UART module */
        MAP_UART_enableModule(EUSCI_A0_MODULE);
    
    
        MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    }
    
    void ConfigDma4Uart(void)
    {
        /* Configuring DMA module */
        MAP_DMA_enableModule();
        MAP_DMA_setControlBase(controlTable);
    
        /* Assigning Channel 0 to EUSCIA0TX*/
        MAP_DMA_assignChannel(DMA_CH0_EUSCIA0TX);
    
        /* Disabling channel attributes of alternate DMA channel which will not be used in the basic DMA mode */
        MAP_DMA_disableChannelAttribute(DMA_CH0_EUSCIA0TX,
                UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY
                        | UDMA_ATTR_REQMASK);
    
        /* Setting control parameters: 'UDMA_SIZE_8' and 'UDMA_SRC_INC_8' are selected coz UART TX/RX data buffer size limited to one character */
        // primary channel
        MAP_DMA_setChannelControl(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
        // secondary channel
        MAP_DMA_setChannelControl(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    
        /* Setting channel transfers */
        // primary channel
        MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
                (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                SIZE_BUFF_A_TX);
        // secondary channel
        MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
                (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                SIZE_BUFF_B_TX);
    
        /* Assigning interrupts */
        MAP_DMA_assignInterrupt(DMA_INT1, zCHAN_DMA_UART_TX);
        MAP_DMA_clearInterruptFlag(zCHAN_DMA_UART_TX);
    
        /* Making it so that we go back to sleep when interrupts end */
        MAP_Interrupt_enableSleepOnIsrExit();
    
        /* Enable DMA channel */
        MAP_DMA_enableChannel(zCHAN_DMA_UART_TX);
    
        /* Enable intrrupts for both DMA channels */
        /* FROM TIM-TI, We need to enable interrupts after enabling the DMA channel
         * to ensure that we don't get stuck in a "deadlock" situation */
        MAP_Interrupt_enableInterrupt(DMA_INT1);
    
    }
    
    //*****************************************************************************
    // ISR routine for 'DMA_INT1'
    //*****************************************************************************
    void DMA_UART_TX_IntHndlr(void)
    {
        uint32_t ui32Mode;
        MAP_DMA_clearInterruptFlag(0);
    
        // Check if the ping-pong "A" transfer is complete.
        ui32Mode = MAP_DMA_getChannelMode( DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT);
        if (ui32Mode == UDMA_MODE_STOP)
        {
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN1);
    
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(
                            EUSCI_A0_MODULE), SIZE_BUFF_A_TX);
        }
    
        // Check if the ping-pong "B" transfer is complete.
        ui32Mode = MAP_DMA_getChannelMode( DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT);
        if (ui32Mode == UDMA_MODE_STOP)
        {
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN2);
    
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(
                            EUSCI_A0_MODULE), SIZE_BUFF_B_TX);
        }
    }
    
    //*****************************************************************************
    // ISR for DMA errors (DMA_ERR ISR)
    //*****************************************************************************
    void uDMAErrorHandler(void)
    {
        uint32_t ui32Status;
    
        // Check for uDMA error bit
        ui32Status = MAP_DMA_getErrorStatus();
    
        // If there is a uDMA error, then clear the error and increment the error counter
        if (ui32Status)
        {
            MAP_DMA_clearErrorStatus();
    
            // toggle an LED to indicate DMA error
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
        }
    }
    
    int main(void)
    {
        /* Halting WDT  */
        MAP_WDT_A_holdTimer();
    
        /* Initializing buffers */
        memset(zUI8_BUFF_A_TX, 'A', SIZE_BUFF_A_TX);
        memset(zUI8_BUFF_B_TX, 'B', SIZE_BUFF_B_TX);
    
        /*Config Sys Clk*/
        ConfigSysClk();
    
        /* Config LED */
        ConfigLED_Pins();
    
        /* Config UART */
        ConfigUart();
    
        /* Config DMA */
        ConfigDma4Uart();
    
        /* Config LPM */
        MAP_PCM_gotoLPM0();
    }
    

  • Hi Timothy,

    Thanks for the detailed answer, and with this everything works now. About the baud rate limit: "Generally we recommend baud rates of 38400", 38400 is well below what I need for my application. The lowest I can go is 1.5 Mbit/s. Do you know what is the maximum recommended limit on the rate beyond which it is not safe to use the UART port.

    Kind regards
    Jatala
  • Jatala,

    According to the datasheet, the maximum clock frequency you can set for the BITCLK (baud rate) is 3MHZ when you are operating at VCORE1:

    Keep in mind to achieve this rate, you have to increase the core voltage to VCORE1. You can do this with the following DriverLib API:

    PCM_setCoreVoltageLevel(PCM_VCORE1);

    Best Regards,

  • Hi Timothy,

    Thanks for the info.

    I am experimenting with the DMA ping-pong mode with all the modifications you have proposed. Everything is working like a charm :)

    Next I added a periodic timer, with a period of 5 seconds. Within the timer ISR, I

    1) disable DMA channel and its associated interrupt if it was already enabled

    2) otherwise enable the DMA channel and the interrupt

    The DMA channel is enabled when the the timer interrupt fires first time. So the timer ISR disables the channel. When the timer interrupt fires second timer,

    the DMA channel is enabled again, and so. The DMA transfers data when it is enabled first time. However latter on, when the timer ISR enables the

    DMA channel no data transfer takes place.  I am baffled what is happening. I have tried reconfiguring the DMA channels (PRI and ALT), besides resetting

    the channel transfers, and that too did not help. The code I am working on is in the attachment. Please see what is going on here.

    BR

    dmaPingPong_timerStartStop.c
    #include "rom_map.h"
    #include "driverlib.h"
    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    
    #define zCHAN_DMA_UART_TX  DMA_CHANNEL_0
    
    //*****************************************************************************
    // DMA Control Table
    //*****************************************************************************
    #ifdef ewarm
    #pragma data_alignment=1024
    #else
    #pragma DATA_ALIGN(controlTable, 1024)
    #endif
    uint8_t controlTable[1024];
    
    //*****************************************************************************
    // UART Parameters
    //*****************************************************************************
    #define zUART_BAUD_RATE 9600
    /* UART Configuration Parameter. 'zUART_BAUD_RATE' baud rate.
     * Rf. online calculator provided by TI at:
     * <a href="http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html">software-dl.ti.com/.../index.html</a>
     */
    const eUSCI_UART_Config uartConfig =
    {
    EUSCI_A_UART_CLOCKSOURCE_SMCLK,                 // SMCLK Clock Source
            78,                                     // BRDIV = 78
            2,                                       // UCxBRF = 2
            0,                                       // UCxBRS = 0
            EUSCI_A_UART_NO_PARITY,                         // No Parity
            EUSCI_A_UART_LSB_FIRST,                         // LSB First
            EUSCI_A_UART_ONE_STOP_BIT,                      // One stop bit
            EUSCI_A_UART_MODE,                              // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION  // NO Oversampling
            };
    
    //*****************************************************************************
    // Ping-pong Data buffers
    //*****************************************************************************
    #define SIZE_BUFF_A_TX 16
    #define SIZE_BUFF_B_TX 16
    static uint8_t zUI8_BUFF_A_TX[SIZE_BUFF_A_TX];
    static uint8_t zUI8_BUFF_B_TX[SIZE_BUFF_B_TX];
    
    //*****************************************************************************
    // Function
    //*****************************************************************************
    void ConfigSysClk(void)
    {
        /* Enabling FPU for DCO Frequency calculation */
        MAP_FPU_enableModule();
    
        /* Setting DCO to 48MHz (upping Vcore) */
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
    }
    
    void ConfigLED_Pins(void)
    {
        /* LED1: RED */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
    
        /* LED RGB: P2.0: RED, P2.1: GREEN, P2.2: BLUE */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);
    
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
    
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);
    
    }
    
    void ConfigUart(void)
    {
        /* Selecting P1.2 and P1.3 in UART mode */
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
                GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
    
        /* Configuring UART Module */
        MAP_UART_initModule(EUSCI_A0_MODULE, &uartConfig);
    
        /* Enable UART module */
        MAP_UART_enableModule(EUSCI_A0_MODULE);
    
    
        MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    }
    
    void ConfigDma4Uart(void)
    {
        /* Configuring DMA module */
        MAP_DMA_enableModule();
        MAP_DMA_setControlBase(controlTable);
    
        /* Assigning Channel 0 to EUSCIA0TX*/
        MAP_DMA_assignChannel(DMA_CH0_EUSCIA0TX);
    
        /* Disabling channel attributes of alternate DMA channel which will not be used in the basic DMA mode */
        MAP_DMA_disableChannelAttribute(DMA_CH0_EUSCIA0TX,
                UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY
                        | UDMA_ATTR_REQMASK);
    
        /* Setting control parameters: primary & secondary channels */
        MAP_DMA_setChannelControl(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
        MAP_DMA_setChannelControl(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    
        /* Setting channel transfers: primary & secondary channels */
        MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
                (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                SIZE_BUFF_A_TX);
        MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
                (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                SIZE_BUFF_B_TX);
    
        /* Assigning interrupt*/
        MAP_DMA_assignInterrupt(DMA_INT1, zCHAN_DMA_UART_TX);
        /* Clear interrupt*/
        MAP_DMA_clearInterruptFlag(zCHAN_DMA_UART_TX);
    
        /* Enable DMA channel */
        MAP_DMA_enableChannel(zCHAN_DMA_UART_TX);
    
        /* Enable intrrupts for DMA channel */
        /* FROM TIM-TI, We need to enable interrupts after enabling the DMA channel
         * to ensure that we don't get stuck in a "deadlock" situation */
        MAP_Interrupt_enableInterrupt(DMA_INT1);
    
    }
    
    //*****************************************************************************
    // ISR routine for 'DMA_INT1'
    //*****************************************************************************
    void DMA_UART_TX_IntHndlr(void)
    {
        uint32_t ui32Mode;
        MAP_DMA_clearInterruptFlag(0);
    
        // Check if the ping-pong "A" transfer is complete.
        ui32Mode = MAP_DMA_getChannelMode( DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT);
        if (ui32Mode == UDMA_MODE_STOP)
        {
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN2);
    
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(
                            EUSCI_A0_MODULE), SIZE_BUFF_A_TX);
        }
    
        // Check if the ping-pong "B" transfer is complete.
        ui32Mode = MAP_DMA_getChannelMode( DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT);
        if (ui32Mode == UDMA_MODE_STOP)
        {
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN1);
    
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(
                            EUSCI_A0_MODULE), SIZE_BUFF_B_TX);
        }
    }
    
    //*****************************************************************************
    // ISR for DMA errors (DMA_ERR ISR)
    //*****************************************************************************
    void uDMAErrorHandler(void)
    {
        uint32_t ui32Status;
    
        // Check for uDMA error bit
        ui32Status = MAP_DMA_getErrorStatus();
    
        // If there is a uDMA error, then clear the error and increment the error counter
        if (ui32Status)
        {
            MAP_DMA_clearErrorStatus();
    
            // toggle an LED to indicate DMA error
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
        }
    }
    
    
    void ConfigSTimer(void)
    {
    	/* Configuring Timer32 to 60 msec of DCO Clk in periodic mode */
    	MAP_Timer32_initModule(TIMER32_0_MODULE, TIMER32_PRESCALER_1, TIMER32_32BIT, TIMER32_PERIODIC_MODE);
    
    	/* enable timer entrupt*/
    	MAP_Interrupt_enableInterrupt(INT_T32_INT1);
    	MAP_Timer32_enableInterrupt(TIMER32_0_MODULE);
    
    	/* set value of timer period */
    	uint32_t timerPeriod;
    	timerPeriod  = (uint32_t)(5.0*((double)MAP_CS_getMCLK()));
    
        MAP_Timer32_setCount(TIMER32_0_MODULE, timerPeriod);
        MAP_Timer32_startTimer(TIMER32_0_MODULE, false);
    }
    
    
    
    void timer0_IntHndr(void)
    {
    	// Clear timer interrupt
    	MAP_Timer32_clearInterruptFlag(TIMER32_0_MODULE);
    
    	if (DMA_isChannelEnabled(DMA_CH0_EUSCIA0TX))
    	{
    		 MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
    
    		 MAP_DMA_disableChannel(zCHAN_DMA_UART_TX);
    		 MAP_DMA_disableInterrupt(DMA_INT1);
    
    		 MAP_DMA_clearInterruptFlag(zCHAN_DMA_UART_TX);
    	}
    	else
    	{
    		MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN0);
    
    		/* Setting channel transfers: primary & secondary channels */
    		MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
    				UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
    				(void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
    				SIZE_BUFF_A_TX);
    		MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
    				UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
    				(void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
    				SIZE_BUFF_B_TX);
    
    		/* Enable DMA channel */
    		MAP_DMA_enableChannel(zCHAN_DMA_UART_TX);
    
    		/* Enable intrrupts for DMA channel */
    		MAP_Interrupt_enableInterrupt(DMA_INT1);
    	}
    }
    
    int main(void)
    {
        /* Halting WDT  */
        MAP_WDT_A_holdTimer();
    
        /* Initializing buffers */
        memset(zUI8_BUFF_A_TX, 'A', SIZE_BUFF_A_TX);
        memset(zUI8_BUFF_B_TX, 'B', SIZE_BUFF_B_TX);
    
        /*Config Sys Clk*/
        ConfigSysClk();
    
        /* Config LED */
        ConfigLED_Pins();
    
        /* Config UART */
        ConfigUart();
    
        /* Config DMA */
        ConfigDma4Uart();
    
        /* Config Timer*/
        ConfigSTimer();
    
        /* Making it so that we go back to sleep when interrupts end */
        MAP_Interrupt_enableSleepOnIsrExit();
    
        /* Config LPM */
        MAP_PCM_gotoLPM0();
    }
    
    dmaPingPong_timerStartStop.c
    #include "rom_map.h"
    #include "driverlib.h"
    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    
    #define zCHAN_DMA_UART_TX  DMA_CHANNEL_0
    
    //*****************************************************************************
    // DMA Control Table
    //*****************************************************************************
    #ifdef ewarm
    #pragma data_alignment=1024
    #else
    #pragma DATA_ALIGN(controlTable, 1024)
    #endif
    uint8_t controlTable[1024];
    
    //*****************************************************************************
    // UART Parameters
    //*****************************************************************************
    #define zUART_BAUD_RATE 9600
    /* UART Configuration Parameter. 'zUART_BAUD_RATE' baud rate.
     * Rf. online calculator provided by TI at:
     * <a href="http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html">software-dl.ti.com/.../index.html</a>
     */
    const eUSCI_UART_Config uartConfig =
    {
    EUSCI_A_UART_CLOCKSOURCE_SMCLK,                 // SMCLK Clock Source
            78,                                     // BRDIV = 78
            2,                                       // UCxBRF = 2
            0,                                       // UCxBRS = 0
            EUSCI_A_UART_NO_PARITY,                         // No Parity
            EUSCI_A_UART_LSB_FIRST,                         // LSB First
            EUSCI_A_UART_ONE_STOP_BIT,                      // One stop bit
            EUSCI_A_UART_MODE,                              // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION  // NO Oversampling
            };
    
    //*****************************************************************************
    // Ping-pong Data buffers
    //*****************************************************************************
    #define SIZE_BUFF_A_TX 16
    #define SIZE_BUFF_B_TX 16
    static uint8_t zUI8_BUFF_A_TX[SIZE_BUFF_A_TX];
    static uint8_t zUI8_BUFF_B_TX[SIZE_BUFF_B_TX];
    
    //*****************************************************************************
    // Function
    //*****************************************************************************
    void ConfigSysClk(void)
    {
        /* Enabling FPU for DCO Frequency calculation */
        MAP_FPU_enableModule();
    
        /* Setting DCO to 48MHz (upping Vcore) */
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
    }
    
    void ConfigLED_Pins(void)
    {
        /* LED1: RED */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
    
        /* LED RGB: P2.0: RED, P2.1: GREEN, P2.2: BLUE */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);
    
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
    
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);
    
    }
    
    void ConfigUart(void)
    {
        /* Selecting P1.2 and P1.3 in UART mode */
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
                GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
    
        /* Configuring UART Module */
        MAP_UART_initModule(EUSCI_A0_MODULE, &uartConfig);
    
        /* Enable UART module */
        MAP_UART_enableModule(EUSCI_A0_MODULE);
    
    
        MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    }
    
    void ConfigDma4Uart(void)
    {
        /* Configuring DMA module */
        MAP_DMA_enableModule();
        MAP_DMA_setControlBase(controlTable);
    
        /* Assigning Channel 0 to EUSCIA0TX*/
        MAP_DMA_assignChannel(DMA_CH0_EUSCIA0TX);
    
        /* Disabling channel attributes of alternate DMA channel which will not be used in the basic DMA mode */
        MAP_DMA_disableChannelAttribute(DMA_CH0_EUSCIA0TX,
                UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY
                        | UDMA_ATTR_REQMASK);
    
        /* Setting control parameters: primary & secondary channels */
        MAP_DMA_setChannelControl(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
        MAP_DMA_setChannelControl(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    
        /* Setting channel transfers: primary & secondary channels */
        MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
                (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                SIZE_BUFF_A_TX);
        MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
                (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                SIZE_BUFF_B_TX);
    
        /* Assigning interrupt*/
        MAP_DMA_assignInterrupt(DMA_INT1, zCHAN_DMA_UART_TX);
        /* Clear interrupt*/
        MAP_DMA_clearInterruptFlag(zCHAN_DMA_UART_TX);
    
        /* Enable DMA channel */
        MAP_DMA_enableChannel(zCHAN_DMA_UART_TX);
    
        /* Enable intrrupts for DMA channel */
        /* FROM TIM-TI, We need to enable interrupts after enabling the DMA channel
         * to ensure that we don't get stuck in a "deadlock" situation */
        MAP_Interrupt_enableInterrupt(DMA_INT1);
    
    }
    
    //*****************************************************************************
    // ISR routine for 'DMA_INT1'
    //*****************************************************************************
    void DMA_UART_TX_IntHndlr(void)
    {
        uint32_t ui32Mode;
        MAP_DMA_clearInterruptFlag(0);
    
        // Check if the ping-pong "A" transfer is complete.
        ui32Mode = MAP_DMA_getChannelMode( DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT);
        if (ui32Mode == UDMA_MODE_STOP)
        {
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN2);
    
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(
                            EUSCI_A0_MODULE), SIZE_BUFF_A_TX);
        }
    
        // Check if the ping-pong "B" transfer is complete.
        ui32Mode = MAP_DMA_getChannelMode( DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT);
        if (ui32Mode == UDMA_MODE_STOP)
        {
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN1);
    
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(
                            EUSCI_A0_MODULE), SIZE_BUFF_B_TX);
        }
    }
    
    //*****************************************************************************
    // ISR for DMA errors (DMA_ERR ISR)
    //*****************************************************************************
    void uDMAErrorHandler(void)
    {
        uint32_t ui32Status;
    
        // Check for uDMA error bit
        ui32Status = MAP_DMA_getErrorStatus();
    
        // If there is a uDMA error, then clear the error and increment the error counter
        if (ui32Status)
        {
            MAP_DMA_clearErrorStatus();
    
            // toggle an LED to indicate DMA error
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
        }
    }
    
    
    void ConfigSTimer(void)
    {
    	/* Configuring Timer32 to 60 msec of DCO Clk in periodic mode */
    	MAP_Timer32_initModule(TIMER32_0_MODULE, TIMER32_PRESCALER_1, TIMER32_32BIT, TIMER32_PERIODIC_MODE);
    
    	/* enable timer entrupt*/
    	MAP_Interrupt_enableInterrupt(INT_T32_INT1);
    	MAP_Timer32_enableInterrupt(TIMER32_0_MODULE);
    
    	/* set value of timer period */
    	uint32_t timerPeriod;
    	timerPeriod  = (uint32_t)(5.0*((double)MAP_CS_getMCLK()));
    
        MAP_Timer32_setCount(TIMER32_0_MODULE, timerPeriod);
        MAP_Timer32_startTimer(TIMER32_0_MODULE, false);
    }
    
    
    
    void timer0_IntHndr(void)
    {
    	// Clear timer interrupt
    	MAP_Timer32_clearInterruptFlag(TIMER32_0_MODULE);
    
    	if (DMA_isChannelEnabled(DMA_CH0_EUSCIA0TX))
    	{
    		 MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
    
    		 MAP_DMA_disableChannel(zCHAN_DMA_UART_TX);
    		 MAP_DMA_disableInterrupt(DMA_INT1);
    
    		 MAP_DMA_clearInterruptFlag(zCHAN_DMA_UART_TX);
    	}
    	else
    	{
    		MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN0);
    
    		/* Setting channel transfers: primary & secondary channels */
    		MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
    				UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
    				(void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
    				SIZE_BUFF_A_TX);
    		MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
    				UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
    				(void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
    				SIZE_BUFF_B_TX);
    
    		/* Enable DMA channel */
    		MAP_DMA_enableChannel(zCHAN_DMA_UART_TX);
    
    		/* Enable intrrupts for DMA channel */
    		MAP_Interrupt_enableInterrupt(DMA_INT1);
    	}
    }
    
    int main(void)
    {
        /* Halting WDT  */
        MAP_WDT_A_holdTimer();
    
        /* Initializing buffers */
        memset(zUI8_BUFF_A_TX, 'A', SIZE_BUFF_A_TX);
        memset(zUI8_BUFF_B_TX, 'B', SIZE_BUFF_B_TX);
    
        /*Config Sys Clk*/
        ConfigSysClk();
    
        /* Config LED */
        ConfigLED_Pins();
    
        /* Config UART */
        ConfigUart();
    
        /* Config DMA */
        ConfigDma4Uart();
    
        /* Config Timer*/
        ConfigSTimer();
    
        /* Making it so that we go back to sleep when interrupts end */
        MAP_Interrupt_enableSleepOnIsrExit();
    
        /* Config LPM */
        MAP_PCM_gotoLPM0();
    }
    

    Jatala


     

  • Jatala,

    Looking at your code, your problem comes when you are re-enabling interrupts in your timer controller:

    void timer0_IntHndr(void)
    {
        // Clear timer interrupt
        MAP_Timer32_clearInterruptFlag(TIMER32_0_MODULE);
    
        if (DMA_isChannelEnabled(DMA_CH0_EUSCIA0TX))
        {
             MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
    
             MAP_DMA_disableChannel(zCHAN_DMA_UART_TX);
             MAP_DMA_disableInterrupt(DMA_INT1);
    
             MAP_DMA_clearInterruptFlag(zCHAN_DMA_UART_TX);
        }
        else
        {
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN0);
    
            /* Setting channel transfers: primary & secondary channels */
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                    SIZE_BUFF_A_TX);
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                    SIZE_BUFF_B_TX);
    
            /* Enable DMA channel */
            MAP_DMA_enableChannel(zCHAN_DMA_UART_TX);
    
            /* Enable intrrupts for DMA channel */
            MAP_Interrupt_enableInterrupt(DMA_INT1);
        }
    }

    For MSP432, there are a few levels of interrupt controls for enabling/disabling/etc. There are peripheral level controllers (DMA, ADC14, WDT_A, etc.) which control the specific interrupts for each specific peripheral. There are also controls on the ARM core NVIC level (the Interrupt_ DriverLib APIs) which will enable/disable interrupts for an entire peripheral on the CPU level. What you are doing is disabling the DMA interrupts on the DMA peripheral level with the following line in the timer branch where the DMA channel is enabled:

             MAP_DMA_disableInterrupt(DMA_INT1);

    ... but when you go back to re-enable the interrupts in the else statement of the same branch, you are using the wrong API:

    MAP_Interrupt_enableInterrupt(DMA_INT1);

    To fix your problems, simply change the above API to:

    MAP_DMA_enableInterrupt(DMA_INT1);

    This should cause all of the quirkiness that you've been seeing with your interrupt behavior to go away and let the DMA module ping pong away.

    A few other notes looking through your code, in the timer ISR you do not need the following lines:

            /* Setting channel transfers: primary & secondary channels */
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_PRI_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_A_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                    SIZE_BUFF_A_TX);
            MAP_DMA_setChannelTransfer(DMA_CH0_EUSCIA0TX | UDMA_ALT_SELECT,
                    UDMA_MODE_PINGPONG, zUI8_BUFF_B_TX,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A0_MODULE),
                    SIZE_BUFF_B_TX);

    This information is persisted and you do not need to set it again when enabling/disabling the DMA channels.

    Additionally, when you set the period of your timer you are using double precision math:

        timerPeriod  = (uint32_t)(5.0*((double)MAP_CS_getMCLK()));

    This is highly advised against as double precision is not needed here and tends to be terribly inefficient. I'd recommend changing it to the following:

    timerPeriod  = (uint32_t)(5*MAP_CS_getMCLK());

    I hope this answers all your questions. If you have any additional questions, do not hesitate to let us know.

    Best Regards,

  • Hi Timothy,

    Once again many thanks for pointing out the problem, and suggestions to improve the code.

    Now the ping-pong works by replacing "MAP_Interrupt_enableInterrupt(DMA_INT1)" with "MAP_DMA_enableInterrupt(DMA_INT1)" in the timer ISR :)

    However, when I do the same change in 'ConfigDma4Uart(void)' function it does not work even the first time. Could you please clarify why this does not work. Does this mean, first time we have to use 'MAP_Interrupt_enableInterrupt' to enable interrupt, and latter on we can use 'DMA_enableInterrupt' ?


    BR

    Jatala

    ,

  • Jatala,

    Perhaps this slide will clear things up:

    When you enable interrupts in your ConfigDma4Uart function, you have to use both DMA_enableInterrupt and Interrupt_enableInterrupt for the interrupts to actually be enabled. When you disable interrupts in your ISR however, you only need to use DMA_enableInterrupt/DMA_disableInterrupt. You could also use the Interrupt_enableInterrupt/Interrupt_disableInterrupt functions in the ISR instead of the DMA specific APIs, however these functions will enable/disable all DMA interrupts (if you have DMA transactions going on different channels this would be a problem).

    Note that the "master" interrupts in the chart above are already enabled on reset.

    Best Regards,

  • Hi Timothy,

    Thanks a lot for explaining all these things.

    Kind regards
    Jatala
  • Hello Timothy,

    Maybe you should change the data alignment of dma control structures in dma examples. When trying this code I noticed, that GCC does not support the DATA_ALIGN pragma used currently: 

    #ifdef ewarm
    #pragma data_alignment=1024
    #else
    #pragma DATA_ALIGN(controlTable, 1024)
    #endif
    uint8_t controlTable[1024]; 

    But as stated here it could be made compatible with GCC and TI compiler:

    #ifdef ewarm
    #pragma data_alignment=1024
    uint8_t controlTable[1024];
    #else
    uint8_t controlTable[1024] __attribute__ ((aligned (1024)));
    #endif
     

    Thanks and best regards

  • Hi Timothy and Jatala,

    I took your code as a reference point. But I have some changes:
    1. When I change buffer size to be less than 7 it stop working, i.e. it sends first portion and then stops. Any ideas why?
    2. I need to update the buffers on the fly ( after transmission). I choose to do it inside the interrupt (remember my buffer is small = 8 bytes).
    So when I touch the buffer the mechanism also stops working. What I do wrong? Here is my interrupt attached.

    void DMA_Audio_TX_Isr_Handler(void)
    {
    uint32_t ui32Mode;
    MAP_DMA_clearInterruptFlag(DMA_CHANNEL_6);

    // Check if the ping-pong "A" transfer is complete.
    ui32Mode = MAP_DMA_getChannelMode( DMA_CH6_EUSCIA3TX | UDMA_PRI_SELECT);
    if (ui32Mode == UDMA_MODE_STOP)
    {
    // DMA_AUDIO_Sample_Index += 2;
    // if(DMA_AUDIO_Sample_Index < AUDIO_SAMPLE_SIZE - 10){
    // DMA_AUDIO_Sample_Index = 0;
    // }
    // if(DMA_AUDIO_Sample_Index < 4){
    DMA_Audio_Fill_Buffer(DMA_FILL_BUFFER_B);

    MAP_DMA_setChannelTransfer(DMA_CH6_EUSCIA3TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, AUDIO_TX_Buffer_A,
    (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A3_MODULE), DMA_AUDIO_TX_BUFFER_SIZE);
    // }
    // else{
    // DMA_Audio_Stop_Sound();
    // }
    }

    // Check if the ping-pong "B" transfer is complete.
    ui32Mode = MAP_DMA_getChannelMode( DMA_CH6_EUSCIA3TX | UDMA_ALT_SELECT);
    if (ui32Mode == UDMA_MODE_STOP)
    {
    DMA_Audio_Fill_Buffer(DMA_FILL_BUFFER_A);

    MAP_DMA_setChannelTransfer(DMA_CH6_EUSCIA3TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, AUDIO_TX_Buffer_B,
    (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A3_MODULE), DMA_AUDIO_TX_BUFFER_SIZE);
    }
    }

    Kind regards,
    Andrei Zinenko
  • My DMA_Audio_Fill_Buffer function:

    void DMA_Audio_Fill_Buffer(DMA_Buffer_Name_t buffer_name)
    {
    uint32_t temp_buffer;

    /* Put audio data bytes at proper place in future buffer and make shift right one bit */
    temp_buffer = ((Cuckoo_15_rawData[DMA_AUDIO_Sample_Index]) << (24 - 1)) + ((Cuckoo_15_rawData[DMA_AUDIO_Sample_Index+1]) << (16 - 1));

    if ((buffer_name == DMA_FILL_BUFFER_A) || (buffer_name == DMA_FILL_BOTH_BUFFERS)) {
    AUDIO_TX_Buffer_A[0] = (uint8_t) (temp_buffer >> 24);
    AUDIO_TX_Buffer_A[1] = (uint8_t) (temp_buffer >> 16);
    AUDIO_TX_Buffer_A[2] = (uint8_t) (temp_buffer >> 8);
    AUDIO_TX_Buffer_A[3] = (uint8_t) (temp_buffer );
    AUDIO_TX_Buffer_A[4] = (uint8_t) (temp_buffer );
    AUDIO_TX_Buffer_A[5] = (uint8_t) (temp_buffer );
    AUDIO_TX_Buffer_A[6] = (uint8_t) (temp_buffer );
    AUDIO_TX_Buffer_A[7] = (uint8_t) (temp_buffer );
    }

    if ((buffer_name == DMA_FILL_BUFFER_B) || (buffer_name == DMA_FILL_BOTH_BUFFERS)) {
    AUDIO_TX_Buffer_B[0] = (uint8_t) (temp_buffer >> 24);
    AUDIO_TX_Buffer_B[1] = (uint8_t) (temp_buffer >> 16);
    AUDIO_TX_Buffer_B[2] = (uint8_t) (temp_buffer >> 8);
    AUDIO_TX_Buffer_B[3] = (uint8_t) (temp_buffer );
    AUDIO_TX_Buffer_B[4] = (uint8_t) (temp_buffer );
    AUDIO_TX_Buffer_B[5] = (uint8_t) (temp_buffer );
    AUDIO_TX_Buffer_B[6] = (uint8_t) (temp_buffer );
    AUDIO_TX_Buffer_B[7] = (uint8_t) (temp_buffer );
    }

    }
  • user138497234 ,

    Thanks for this catch.

    Fixed this- it will be reflected in the next release.

    BR,
    Tim

  • Andrei,

    To isolate the problem, I took the reference code, trimmed it down to simplify, and added your two use cases:

    • Having ping pong buffers "A" and "B" of size 7
    • Changing the data in the ISR. In my case, I increment the current character and memset the buffer

    I am talking through the back channel UART connection of the LaunchPad of the computer and everything seems to be working correctly. Perhaps if you sent me your full code (either here or PM) I would be able to help debug a bit more thoroughly? Find my reference code below:

    msp432_ping_pong.zip

    Best Regards,

  • Hi Timothy,

    Thank you for your response. Small addition it about the buffer size. It do work with size = 7 and don't with size = 6. In ideal I want to send 4 bytes from each buffer and do some actions between the buffers (GPIO). Currently I work with 12.288 MHz for SMCK from DCO and with 24 MHz for MCKL from MODOSC. I use SMCK for my SPI and divide it by 6 so SPI clock is 2.048 MHz. MCU is MSP432.

    One more strange thing, if I change the line:

    MAP_DMA_setChannelTransfer(DMA_CH6_EUSCIA3TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, AUDIO_TX_Buffer_A,
                    (void*) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A3_MODULE), DMA_AUDIO_TX_BUFFER_SIZE);

    with :

    MAP_DMA_setChannelTransfer(DMA_CH6_EUSCIA3TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, AUDIO_TX_Buffer_A,
                    (void*) MAP_SPI_getTransmitBufferAddressForDMA(EUSCI_A3_MODULE), DMA_AUDIO_TX_BUFFER_SIZE);

    It also does not work.

    Kind regards,

    Andrei

  • Hi Timothy,

    Do you have any news about those issues to share?

    Kind regards,
    Andrei Zinenko

  • Hi,

    I also noticed, that in SPI Mode there seems to be no dma_request by the peripheral. I had to do a software request, and then one byte was transmitted. But doing a software request for every single byte is against the idea of any DMA from my point of view.
    I would appreciate a functional SPI DMA example code by TI (or confirmation of bug).

    Regards
  • Hello Timothy, 

    i checked the alignment of the controlTable in MSPWare v3.10.00 beta and found that the DMA example with SPI contains a compiler checking for GCC while the examples for I2C, CRC32 and software transfer are not compatible with GCC. Probably they should be changed to the better compiler detection as in the SPI example.

  • How does this work for DMA channels that use interrupt 0?

    I have 3 uarts that I want to use DMA with concurrently, so interrupt 0 may need to be enabled for channel DMA channel 2, and then the ISR for DMA channel 4 and channel 6 will deadlock if that channel is not enabled at that point.

    We also have SPI and the ADC on DMA interrupts 1 and 2, so using interrupt 0 for the UART channels is important.

    If you have an example that uses multiple channels on interrupt 0 that would be helpful.

**Attention** This is a public forum