STM32F4 multi ADC mode

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
User avatar
piers
Posts: 42
Joined: Fri Apr 06, 2012 1:02 am
Location: Netherlands
Been thanked: 15 times
Contact:

STM32F4 multi ADC mode

Postby piers » Thu Jan 29, 2015 5:07 pm

Since there is no multi ADC mode support for STM32F4 in ChibiOS I've been doing a test to see if I could get triple adc mode to work.
I hacked together some replacements for adcStart and adcStartConversion that use triple adc mode. This generally works, but there is something strange with the DMA stream, as the result from ADC3 is streamed twice every cycle.

The following shows the buffer directly printed to serial, and instead of ADC1[0], ADC2[0], ADC3[0], ADC1[1], ADC2[1], ... it shows ADC1[0], ADC2[0], ADC3[0], ADC3[1], ADC1[1], ADC2[1], ADC3[1], ...

Code: Select all

4095,    0, 1006, 1030, 4095,    0, 1030,  996, 4095,    2,  996, 1009,
4095,   10, 1005, 1020, 4095,    0, 1020, 1040, 4095,    0, 1040,  997,
4095,    0, 1005, 1024, 4095,    2, 1024,  976, 4095,    0,  976,  982,
4095,    1,  982,  997, 4095,    0,  997, 1010, 4095,    1,  979, 1025,
4095,    0,  985,  993, 4095,    6,  993,  995, 4095,    1,  995, 1007,


I use Triple ADC regular simultaneous mode, and DMA mode 1, which should give three half word dma requests, but instead seems to give four dma requests.

Anyone has an idea what could be happening?

The full code can be found at https://github.com/pierstitus/chibios-d ... i_adc_mode
I use three adc group configs and modified adcMultiStart() and adcMultiStartConversion() functions.

Thanks, Piers

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32F4 multi ADC mode

Postby Giovanni » Thu Jan 29, 2015 6:19 pm

Hi,

Are you reading the data register ADC_CDR using 16 or 32 bits accesses? using 32 bits accesses you get the value of each ADC twice every 3 DMA cycles. I never used this mode, I am reading the RM.

About the DOUBLE mode, there is an implementation for the STM32F3 ADC that should be adaptable to the F4.

Giovanni

User avatar
piers
Posts: 42
Joined: Fri Apr 06, 2012 1:02 am
Location: Netherlands
Been thanked: 15 times
Contact:

Re: STM32F4 multi ADC mode

Postby piers » Thu Jan 29, 2015 6:31 pm

I'm using the 16 bit (half word) mode. I might try to use the 32 bit mode, but that needs changing the ChibiOS code and some thinking about how it will be handled.
And still the 16 bit mode should work too. Probably I'll just make a workaround to ignore the double value.

I looked at the double mode from the F3, but it seemed quite different to me than the F4 adc driver.
Are there plans for implementing a multi adc mode for the stm32f4?

Thanks, Piers

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32F4 multi ADC mode

Postby Giovanni » Thu Jan 29, 2015 6:40 pm

Not immediate plans but it would be done along the lines of the F3 driver.

Giovanni

User avatar
piers
Posts: 42
Joined: Fri Apr 06, 2012 1:02 am
Location: Netherlands
Been thanked: 15 times
Contact:

Re: STM32F4 multi ADC mode

Postby piers » Fri Jan 30, 2015 4:11 pm

Hi Giovanni,
I've solved the issue with a change that's probably good to put in the main release of ChibiOS too.
By setting the SWSTART bit in the ADC_CR2 register in a separate write all the issues with spurious DMA transfers in various cases are gone.

In os/hal/platforms/STM32F4xx/adc_lld.c at line 347 I replaced

Code: Select all

  /* ADC configuration and start, the start is performed using the method
     specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/
  adcp->adc->CR1   = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN;
  if ((grpp->cr2 & ADC_CR2_SWSTART) != 0)
    adcp->adc->CR2 = grpp->cr2 | ADC_CR2_CONT  | ADC_CR2_DMA |
                                 ADC_CR2_DDS   | ADC_CR2_ADON;
  else
    adcp->adc->CR2 = grpp->cr2 |                 ADC_CR2_DMA |
                                 ADC_CR2_DDS   | ADC_CR2_ADON;

with

Code: Select all

  /* ADC configuration and start, the start is performed using the method
     specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/
  if ((grpp->cr2 & ADC_CR2_SWSTART) != 0) {
    adcp->adc->CR2 = (grpp->cr2 & !ADC_CR2_SWSTART) | ADC_CR2_ADON | ADC_CR2_CONT;
    // Setting SWSTART in a separate write prevents spurious DMA requests
    adcp->adc->CR2 |= ADC_CR2_SWSTART;
  }
  else {
    adcp->adc->CR2 = grpp->cr2 | ADC_CR2_ADON;
  }


I hope that's a useful addition,
Piers

User avatar
piers
Posts: 42
Joined: Fri Apr 06, 2012 1:02 am
Location: Netherlands
Been thanked: 15 times
Contact:

Re: STM32F4 multi ADC mode

Postby piers » Sat Jan 31, 2015 4:31 pm

Sorry, that last one was without DMA, for multi ADC mode, for normal ADC it should be:

Code: Select all

  /* ADC configuration and start, the start is performed using the method
     specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/
  adcp->adc->CR1   = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN;
  if ((grpp->cr2 & ADC_CR2_SWSTART) != 0) {
    adcp->adc->CR2 = (grpp->cr2 & !ADC_CR2_SWSTART) | ADC_CR2_CONT  | ADC_CR2_DMA |
                                 ADC_CR2_DDS   | ADC_CR2_ADON;
    // Setting SWSTART in a separate write prevents spurious DMA requests
    adcp->adc->CR2 |= ADC_CR2_SWSTART;
  }
  else
    adcp->adc->CR2 = grpp->cr2 |                 ADC_CR2_DMA |
                                 ADC_CR2_DDS   | ADC_CR2_ADON;

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32F4 multi ADC mode

Postby Giovanni » Sun Feb 01, 2015 10:31 pm

Hi,

Thanks, I will merge your change soon.

Giovanni

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32F4 multi ADC mode

Postby Giovanni » Tue Feb 10, 2015 4:00 pm

Hi,

I committed a slightly different change. In your code that ! should be a ~.

Giovanni

User avatar
piers
Posts: 42
Joined: Fri Apr 06, 2012 1:02 am
Location: Netherlands
Been thanked: 15 times
Contact:

Re: STM32F4 multi ADC mode

Postby piers » Thu Feb 12, 2015 11:21 pm

Oops, stupid mistake, thanks for noticing.

Piers

pito
Posts: 199
Joined: Sun Nov 06, 2011 3:54 pm

Re: STM32F4 multi ADC mode

Postby pito » Thu Mar 12, 2015 1:50 pm

Hi Piers,
it is my current understanding the sampling period in your driver is set 480+12 ADC clocks (ADC's clock probably 84MHz/8).
Is it there a way one can set the sampling period with a timer_x? (ie. 10.000kHz).
Btw

Code: Select all

#define ADC_GRP1_BUF_DEPTH      (1*ADC_N_ADCS) // must be 1 or even

crashes.
PS: I can do it with 15+12 ADC clocks (about 1MHz sampling) and a 10kHz gpt callback, ie. (a 4 triple samples deep buffer)

Code: Select all

/* GPT2 callback. */
static void gpt2cb(GPTDriver *gptp) {
  (void)gptp;
  chSysLockFromIsr();
  chMBPostI(&mb[0], (msg_t)samples[0])+(msg_t)samples[3])+(msg_t)samples[6])+(msg_t)samples[9]) ;
  chMBPostI(&mb[0], (msg_t)samples[1])+(msg_t)samples[4])+(msg_t)samples[7])+(msg_t)samples[10]) ;
  chMBPostI(&mb[0], (msg_t)samples[2])+(msg_t)samples[5])+(msg_t)samples[8])+(msg_t)samples[11]) ;
  chSysUnlockFromIsr();
}

and then mb[]/4 values (averaging), but not sure it is equivalent to an exact sampling (because of the phase).
P.


Return to “Development and Feedback”

Who is online

Users browsing this forum: No registered users and 17 guests