cancel
Showing results for 
Search instead for 
Did you mean: 

DMA / UCPD sending the wrong data

Carl_G
Senior II

Hi, I have a strange situation I can't figure out. I'm new at DMA so I just follow directions as  best I can without a full understanding. Right now, my setup is more or less working for a few months. But today I encountered a problem. I am using UCPD with DMA. Somehow UCPD starts sending data that is equivalent to all 0s. Basically, the data being sent to UCPD by the DMA is all 0s. UCPD encodes this and sends it out over the data channel. Its the correct number of bytes. Also, the preamble and header which are made by UCPD are both correct. I've checked with a scope to verify what is going out. And I've checked with a debugger to verify what is going into the DMA.

Can you think of any reason why the DMA would transfer just 0s to the peripheral? Or why the peripheral would receive 0s? Does the DMA buffer need to be volatile? Makes sense that it would need to be but following the STM example code for UCPD their DMA buffers were not volatile..

 

Also I should point out this isn't just one time. Once it starts this it is continuously transmitting 0s. My program is requesting the transmissions on purpose. The point is, they are all wrong.

1 ACCEPTED SOLUTION

Accepted Solutions
Carl_G
Senior II

Hi @FBL ,

unfortunately I can't share any minimal project with the issue. I'm not having the issue at the moment. I feel strongly that the issue is caused by odd ordered configuration of the registers. Likely by configuring some registers under conditions where they should not be configured such as when the peripheral is set to off or on.

But its too complicated to try and narrow down. If it comes back yet again I might have to but I think ultimately it has been my fault.

Thanks for your support.

View solution in original post

6 REPLIES 6
Carl_G
Senior II

I've narrowed it down to CPAR and CMAR registers. When I disable, reconfigure, the reenable the DMA as long as I don't touch these registers it keeps working. This is even though I set them to 0 then a few lines of code later they get set back to their proper values before the DMA is reenabled. It's as if the register is double buffered.

What happens if the DMA is disabled but the peripherals "use DMA" flag is still enabled?

Carl_G
Senior II

Just one of those things you deal with on a complex MCU like Cortex. I can't definitively say what the issue was. I like to be able to point to a given register and look at the value and know somehow that is what caused it, but I can't. It came down to doing things in interrupt context and mixing with things out of interrupt context. It really prefer a more predictable failure but cest la vie...

Carl_G
Senior II

Well its back. Sending all 0s. Is there any technique for debugging the DMA?

Carl_G
Senior II

I do some configuration within an IRQ and some in the main loop. I think the IRQ was interrupting the main loops configuration and doing things in an unexpected order. Even though the registers were left with correct values this seems to have been a problem.

Also, as I changed my DMA data variables to volatile I had to shift to using std::copy instead of memcpy. memcpy copies in bytes but std::copy copies in the size of whatever you pass into it. so I was overwriting the limits.

weird how many different mistakes resulted in the same strange DMA behavior. I feel like I need access to some internal buffer that could have revealed the misconfiguration since the DMA is maintaining some configuration that is not apparent in its accessible buffers.

FBL
ST Employee

Hi @Carl_G 

Would you share a minimum project to reproduce on reference board?

Here some suggestions:

  • Verify the number of data items to transfer using the CNDTR register.
  • Confirm the peripheral and memory addresses in the CPAR and CMAR registers.
  • Check the DMA status register for flags indicating transfer completion, errors, etc.
  • Check TCIE (Transfer Complete Interrupt Enable) and TEIE (Transfer Error Interrupt Enable) to handle DMA transfer and error events.

In case of synchronization issue between interrupt context and main context, you can:

  • Disable interrupts during critical DMA configuration using __disable_irq() and re-enable them with __enable_irq().
  • Or, for some complex application, utilize BISPRI to set interrupt priorities, ensuring high-priority interrupts are enabled while disabling lower-priority ones.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


Carl_G
Senior II

Hi @FBL ,

unfortunately I can't share any minimal project with the issue. I'm not having the issue at the moment. I feel strongly that the issue is caused by odd ordered configuration of the registers. Likely by configuring some registers under conditions where they should not be configured such as when the peripheral is set to off or on.

But its too complicated to try and narrow down. If it comes back yet again I might have to but I think ultimately it has been my fault.

Thanks for your support.