cancel
Showing results for 
Search instead for 
Did you mean: 

How to send data from ADC diretly to FMAC using DMA (peripheral-to-peripheral)?

Helder Sales
Associate II

Hi,

I'm trying to send data from ADC to FMAC directly via DMA in circular mode. From the STM32G4 reference manual (dm00355726) page 402:

"Peripheral-to-memory, memory-to-peripheral, memory-to-memory and peripheral-to-peripheral data transfers"

But I can't find anything on STM32CubeG4 that configures that. Here's a screenshot:

0693W000006EshuQAC.png 

I've tried writing to FMAC write data register directly using

HAL_ADC_Start_DMA(&hadc1, &FMAC->WDATA, 1)

But it doesn't work.

What worked for me was setting the DMA circular mode for both ADC and FMAC, then syncronize it using DMAMUX requests. Although this eliminates the CPU in the process, it doesn't feel like a true peripheral-to-peripheral transaction.

How can I make a DMA transfer content from one peripheral to another, directly?

Kind regards,

Helder

19 REPLIES 19

I've tested with UART, and it works!

Configured ADC in 8 bit mode and slow output rate, USART2 without interrupt or DMA, and then

HAL_ADC_Start_DMA(&hadc1, &USART2->TDR, 1);

The serial comm printed the ASCII equivalent of whatever the ADC was reading (I've tested varying a DC signal on the ADC input).

So, the problem most probably is with the FMAC peripheral, because when I try to put anything into the WDATA register, it gives me a transfer error. And I can't see anything wrong, the SR just tell me that the output buffer is empty (Y_EMPTY is 1) and the rest is 0.

From the ref manual:

Three methods are supported:

• Polling: No DMA request or Interrupt request is generated. Software must check that

the X1_FULL flag is low before writing to WDATA, or that the Y_EMPTY flag is low

before reading from RDATA.

• Interrupt: The interrupt request is asserted while the X1_FULL flag is low, for writes, or

when the Y_EMPTY flag is low, for reads.

• DMA: DMA requests are asserted on the DMA write channel while the X1_FULL flag is

low, and on the read channel while the Y_EMPTY flag is low.

I know that the X1_FULL is low, but still gives a transfer error. I starting to believe that the way I did with DMAMUX is probably the best way possible.

Helder Sales
Associate II

Ok, now I've got everything working now. The Half Word data width in ADC DMA configuration was the problem. Once I set up as Word, everything started to work.

0693W000006F4M5QAK.png 

Not sure why this gave me problems, the UART did work just fine with the ADC as Half Word (actually I thought it should be byte). The FMAC on the other hand, refuses everything except Word.

RM0440 Rev 5 does not say what width of accesses is allowed, presumably only word.

@Imen DAHMEN​ , can you please have a look at this? Can you please verify this, and chalk up for correction?

Thanks.

Jan

@Vincent Onde​  #STM32G4 #Documentation

Hello @Community member​ ,

Thanks for pointing this out to me.

I reported your feedback internally for cheking and update.

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
victagayun
Senior III

Hi,

I am using LL DMA for ADC as shown:

/* Select ADC as DMA transfer request */
	  LL_DMA_SetPeriphRequest(DMA1,
	                          LL_DMA_CHANNEL_6,
	                          LL_DMAMUX_REQ_ADC5);
 
	  /* Set DMA transfer addresses of source and destination */
	  LL_DMA_ConfigAddresses(DMA1,
	                         LL_DMA_CHANNEL_6,
	                         LL_ADC_DMA_GetRegAddr(ADC5, LL_ADC_DMA_REG_REGULAR_DATA),
	                         (uint32_t)&VoutMeasured,
	                         LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
 
	  /* Set DMA transfer size */
	  LL_DMA_SetDataLength(DMA1,
	                       LL_DMA_CHANNEL_6,
	                       1); // only1

If I use FMAC, it will be like the one shown below?

LL_DMA_ConfigAddresses(DMA1,
	                         LL_DMA_CHANNEL_6,
	                         LL_ADC_DMA_GetRegAddr(ADC5, LL_ADC_DMA_REG_REGULAR_DATA),
	                         &FMAC->WDATA,
	                         LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

like:

(uint32_t)&VoutMeasured    to    &FMAC->WDATA,

How to use a variable to check on the ADC value for inspection and display to like CubeMonitor?

Igor Cesko
ST Employee

The APB peripherals registers are accessible through Word access (32-bit). If there is 16-bit or 8-bit access then this access is transferred into 32-bit access. As written in RM0440 (Chapter 2.1.5 Bus Matrix):

Note: When a 16- or 8-bit access is performed on an APB register, the access is transformed into a 32-bit access: the bridge duplicates the 16- or 8-bit data to feed the 32-bit vector.

This is probably reason why the USART worked also with half-word access (USART1 is on APB2 bus).

The AHB peripherals register access is defined for each peripheral in registers description (RCC, Flash interface registers, CRC, DMA, DMAMUX, CORDIC, DAC, RNG, GPIO). For the FMAC (which is also on AHB bus) is there no definition written in RM0440. I think that access is usually 32-bit only (if nothing else is written in RM0440).

We will try to improve this description in future documentation.

Regards

Igor

Recently I noticed that the Reference Manual (RM0440) has been updated. Section 18.4.7 states:

FMAC write data register (FMAC_WDATA)

Address offset: 0x18

Reset value: 0x0000 0000

Access: word and half-word access

But the FMAC does not function properly when you use DMA with half-word destination (or even using a pointer to write directly in code). I think either the documentation is wrong, or I'm missing something to make the DMA transfer a half-word (or writing via pointer) into that WDATA register.

Igor Cesko
ST Employee

You are right - those register can be accesses only by 32-bit. This is mistake in RM0440 (for WDATA and RDATA registers). All FMAC registers should have only word access. We will modify description of WDATA and RDATA FMAC register: "Access: word access".

I have tested the behavior (DMA and direct CPU write to WDATA register) and tests confirmed that 16-bit access is not working (only 32-bit access is correct).

Regards

Igor

Hi @Igor Cesko​ 

Thanks for confirming it and marking for correction.

Hello  Helder,

Could you please share how you have configured the ADC DMA (using DMUX to) -> DMA (Write) -> FMAC -> DMA (Read) module? I also wanted to send the ADC DMA data to FMAC module in circular mode. I have tried by configuring  Preload and write only for Normal mode by referring the sample code but not able to configure through ADC DMA to DMA Write to FMAC. 

Any help is really appreciated.

Thanks in advance.