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: Multiple DMA-Channels and DMA_INT1 does not work

Part Number: MSP432P401R

Hi,

i'm trying to work with 4 DMA-Channels (2 for EUSCI_B3 and the other two for EUSCI_B2) to talk to 2 different chips using SPI.

I started with the comminucation over EUSCI_B3 to an RTC and using Channels 6 and 7 with DMA_INT0. That works fine.

Now im Trying to activate the channels 4 and 5 for EUSCI_B2 for send and recieve to an external storage. There i want to use the DMA_INT1 at the end of a Transmit to deactivate the CS-Signal after a complete transfer, but the function never gets called. The data gets transferred, but the Chip needs the toggle of CS to work correct.

This is the code-snippet for the initalisation of the DMA and the part of the RTC (EUSCI_B3) which works.

const eUSCI_SPI_MasterConfig spiRTCConfig =
{
    EUSCI_B_SPI_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
    12000000, // SMCLK = DCO
    2000000, // SPICLK = 2MHz
    EUSCI_B_SPI_MSB_FIRST, // MSB First
    EUSCI_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT, // Phase CPHA=0
    EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW, // High polarity CPOL=0
    EUSCI_B_SPI_3PIN   //SPI 3Pin Mode
};

/* DMA Control Table */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN(RTC_SPI_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 RTC_SPI_DMAControlTable[32];

void prvRtcInit(void)
{
    //Alles um die externe RTC zu initialisieren
    //Init des SPI
    /* Selecting P10.1 P10.2 P10.3 in SPI mode */
    MAP_GPIO_setDriveStrengthHigh(GPIO_PORT_P10,GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3);
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P10,GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P10,GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION);
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P10,GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);

    //CS Für die RTC
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P10,GPIO_PIN0);
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P10,GPIO_PIN0);

    //Int-Input für die RTC
    MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P4, GPIO_PIN0);
    MAP_GPIO_setDriveStrengthHigh(GPIO_PORT_P4, GPIO_PIN0);
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN0);

    MAP_GPIO_interruptEdgeSelect(GPIO_PORT_P4, GPIO_PIN0,GPIO_HIGH_TO_LOW_TRANSITION);
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P4, GPIO_PIN0);
    MAP_GPIO_registerInterrupt(GPIO_PORT_P4,RTC_C_ISR);
    MAP_GPIO_enableInterrupt( GPIO_PORT_P4, GPIO_PIN0);


    MAP_SPI_initMaster(EUSCI_B3_BASE, &spiRTCConfig);

    MAP_SPI_enableModule(EUSCI_B3_BASE);

    //DMA-Versuch
    /* Configuring DMA module */

    MAP_DMA_enableModule();
    MAP_DMA_setControlBase(RTC_SPI_DMAControlTable);

    /* Assign DMA channel 6 to EUSCI_B3_TX0, channel 7 to EUSCI_B3_RX0 */
    MAP_DMA_assignChannel(DMA_CH6_EUSCIB3TX0);
    MAP_DMA_assignChannel(DMA_CH7_EUSCIB3RX0);

    /* Setup the TX transfer characteristics & buffers */

    MAP_DMA_setChannelControl(DMA_CH6_EUSCIB3TX0 | UDMA_PRI_SELECT,
                              UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    MAP_DMA_setChannelControl(DMA_CH7_EUSCIB3RX0 | UDMA_PRI_SELECT,
                              UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1);

    /* Enable DMA interrupt */

    MAP_DMA_clearInterruptFlag(DMA_CH6_EUSCIB3TX0 & 0x0F);

    MAP_DMA_clearInterruptFlag(DMA_CH7_EUSCIB3RX0 & 0x0F);

    /* Assigning/Enabling Interrupts */
    MAP_Interrupt_enableInterrupt(INT_DMA_INT0);

    MAP_DMA_enableInterrupt(INT_DMA_INT0);
    
    /* Start of Init RTC*/

This is the code-snippet for the storage-device

const eUSCI_SPI_MasterConfig spiSpeicherConfig =
{
    EUSCI_B_SPI_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
    12000000, // SMCLK = DCO
    6000000, // SPICLK = 6Mhz
    EUSCI_B_SPI_MSB_FIRST, // MSB First
    EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT, // Phase CPHA=1
    EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH, // High polarity CPOL=1
    EUSCI_B_SPI_3PIN   //SPI 3Pin Mode
};

void prv_SpeicherInit (void)
{
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P3,GPIO_PIN4); //CS Pin  manuell steuern
    ResetCS(); //Macro
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3,GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION);
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3,GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION);
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3,GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

    MAP_SPI_initMaster(EUSCI_B2_BASE, &spiSpeicherConfig);

    MAP_SPI_enableModule(EUSCI_B2_BASE);

    /* Assign DMA channel 4 to EUSCI_B2_TX0, channel 5 to EUSCI_B2_RX0 */
   MAP_DMA_assignChannel(DMA_CH4_EUSCIB2TX0);
   MAP_DMA_assignChannel(DMA_CH5_EUSCIB2RX0);

   /* Setup the TX transfer characteristics & buffers */

   MAP_DMA_setChannelControl(DMA_CH4_EUSCIB2TX0 | UDMA_PRI_SELECT,
                             UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
   MAP_DMA_setChannelControl(DMA_CH5_EUSCIB2RX0 | UDMA_PRI_SELECT,
                             UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1);

   /* Enable DMA interrupt */
   MAP_DMA_assignInterrupt(DMA_INT1,4);
   MAP_DMA_clearInterruptFlag(4);
   MAP_DMA_assignInterrupt(DMA_INT1,5);
   MAP_DMA_clearInterruptFlag(5);

   DMA_registerInterrupt(DMA_INT1,DMA_INT1_IRQHandler);

   /* Assigning/Enabling Interrupts */
   Interrupt_enableInterrupt(DMA_INT1);
   
   /*Start of Transfer*/
   ...
   }
   
   void DMA_INT1_IRQHandler(void)
{
    //Get Status
    uint32_t DMA_Int_Status=MAP_DMA_getInterruptStatus();
    //BaseType_t xHigherPriorityTaskWoken=pdFALSE;

    if (DMA_Int_Status && (DMA_CH4_EUSCIB2TX0 & 0x0F))
    {
        //Daten gesendet
        MAP_DMA_clearInterruptFlag(DMA_CH4_EUSCIB2TX0 & 0x0F);
        ResetCS();

    }
    if (DMA_Int_Status && (DMA_CH5_EUSCIB2RX0 & 0x0F))
    {
        //was anderes tun, da Datenempfang fertig
        if(!DMA_isChannelEnabled(5) && (SPI_isBusy(EUSCI_B2_BASE)==EUSCI_SPI_NOT_BUSY) )
        {
            MAP_DMA_clearInterruptFlag(DMA_CH5_EUSCIB2RX0 & 0x0F);
            ResetCS();
        }
    }
    else
    {
        MAP_DMA_clearInterruptFlag(DMA_Int_Status & !(DMA_CHANNEL_4|DMA_CHANNEL_5));
    }

}

In the startup_msp432p401r_ccs.c i also added the ISR in place of defaultISR in the interruptVectors. This changed nothing.

Hopefully  someone can help me.

  • How do you tell that the ISR isn't called? A breakpoint? or some external observation?

    -------------

    > MAP_DMA_assignInterrupt(DMA_INT1,4);
    ...
    > MAP_DMA_assignInterrupt(DMA_INT1,5);

    You can only assign one channel to a (DMA_INT1/2/3) interrupt register [Ref TRM (SLAU356I) Table 11-18]. This sequence may still work by accident, since channel 5 (RX) is really what you're interested in.

    -------------

    >  if (DMA_Int_Status && (DMA_CH4_EUSCIB2TX0 & 0x0F))

    This condition doesn't check what you want, but in any case there's no reason to check anything here -- the fact that you got here says that there is status from channel 5 [Ref TRM Sec 11.2.6.1]

  • Thank you Bruce.

    Your post solved my issues. When i assign one Int-source, it works as expected.