Skip to main content
Robmar
Senior II
December 7, 2022
Question

To use the ADC data offset registers with ADC1 & 2 should I use Dual injected simultaneous mode?

  • December 7, 2022
  • 9 replies
  • 3748 views

Using ADC1 and ADC2 and timer3 trigger rising and falling edges to get a 96KHz event, I understand that we can't use Dual injected simultaneous mode with DMA, so we are using Independent mode, but is there a better (more efficient and robust) mode?

I searched the web and the 407 Ref manual but can find nothing to clearly explain this clearly.

Aim is to have synchronous 16-bit ADC conversion with DMA on two inputs at 96 - 384KHz (selectable by user) with time accurate sampling as this is for I and Q sampling, which are 90 degrees out of phase.

Appreciate expert guidance on this as I am new to this chip though have worked on complex MCUs for years, but its a lot to go through a 1700 page manual and from community comments many people seem uncertain about injected channels.

Project volume is around 3K units a year.

This topic has been closed for replies.

9 replies

Robmar
RobmarAuthor
Senior II
December 7, 2022

I am also concerned if I have this set-up correctly, I start the ADC-DMA transfers requesting 32 samples, and was told that timer3 trigger would cause incrementing memory DMA transfers each trigger, but without the DMA continuous bit set, this doesn't work.

Could each trigger be launching the entire 32 conversions?

This is the code:

 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.ScanConvMode = DISABLE;
 hadc1.Init.ContinuousConvMode = DISABLE;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
 hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.NbrOfConversion = 1;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;	//ADC_EOC_SINGLE_CONV ADC_EOC_SEQ_CONV;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }

Robmar
RobmarAuthor
Senior II
December 15, 2022

No replies, nothing from STM, I had hoped for support on this.

We have a 2uS delay on the ADC1 and ADC2 completion interrupts, and this is a problem for IQ sampling.

Appreciate if anyone can advise if there is a way to fix this.

Currently ADC1 and 2 are triggered off the same timer.

ST Technical Moderator
December 20, 2022

Hello @Robmar​ 

Would you please precise the product used? F407? 

Have you tried changing dual regular simultaneous mode? So you can use DMA mode 2.

Hope this helps.

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Robmar
RobmarAuthor
Senior II
December 20, 2022

Hi, its a 32F407VG on the Discovery board.

The problem is that there are so many modes, but no clear explanations of how to make two synchronised samples of signal lines at up to 384 KHz.

Currently I am using ADC1 and ADC2 both triggered off timer3, scope shows a 2uS delay on the DMA completion Irqs.

Without knowing the inner design of the chip, and with no example of my case, I need to ask STM which is the best method to capture IQ signals on the 407VG.

I also need to get the sample range as low as possible, I understand that 1.8v is the minimum VREF+ allowed, also need verification as the datasheet has conflicting notes on this issue.

Piranha
Principal III
December 20, 2022

Basically all the starting hints were given in this topic:

https://community.st.com/s/question/0D53W00001yi6jISAQ/adc-sample-rate-impossible-to-set-precisely-calculations-added

Why are you using injected channels?

> ADC1 and ADC2 both triggered off timer3, scope shows a 2uS delay on the DMA completion Irqs

The ISRs do not run simultaneously on a single CPU core!

> its a lot to go through a 1700 page manual

ADC chapter is 45 pages and DMA is 37 pages including the register descriptions. With reading the documentation and programming the registers (not using the HAL/Cube broken bloatware), one can to this in a single day easily.

Edited post by moderation team to adhere to community guidelines.

Robmar
RobmarAuthor
Senior II
December 21, 2022

One thing experience has shown me is that these complex devices are often not fully characterised.

I've worked with STM some years ago to resolve issues with one of their chips as there isn't a single engineer that knows how every part of the chip works.

In this case one problem was that the activity of the IRQs and DMA bus sharing is causing glitches on the transfer of data via IS2 to the DAC. I partially solved this by disabling FIFO on the I2S DMA although there is no technical information as far as I know that explains why that would help.

I also reduced the priority on the ADC IRQs in preference to the IS2, so although the sampling is running at 96 KHz, the 32F407 is unable to guarantee smooth delivery of data, which given the datasheet shouldn't be the case.

So unless you have any useful proven info to put in, no need to reply... if you can resist of course ;)

ST Technical Moderator
December 22, 2022

Hello again @Robmar​,

If you use dual regular simultaneous mode, there is no need of two different completion interrupts for master and slave and this should resolves your issue, while ensuring use of DMA.

Unfortunately, your question was not clear from the beginning. A detailed description of your issue including the steps you have already taken to try to fix is strongly recommended to help you solving your issue.

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Robmar
RobmarAuthor
Senior II
December 23, 2022

Hello and thanks very much for you reply.

I've looked at the MX and see that selecting "Dual combined regular simultaneous + alternate trigger mode" on ADC1 also changes the configuration settings of ADC2, but not ADC3.

DMA access mode 2 is set automatically without other options.

I've set Timer3 event out as the trigger source, triggering on rising and falling edges, which presumably triggers conversion of both ADCs alternately, one after the other with a minimum 5 cycle delay, would that be correct?

I've also set EOC to the end of all conversions, 32 samples in this case, and presume that the same interrupt handler is called with the ADC1 handle, but on the premise that ADC2 samples have also been DMA'd to the specified buffer, would that be correct?

ADC conversion Sampling time is 84 clocks, a few clocks less than the timer period (edge to edge).

Is there anything about this mode that I should be aware of, and special requirements or known issues?

We're due to start production by the end of January so the pressure is on, appreciate your assistance.

Piranha
Principal III
December 24, 2022

You are right that the documentation is often lacking the details, but that is not an excuse to not read it. Unnoticed hardware flaws are possible, but very unlikely, especially as severe ones as a bus sharing problems would be.

> I've also set EOC to the end of all conversions, 32 samples in this case

ADC EOC interrupt triggers at the end of either a single regular conversion or regular group. In your case the length of the regular group is 1 channel, therefore effectively it's the same thing in both cases. But it was already explained in the other topic that EOC or other ADC interrupts has nothing to do with DMA samples. You must just use the DMA TC/HT interrupts for the blocks (for example, 32 or 2*32 samples, probably even larger blocks to reduce the CPU cycle wasting) of data, not the ADC EOC interrupt. Do you enable the ADC EOC interrupt? In that case 168 MHz / 96 kHz / 2 = 875 CPU cycles. With HAL, slow code in callbacks and no compiler optimization (O0) that is the problem, not a hardware.

> selecting "Dual combined regular simultaneous + alternate trigger mode"

> triggers conversion of both ADCs alternately

Alternate trigger mode is for injected channels. It triggers a conversion of injected channels alternately, not the regular ones. You didn't answer why you are using injected channels and you are trying to use them again.

> one after the other with a minimum 5 cycle delay

ADC_CCR_DELAY field is only relevant for interleaved mode.

All of this is completely unnecessary for the requirements you have described. You just need to configure the ADC dual simultaneous regular mode with a trigger on timer TRGO, set the ADC_CCR_DMA field to "DMA mode 2", configure the DMA to read 32-bit words from the ADC_CDR register and use the DMA TC/HT interrupts to start the data processing.

It's pretty clear that all of this confusion comes from clicking CubeMX instead of reading the reference manual. Are the data processing algorithms already developed and tested? If no and the algorithms are not trivial, I don't see how that can be done in a month, especially if a simple data capture is such a huge problem.

Edited by moderation team to adhere to community guidelines

Robmar
RobmarAuthor
Senior II
December 26, 2022

As I have now repeatedly mentioned, I do not agree, and would appreciate if you would refrain from making any further posts. Okay?

ST Technical Moderator
December 26, 2022

Hello @Robmar​, 

If you wonder to find known issues of ADC peripheral on F407, you may refer to this errata sheet, section 2.14 ADC peripheral limitations, where you can find the workaround as well.

You can take a look at this MOOC and explore an interesting mode which is the interleaved mode to perform faster ADC conversions. How to boost ADC conversion rate on STM32L4 - STMicroelectronics

Good reading!

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Robmar
RobmarAuthor
Senior II
December 26, 2022

My experience with STM32CubeIDE is mixed, for example the IDE lacks the simple code to make simple changes to the files to allow users to select alternative MCUs.

There are so many variants to the MCUs that many customers have complained about this over the last many years.

To change one sample project with 50+ files from the F411 to F407 we had to edit the .ioc and project files, replacing the 411 references with the required 407 ones, it was quicker than recreating the entire project, but still a waste of valuable time. This really should have been fixed years ago.

The idea behind Cube MX is to allow clients to focus on their particular application code, not re-read length and occasionally conflicting datasheets. Several people on this forum are trashing Cube MX whereas it generally works well, and can easily be refined in code later.

*** As far as ADC Dual Regular Mode with Alternate trigger, we used Cube MX to generate the code and the IRQs for ADC 1 and 2 are still both being generated, though we can just use the IRQ from ADC 2 and all data samples have arrived to the buffer.

I had understood that only one set of IRQs would be generated with both ADC linked.

Is there something missing from the MX generated code?

/* ADC1 init function */
void MX_ADC1_Init(void)
{
 
 /* USER CODE BEGIN ADC1_Init 0 */
 
 /* USER CODE END ADC1_Init 0 */
 
 /* USER CODE BEGIN ADC1_Init 1 */
 
 /* USER CODE END ADC1_Init 1 */
 
 ADC_ChannelConfTypeDef sConfig = {0};
 ADC_MultiModeTypeDef multimode = {0};
 
 /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
 */
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;	// xyzzy ADC_CLOCK_SYNC_PCLK_DIV4
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.ScanConvMode = DISABLE;
 hadc1.Init.ContinuousConvMode = DISABLE;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING;
 hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.NbrOfConversion = 1;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;	//ADC_EOC_SINGLE_CONV ADC_EOC_SEQ_CONV;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }
 
 
 /** Configure the ADC multi-mode
 */
 multimode.Mode = ADC_DUALMODE_REGSIMULT_ALTERTRIG;
 multimode.DMAAccessMode = ADC_DMAACCESSMODE_2;
 multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
 {
 Error_Handler();
 }
 
 /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
 */
 sConfig.Channel = ADC_CHANNEL_2;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES;	//ADC_SAMPLETIME_84CYCLES ADC_SAMPLETIME_28CYCLES ADC_SAMPLETIME_144CYCLES
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

Edited by moderation team to adhere to community guidelines