cancel
Showing results for 
Search instead for 
Did you mean: 

DMA reads from USART1 without RXNE set

h2
Associate II
Posted on May 06, 2014 at 12:11

Hi community,

I use the USART1 in STM32F100C4 to receive serial data in DMA mode. Because the data comes in packets with less than 16 bytes I start the DMA mode every time, when new data is expected. This works most of the time well.

But in some cases, DMA is not new started, because data is not of interest and DMA reads only 16 bytes to the memory. then DMA stops the transfer.

Next time data is expected, DMA is new started in the same manner like before:

  DMA_Cmd(DMAChannel_USART1_RX, DISABLE);

  DMAChannel_USART1_RX->CNDTR = 16;

  DMA_Cmd(DMAChannel_USART1_RX, ENABLE);

But now immediatly after DMA is enabled, the last data in USART1_DR is read to the memory althougt RXNE is cleared!

It seems, this undesirable data is only read after DMAChannel_USART1_RX->CNDTR has count to 0 in last DMA session and more data is unread received.

A resolution to that problem is allmost when I restart DMA mode like above. But I prefer to know the reason for this problem rather I solve it in this kind.

Thanks for your help,

Best reards,

Herbert

#usart1-dma-rx
16 REPLIES 16
Posted on May 06, 2014 at 14:11

Do you need to reset the transfer address as well as the transfer size?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
h2
Associate II
Posted on May 06, 2014 at 16:07

Hi clive1,

thanks for your fast answer.

The transfer addresses remains unchanged (according to user manual) and it works fine too, most of the time.

Only if the last DMA transfer had an overflow (more bytes than USART1_RX->CNDTR handels) the last received Byte in USART1_DR is transfered to the spezified memory althougt there is no event (RXNE is cleared).

Can it be, that the last event, that is not successful done, is saved in a internal bit? And if it is so, how can I reset this?

Thanks for your answer,

Herbert

Posted on May 06, 2014 at 16:48

When not using Circular mode, I generally reconfigure the DMA for each transfer, there may be short-cuts, but if you have problems try doing it explicitly and see if that behaves differently.

It really should be dependent on RXNE, you might want to clear the buffer with a known fill character and confirm what is actually being read. Remember the buffer is volatile, and that DMA continues independently of the CPU, and the debug view thereof.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
h2
Associate II
Posted on May 06, 2014 at 18:22

Hi clive1,

the DMA is not working in Circular mode, transfer is from peripherel to memory, 16 byte. This initialisation happens only at stsrtUp:

  DMA_DeInit(DMAChannel_USART1_TX);

  DMA_InitStructure.DMA_PeripheralBaseAddr  = USART1_DR_ADDR;

  DMA_InitStructure.DMA_MemoryBaseAddr      = (uint32_t)&sendBuffer;

  DMA_InitStructure.DMA_DIR                 = DMA_DIR_PeripheralDST;

  DMA_InitStructure.DMA_BufferSize          = SENDBUFFSIZE;

  DMA_InitStructure.DMA_PeripheralInc       = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc           = DMA_MemoryInc_Enable;

  DMA_InitStructure.DMA_PeripheralDataSize  = DMA_PeripheralDataSize_Byte;

  DMA_InitStructure.DMA_MemoryDataSize      = DMA_MemoryDataSize_Byte;

  DMA_InitStructure.DMA_Mode                = DMA_Mode_Normal;

  DMA_InitStructure.DMA_Priority            = DMA_Priority_Medium;

  DMA_InitStructure.DMA_M2M                 = DMA_M2M_Disable;

  DMA_Init(DMAChannel_USART1_TX, &DMA_InitStructure);

  // USART1 RX DMA1 Channel (triggered by USART1 Rx event) Config

  DMA_DeInit(DMAChannel_USART1_RX);

  DMA_InitStructure.DMA_MemoryBaseAddr  = (uint32_t)&RxBufferU1;

  DMA_InitStructure.DMA_DIR             = DMA_DIR_PeripheralSRC;

  DMA_InitStructure.DMA_BufferSize      = RXBUFFSIZEU1;

 

  DMA_Init(DMAChannel_USART1_RX, &DMA_InitStructure);

Actualy being read is the last character in USART1_DR. I can proof that in debug mode. As soon as DMA is enabled the contents of register USART1_DR is read to my first memory buffer byte.

Then i tried some thing:

- read the USART1_DR bevor enabeling DMA (to clear an event)

- clear the bit RXNE bevor enabeling DMA

nothing of that was successful.

When I relaod DMAChannel_USART1_RX->CNDTR twice immediatly one after the other:

  DMA_Cmd(DMAChannel_USART1_RX, DISABLE);  

  DMAChannel_USART1_RX->CNDTR = RXBUFFSIZEU1;

  DMA_Cmd(DMAChannel_USART1_RX, ENABLE);

  DMA_Cmd(DMAChannel_USART1_RX, DISABLE);  

  DMAChannel_USART1_RX->CNDTR = RXBUFFSIZEU1;

  DMA_Cmd(DMAChannel_USART1_RX, ENABLE);

then the program runs in debug mode correct (run mode and sigle step) but without debugger it fails (reads from USART1_DR). As long, as this action takes place it is shure, that no other characters are received to USART1.

I know that DMA runs independently of the CPU, but if the data in memory buffer is normaly read in, some 10ms are gone and the actual received string is perfectly read but the first character is this forgotten  and undesirable last character in the DR register 😉

Shure, I try to initialize the hole DMA if I find no other solution, but it leaves me with a bad feeling perhaps the reason is unknown.

Maybe there is an error in my program and I unwillingly tolerate this whilst I do a work around.

Herbert

Posted on May 06, 2014 at 19:25

Shure, I try to initialize the hole DMA if I find no other solution, but it leaves me with a bad feeling perhaps the reason is unknown.

The reason for the suggestion is to contain the problem, and will permit you to look in the right place for the problem. Yes, I know you're using it in Normal mode, if you didn't want to keep programming the DMA you'd perhaps use Circular mode with HT/TC managing the buffer.

Be very careful that the debugger is not interfering with the internal state of the peripherals, it is especially important NOT to park a debug view over the peripheral registers.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
h2
Associate II
Posted on May 06, 2014 at 20:14

Hi clive1,

it is a possibility to use Circular mode. I have thougth about it, but I am not shure if it means some Problems in the programm structur.

What do you mean with ''NOT to park a debug view over the peripheral registers''. Exist there a possible problem if i open a debug view window for USARTx (can debug readings corrupt the program?).

But independent of this, the error appears in my old program wether debug is plugged on or not.

Today its to late. Tomorrow i will try to reinit the DMA and show what happens.

Thanks

Herbert

Posted on May 06, 2014 at 21:18

What do you mean with ''NOT to park a debug view over the peripheral registers''. Exist there a possible problem if i open a debug view window for USARTx (can debug readings corrupt the program?).

The debugger is INVASIVE, it doesn't have a magic method of looking at the registers, it reads them as normal code would, with the same side effects of clearing/setting bits in other registers. ie reading USART->DR will clear USART->SR RXNE, and any pending error bits
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
h2
Associate II
Posted on May 07, 2014 at 11:10

Hi clive1,

of course you are right, The debugger has no magic power :-). Sometimes I forget that the debugger do the same as the CPU would do.

In the meantime I have written a complete initialization for the DMA registers, when a new string is expected. But if an overflow on input bytes occurs in the last session, the result is the same: the last byte of the last string is the first byte in my buffer after receiving of the new string. It seems so, that only a reset can make the CPU to forget that condition.

Now I run out of ideas to solve the problem. Because in that case of overflow, the register DMAChannel_USART1_RX->CNDTR is cleared, I only have to throw away the first byte in the buffer. This works fine, but is is no real solution, that makes me jump in the air.

Perhaps you have any further ideas?

Thanks

Herbert

h2
Associate II
Posted on May 08, 2014 at 17:38

Hi to all,

now I made a rework to that problem because it's not possible for me to find the cause.

I consequently switch off the USART1 and the belonging DMA after every sending data and receiving answers. Then the problem is solved.

Two other members of the forum had seemingly similar problems: waclaweek.jan (8/16/12) and A.Paivo (11/20/12).

Unfortunately there where no solutions too.

Thanks for your help

Herbert