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.

stucked in dma block transfer through uart tx

Other Parts Discussed in Thread: MSP430WARE, MSP430F5438A

hello,

I m trying to use DMA for my usart tx messages in my project, that's why I tried the basic example in msp430ware.

I changed the example a little bit, I set the DMA trigger to DMAREQ, and I made that request with a button on Msp430f5438A experimenter board.

here is my code below, for  DMA_TRANSFER_REPEATED_SINGLE mode

static char String1[] = { "Hello World\r\n" };
// uart init etc

DMA_init(DMA_CHANNEL_0,
                 DMA_TRANSFER_REPEATED_SINGLE,
                 (sizeof String1 - 1),
                 DMA_TRIGGERSOURCE_0,
                 DMA_SIZE_SRCBYTE_DSTBYTE,
                 DMA_TRIGGER_RISINGEDGE);

DMA_setSrcAddress(DMA_CHANNEL_0,
                          (uint32_t)String1,
                          DMA_DIRECTION_INCREMENT);

DMA_setDstAddress(DMA_CHANNEL_0,
                          USCI_A_UART_getTransmitBufferAddressForDMA(USCI_A1_BASE),
                          DMA_DIRECTION_UNCHANGED);

DMA_enableTransfers(DMA_CHANNEL_0);
        
        DMA_clearInterrupt(DMA_CHANNEL_0);
        DMA_enableInterrupt(DMA_CHANNEL_0);
        
        _BIS_SR(GIE);
        while(1)
        {
            if((P2IN & BIT6) == 0)
            {
                __delay_cycles(100000);
                if((P2IN & BIT6) == 0)
                {
                    DMA_startTransfer(DMA_CHANNEL_0); 
                    __no_operation();
                }
            }
        }
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=DMA_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(DMA_VECTOR)))
#endif
void DMA_ISR(void)
{
    switch (__even_in_range(DMAIV, DMAIV_DMA2IFG)) 
    {
    case DMAIV_NONE: break;
    case DMAIV_DMA0IFG: 
        DMA_enableTransfers(DMA_CHANNEL_0);
        break;
    case DMAIV_DMA1IFG: break;
    case DMAIV_DMA2IFG: break;
    } 
//    __bic_SR_register_on_exit(LPM0_bits);
}

when I run DMA_TRANSFER_REPEATED_SINGLE mode, as I pressed button, it sends a character from string1, then when the string is completely sent, then it enters dma0 irq as I expected.

I d like to send this string with a block transfer, I tried many things but it only sends the first character of that string, when I changed the mode to DMA_TRANSFER_BLOCK or DMA_TRANSFER_REPEATED_BLOCK etc, it sends 'H' and then enters the dma0 irq after sending the  first character.

Why does it happen? What should I do in order to send the whole array with only one trigger?

A small clue will be greatly appreciated.

best regards,

Gloin

 

 

  • Hi Gloin,

    Gloin said:
    Why does it happen?

    As per the manual, single transfer mode means that the DMA requires one trigger per byte/word movement/copy. This matches what you have seen. The block mode means that when one trigger occurs all the bytes/words are moved as fast as the DMA can go. However, the module you are transferring to can't process the data that fast! As with normal operation of the usart module, the usart tells you using the flags when the next byte can be written or read. The DMA must obey this too. Therefore you should keep using the single transfer mode but change the trigger to one the usart ones. I am not familiar with mspware but look for the one which means the usart module is ready for the next byte to send.

    Gloin said:
    A small clue will be greatly appreciated.

    So in summary - use single transfer mode triggered by the usart module. When you get a button press enable the DMA (and set the number of bytes to send). But let the DMA send data to the usart based on the usart flag not the button.

    BTW there is an example of this in the msp430f5438a example code folder: msp430x54xA_dma_02.c

    Hope this helps, 

**Attention** This is a public forum