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.

MSP432P401R: MSP432 UART TX DMA

Part Number: MSP432P401R

I have the UART working with RX and TX using interrupts.  I need to change the UART to work with DMA.  I tried following examples I found from other posts but have been unable to get anything working.

/* 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[32];


void configDMA_DICE_UART(void){
    MAP_DMA_enableModule();
    MAP_DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable);
    MAP_DMA_assignChannel(DMA_CH4_EUSCIA2TX); //Assign DMA channel 4 to EUSCI_A2_TX
    MAP_DMA_disableChannelAttribute(DMA_CH4_EUSCIA2TX,UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
    MAP_DMA_setChannelControl(DMA_CH4_EUSCIA2TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    EUSCI_A0_BASE
    MAP_DMA_assignInterrupt(DMA_INT1, 4);
    MAP_DMA_clearInterruptFlag(4);
}
__attribute__((interrupt))
void DMA_INT1_IRQHandler(void){
    uint32_t ui32Mode;

    ui32Mode=MAP_DMA_getChannelMode(DMA_CH4_EUSCIA2TX | UDMA_PRI_SELECT);
    if(ui32Mode==UDMA_MODE_STOP)
    {
        dice_tx_busy=0;
        EUSCI_A2->IFG &= ~EUSCI_A_IFG_TXIFG;
    }
    MAP_DMA_clearInterruptFlag(4);
    MAP_DMA_disableInterrupt(DMA_INT1);
}
__attribute__((interrupt))
void DMA_ERR_IRQHandler(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();

    }
}


void EUSCIA2_IRQHandler(void)
{
    volatile uint8_t temp;
    if (EUSCI_A2->IFG & EUSCI_A_IFG_RXIFG)
    {
        dice_rx[dice_rx_wri] = EUSCI_A2->RXBUF;
        if(++dice_rx_wri >= dice_rx_size)
        {

            dice_rx_wri=0;

        }
        dice_rx_cnt++;

    }

    // if (EUSCI_A2->IFG & EUSCI_A_IFG_TXIFG)
    // {
    //     // Check DICE transmit queue
    //     if(!(dice_tx_mt()))
    //     {
    //         EUSCI_A2->TXBUF=dice_tx_deq();
    //     } 
    //     else 
    //     {
    //         // Nothing to transmit, disable transmit interrupt
    //         dice_tx_busy=0;
    //         EUSCI_A2->IFG &= ~EUSCI_A_IFG_TXIFG;
    //     }
    // }
}

// Here is where I try to give data to DMA
uint32_t *DICE_TX;
DICE_TX = (uint32_t *)&EUSCI_A2->TXBUF;


 //Pop packet from Priority Buffer to DICE TX Buffer
void Priority_pop(PacketType Packet){
    int i;
    switch(Packet){
        case HS_DATA:
            MAP_DMA_setChannelTransfer(DMA_CH4_EUSCIA2TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC,PRIORITY_BUF.HS_DATA_BUF.buffer[PRIORITY_BUF.HS_DATA_BUF.TAIL].all_8,
                    (void*)DICE_TX,HS_DATA_SIZE);
            //for(i=0;i<HS_DATA_SIZE;i++)
            //{
            //    dice_tx_enq(PRIORITY_BUF.HS_DATA_BUF.buffer[PRIORITY_BUF.HS_DATA_BUF.TAIL].all_8[i]);
            //}
            PRIORITY_BUF.HS_DATA_BUF.TAIL=(PRIORITY_BUF.HS_DATA_BUF.TAIL+1)%hsdata_buff_size;
            PRIORITY_BUF.HS_DATA_BUF.packet_count--;
            MAP_DMA_enableChannel(4);
            MAP_Interrupt_enableInterrupt(DMA_INT1);
            EUSCI_A2->IFG |= EUSCI_A_IFG_TXIFG;
            break;
            // Only using this case right now for testing
                  }
}

  • Hello,

    tiptonite92 said:
    I tried following examples I found from other posts but have been unable to get anything working

    That's a good start. Could you be more specific about what's not working? Is there any behavior that indicates something specific? For example, does the DMA interrupt trigger?

    Regards,

    James

  • The UART interrupt triggers for the RX. The DMA interrupt does not trigger and neither does the DMA error handler.

  • Try changing DICE_TX to be a (uint8_t *). The compiler is entitled to ensure that a (uint32_t *) is 32-bit aligned, but TXBUF (offset 0x0E) isn't. [Ref TRM (SLAU356I) Table 24-7]

  • Changing DICE_TX to be a (uint8_t*) didn't change the behavior that I could see.  I tried manually triggering the channel (DMA_Channel->SW_CHTRIG |= DMA_SW_CHTRIG_CH4) ;.  This causes the UCTXIFG to set, as well as the DMA_ENASET and EMA_ENACLR for channel 4. However, the DMA interrupt and error handler still do not trigger.

  • Was able to get the DMA working from this post.  From using the Interrupts before, I was manually clearing the TXIFG. Removing this and disabling the TX interrupt got the DMA working.

    e2e.ti.com/.../870953

**Attention** This is a public forum