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.

ADC14 with µDMA on MSP432

Hello!

I'm trying to get the ADC14 with the dma running on the MSP432 Launchpad. I want to sample all 24 channels and shift the data via dma to a result array, after completing one sample cycle. I am working with the driver lib and know how to do it with an ADC14 interrupt, but since I want to unburden the cpu I want to use the dma.

And here I get a bit mixed up. I can select the adc14 as a peripheral trigger for the dma, but i don't find any information on how to use this. Sure I can initiate the controls and even the transfer configuration but when is a dma request fired? when there is one conversion? two? all 23? And how do i get access to the MEM0-23 buffers via dma api's because I have to select them as a source address for the dma. Do i have to increment with 16 byte?
So a lot of questions I would love to get a answer :)

Thanks and best regards,

Benni

  • Ok, so I found out, that the ADC14 triggers the DMA depended on the mode used (single or sequence conversion). But I still don't know how I should configure the dma Channel: shall I use the address of the first memory buffer ADC14MEM0 as the source address and then with 16 Bit increment? But that wouldn't work, i think, because the registers are 32bit long, so i wouldn't jump to the next conversion result...

    still in need for some help :(
  • Benjamin,

    I'm looking into this problem for you and will get back to you as soon as I can.

    Regards,
    Michael Arriete
  • Benni,

    If you refer to the Driver Lib examples found in the following document, as well as, in the provided CCS examples, you can find a well detailed sample code setting up the DMA to interface with the I2C buffer. This should give you some idea of how to use the correct pointers for your source address and your destination address.

    dev.ti.com/.../

    I also want to refer you to the following limitation found in the errata for the MSP432, when using both DMA and ADC, under ADC53, stating that the DMA request in repeat sequence of channel does not get asserted by the ADC12 module:
    www.ti.com/.../slaz610c.pdf

    Hope this gives some guidance into your setup!

    Regards,
    Michael Arriete
  • Hello Michael,

    I am farmiliar with the I2C loopback example, but that is only a good approach for using al eUSCI interfaces, because there are some special APIs for receive and transmit buffer address provided. But with the ADC14 it's different.

    But as far as I understood the ADC14 right, all samples are buffered in the ADC14MEM0 ->x buffer registers. So when I use the 24 analog Inputs in a mutlichannel (not repeat) set up, the dma is triggered, after sampling the last channel and writing the result to ADC14MEM23. So then i have to set up a transfer starting at the address of ADC14MEM0, then incrementing 32bit after each transfer until ADCMEM23. Am I right?

    But what i still don't get is, when I check the define of ADC14MEM0 --> x it starts at address 0x40012098 and register ADC14MEM1 is at 0x4001209C but thats only 4-Bit!!...I don't get this. I thought there had to be at least 14-bit for each buffer. So I am mixed up again on how to set up the correct address and address incrementation.

    best regards, and of course thanks for your efforts!

    Benni

  • Benni,

    As far as memory addressing in this case goes, each single address is pointing to an 8-bit register in memory. Four 8-bit registers add up to a 32-bit value. Hope this clears things up!

    Sincerely,
    Michael Arriete
  • ah ok! perfect thanks! Has this something to do with the bit banding feature?
  • Benni,

    I believe this is just the standard of addressing with memory. Below, I have attached a wiki link that describes these methods in much more detail. Specifically in Section 2 Unit of Address Resolution. Feel free to go through it if you think it could help clear up any more confusion you might have on the subject.

    en.wikipedia.org/.../Memory_address

    Sincerely,
    Michael Arriete
  • Thanks for the link, Michael.

    I think that'll help me understanding that relation in more detail.

    As soon as my routines work, I will give a final post here, if everything worked well.
    Thanks again, for your help and efforts!

    best regards

    Benni

  • Benni,

    I hope everything goes well! And it's my pleasure to help you out to the best of my efforts!

    Sincerely,
    Michael Arriete
  • Benni,

    Checking in to see if your issue has been solved! Let us know!

    Sincerely,
    Michael Arriete
  • Hey Michael,

    this will still take a few weeks because the project I am working on is not so simple: I am measuring 24 acceleration signals via the ADC14 (thats what my question was about). The sampling takes place every 2ms initiated with the timer module of the MSP432. All samples will be buffered in an array of 8*1024 in size and sent over SPI to the ALFAT2 SD/USB-interface from GHI electronics. So apart from creating the routines for the msp432 I need to implement the ALFAT2 command routines which are not that easily implemented...at least for me ;). Currently I am working on a second DMA channel which has to send the buffer array over SPI to ALFAT2. Unfortunetely the µDMA of the MSP432 only supprots 1024 transfers per dma cycle so i have to either split everything up in 8 packets or try a different approach.
    As far as i have thought about the problematic so far, i think I will try to splitt the transfer up into 8 packets, so that i set up a DMA channel being triggered by software and sending 1024 bytes to the transmit buffer adsress of the used SPI interface. After completing the first transfer i wil make a new channelTransfer set up starting at location 1025 of the buffer array and sending the next 1024 bytes and so on...until all 8*1024 bytes are sent. The ALFAT" can handle 8*1024 byte packets without interruption so it would be of course nice to send al 8192 bytes in one piece...i am not quite sure but as far as i have understood the µDMA right, the scatter and gather mode would suite perfectly for that. But is also quite difficult in setting it up.
    Mhhh....as i write this post, i think i will look into it again..maybee this is a better approach.

    what do you think?

    best regards

    Benni
  • Hi Michael,

    I am set up fpr the test but sadly it doesn't work :( . I think I have a problem with the right MEM0 address for the dma transfer. I will show you my initialization for the ADC14 which is triggered by a TimerA0_CC1 to sample every 2ms. This works fine and also the ADC14 triggers the dma at the end of the complete 24 channel conversion. Even this works. But i don't get the results from the dma transfer stored in my buffer, so there is something wrong with the ChannelTransferControl or/and the setup.

    Here's my dma init:

    bool dma_init()
    {
    	/* Configuring DMA module */
    	MAP_DMA_enableModule();
    	MAP_DMA_setControlBase(controlTable);
    
    	/* assigning channels for dma */
    	MAP_DMA_assignChannel(DMA_CH2_EUSCIB3TX2);		// ALFAT2<--MSP43
    	MAP_DMA_assignChannel(DMA_CH7_ADC12C);			// ADC14
    
    	/* Disabling channel attributes */
    	MAP_DMA_disableChannelAttribute(DMA_CH2_EUSCIB3TX2,
    	UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    	UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
    
    	MAP_DMA_disableChannelAttribute(DMA_CH7_ADC12C,
    	UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    	UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
    
    	/* setting ADC14 dma channel as high priority */
    	MAP_DMA_enableChannelAttribute(DMA_CH7_ADC12C,UDMA_ATTR_HIGH_PRIORITY);
    
    	/* Setting Control Indexes */
    	MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH2_EUSCIB3TX2,
    	UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
    
    	MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
    	UDMA_SIZE_16 | UDMA_SRC_INC_32 | UDMA_DST_INC_16 | UDMA_ARB_1);	// size correct?
    
    	/* seting up the channel transfer parameters */
    	MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH2_EUSCIB3TX2,
    	UDMA_MODE_BASIC, (void*)SPI_DATA_TX_FAST_BUFFER[0],
    	(void*) MAP_I2C_getTransmitBufferAddressForDMA(EUSCI_B3_MODULE), DATA_TX_FAST_BUFFER_SIZE);
    
    	MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
    	UDMA_MODE_AUTO, (void*) ADC14MEM0,
    	(void*)ADC_resultsBuffer[0], 24);
    
        /* Assigning/Enabling Interrupts */
        MAP_DMA_assignInterrupt(DMA_INT1, 7);
    
        return true;
    }

    and this is my adc14 init:

    bool adc14_init(void)
    {
    
    	 /* Setting reference voltage to 2.5  and enabling reference */
    	    MAP_REF_A_setReferenceVoltage(REF_A_VREF2_5V);
    	    MAP_REF_A_enableReferenceVoltage();
    
    	    /* Initializing ADC (MCLK/1/1) */
    	    MAP_ADC14_enableModule();
    	    MAP_ADC14_initModule(ADC_CLOCKSOURCE_SMCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1,
    	            0);
    
    	    /* Configuring GPIOs for Analog In --> all 24 channels! */
    	    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,
    	            GPIO_PIN5 | GPIO_PIN4 | GPIO_PIN3 | GPIO_PIN2 | GPIO_PIN1
    	                    | GPIO_PIN0, GPIO_TERTIARY_MODULE_FUNCTION);
    	    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4,
    	            GPIO_PIN7 | GPIO_PIN6 | GPIO_PIN5 | GPIO_PIN4 | GPIO_PIN3
    				| GPIO_PIN2 | GPIO_PIN1 | GPIO_PIN0, GPIO_TERTIARY_MODULE_FUNCTION);
    	    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,
    	    		GPIO_PIN1 | GPIO_PIN0, GPIO_TERTIARY_MODULE_FUNCTION);
    	    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P9,
    	    	    		GPIO_PIN1 | GPIO_PIN0, GPIO_TERTIARY_MODULE_FUNCTION);
    	    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P8,
    	    	            GPIO_PIN7 | GPIO_PIN6 | GPIO_PIN5 | GPIO_PIN4 | GPIO_PIN3
    	    				| GPIO_PIN2, GPIO_TERTIARY_MODULE_FUNCTION);
    
    
    	    /* Configuring ADC Memory (ADC_MEM0 - ADC_MEM7 (A0 - A7)  with no repeat)
    	     * with internal 2.5v reference */
    	    MAP_ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM23, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM0,
    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	            ADC_INPUT_A0, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM1,
    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	            ADC_INPUT_A1, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM2,
    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	            ADC_INPUT_A2, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM3,
    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	            ADC_INPUT_A3, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM4,
    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	            ADC_INPUT_A4, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM5,
    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	            ADC_INPUT_A5, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM6,
    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	            ADC_INPUT_A6, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM7,
    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	            ADC_INPUT_A7, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM8,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A8, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM9,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A9, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM10,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A10, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM11,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A11, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM12,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A12, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM13,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A13, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM14,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A14, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM15,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A15, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM16,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A16, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM17,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A17, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM18,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A18, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM19,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A19, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM20,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A20, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM21,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A21, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM22,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A22, false);
    	    MAP_ADC14_configureConversionMemory(ADC_MEM23,
    	    	            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
    	    	            ADC_INPUT_A23, false);
    
    	    /* seting TA0_CC1 as trigger */
    	    MAP_ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1,false);
    
    	    /* Enabling the interrupt when a conversion on channel 23 (end of sequence)
    	     *  is complete to start the dma */
    	    MAP_ADC14_enableInterrupt(ADC_TOV_INT);
    
    	    /* Setting up the sample timer to automatically step through the sequence
    	     * convert.
    	     */
    	    MAP_ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);
    
    	    /* enableing the ADC14 */
    	    MAP_ADC14_enableConversion();
    
    
    	    return true;
    }

    Maybe you see my fault right away..

    best regards!

  • If i use a 32-bit ADC_resultsBuffer everything works fine. So i will make the type conversion later...

**Attention** This is a public forum