cancel
Showing results for 
Search instead for 
Did you mean: 

DMA transfer from UART to Mem

oe
Associate II
Posted on January 12, 2010 at 17:37

DMA transfer from UART to Mem

8 REPLIES 8
oe
Associate II
Posted on May 17, 2011 at 13:37

I need to combine 4 DMX feeds (250kbit async. data).

My plan is to use DMA to transfer each feed to a buffer 512 byte long.

Take data from the desired memory positions, and create a new send buffer that I then send out.

The problem is that each ''package'' of data can be 2 - 513 byte long (slots) (First slot is 0x00 to signal that its DMX data).

To signal the end of a ''package'' DMX sources sends a BREAK signal.

To signal the start of a new package DMX sources send a MARK signal.

To make my program able to index each slot as a mem address + slot number, the DMA transfer must be reseted after each BREAK / MARK signal pair.

If I set set up DMA to recive 513 byte, I get a Interupt when I have reciver all slots. Unforhutanly this dosen't work if I ony recive say 7 slots.

So to overcome this problem, My next idea was to DMA recive 513 byte, and get a Interuppt from the UART instead for framingerror = BREAK signal.

My big question is, how can I reset the DMA address counter back to the BASE address?

Or should I do a Ring buffer insted, and keep a track on my staring mem-addr insted?

Any ideas??

chikos33
Associate II
Posted on May 17, 2011 at 13:37

Hi oe,

If I correctly understood your issue: you need to reset the counter and base address of the DMA each time you receive a new slot (using Break signal interrupt). The problem is that the DMA is still working at this moment.

What you need is to write the CNDTRx and CMARx DMA registers with new values (respectively 512 and the Buffer start address).

I may suggest two solutions (to be implemented into the USART Break interrupt routine):

1- A simple solution is to disable the DMA, to reconfigure only the CNDTRx and the CMARx registers then re-enable the DMA and let it go... (I even think it is not necessary to re-configure the CMARx register, it should keep the original value, just verify).

2- Actually, it is also possible to modify the CNDTRx and CMARx DMA registers on the fly (when DMA is enabled) but it is risky (a transfer may be ongoing at the modification moment) and it is not clearly stated in the reference manual. So if you are sure to have enough time between Break and Mark signals to do the needed operation, you could always try...

For both cases, you may use direct register access instead of firmware library functions (if you are using it) to gain time.

I hope it helps you a little :)

Regards.

kaouther
Associate II
Posted on May 17, 2011 at 13:37

Hi,

- No! It is not possible to change the CNDTRx on the fly. The DMA_CNDTRx register can only be written when the DMA channel is disabled.

This is clearely stated either in DMA_CNDTRx description or DMA section.

- It is not recommended to modify the DMA_CPARx or the DMA_CMARx on the fly. Refer to the register description :

DMA_CPARx, DMA_CMARx: << This register must not be written when the channel is enabled. >>

-In section '' 10.3.3 DMA channels'' paragraph ''Pointer incrementation'', it states the following:

<< Note: If a DMA channel is disabled, the DMA registers are not reset. The DMA channel registers(DMA_CCRx, DMA_CPARx and DMA_CMARx) retain the initial values programmed during the channel configuration phase. >>

All details are there in RM0008 :o

[ This message was edited by: coucou on 11-01-2010 13:33 ]

jj
Associate II
Posted on May 17, 2011 at 13:37

Hello coucou,

Many are pleased to see you assisting STOne-32 on this forum - thank you. (and we note that you lead another ST forum)

My group found this particular post ''especially valuable'' as you clearly listed the ''source'' of your findings and recommendations. (past coucou posts did not always contain this reference guidance - which is always helpful to we STM users)

So thank you - hope that you are able to continue here - your efforts much appreciated.

Believe such tech support is needed - the faster/easier we STM32 users can complete our design/testing the more likely we are to achieve volume production... (good for us - very good for ST...)

chikos33
Associate II
Posted on May 17, 2011 at 13:37

Try and see by yourself ;) (I used this trick a time ago and it worked fine.)

I'm sorry, but may be I didn't undertand exactly your issue?

Did you already tried the common method: disable+reconfigure+enable DMA and it didn't work?

swhite
Associate III
Posted on May 17, 2011 at 13:37

Did you see my post this morning?

http://www.st.com/mcu/forums-cat-9398-23.html

Maybe that'll be of some help.

kaouther
Associate II
Posted on May 17, 2011 at 13:37

Hi Oe,

If you need to modify the DMA_CNDTRx register it must be first disabled.

Yes the DMA_CPARx and DMA_CMARx registers contain the base peripheral/memory address.

The start address used for the first transfer is the one programmed in the DMA_CPARx /DMA_CMARx register and during transfer operations these registers keep the initially programmed value.

The DMA transfer consists on loading data from the peripheral data register or a location in memory addressed through an internal current peripheral/memory address register which are not accessible by software.

You can refer to RM0008 section “10.3.1 DMA transactions�? and section '' 10.3.3 DMA channels'' paragraph ''Pointer incrementation''.

Cheers, ;)

oe
Associate II
Posted on May 17, 2011 at 13:37

I have been playing around with both the DMA_CMARx and DMA_CNDTRx registers.

As I understand the documentation DMA_CNDTRx contains number of bytes that have / sould be transfered. I tried to reset this back to 513 on the fly witch din't work... I did miss that this regieter is read only to start with :D

As I understand stuff...

DMA_CNDTRx contains number of byte to transfer when DMA is disabled, when It's enable DMA_CNDTRx contins number of bytes that have been transfered.

While

DMA_CMARx contains the base address of the memory location to transfer to/from.

When DMA is active and in progress DMA_CNDTRx is changed while DMA_CMARx is fixed at my base adress.

If this assumption is correct, I guess that all I have to do is to disable DMA and set DMA_CNDTRx to 513, then enable DMA again.

Do anyone know if DMA_CMARx is also incremented, eg. Do I need to reset this back to my memory BASE address.

Unfortunaly my target system is broken for the moment, so I have not been able to test this...

But to know when I get my new target system, Have I understood the function of the registers??

Thanks for the help!