cancel
Showing results for 
Search instead for 
Did you mean: 

DMA and DCMI issues.

thomas2
Associate II
Posted on November 05, 2013 at 17:50

Hi,

I've recently been playing with a Keil MCBSTM32F200 board, specifically using the camera module. Essentially, I'm trying to use DMA2 to route the camera data to an arbitrary location in the SRAM instead of directly to the LCD memory. In order to do image processing before finally displaying the image. I can 'DMA' from camera to LCD address fine, but when I start sending it to say '0x20000000' (valid location in SRAM), it is only sending the first 'pixel' of data. Do I need to manually increment the destination address? I'm not sure if this happens automatically because when I set the LCD address as the destination and view the memory map, all the pixel values appear to be copied across. Here is my DMA & DCMI setup code:

/* Configure DCMI peripheral */
DCMI->CR &= ~(DCMI_CR_ENABLE | DCMI_CR_CAPTURE);
DCMI->CR = DCMI_CR_PCKPOL | /* Rising polarity */
DCMI_CR_VSPOL; /* VS Polarity high */
/* HS Polarity low */
/* Continuous mode */
/* Hardware sync */
/* Capture rate all frames */
/* Extended data mode 8b */
/* Configure DMA stream */
DMA_StreamInitialize(DCMI_DMA_NUMBER, DCMI_DMA_STREAM);
s_ctrl = (DCMI_DMA_CHANNEL << DMA_CHANNEL_POS) |
DMA_MEMORY_DATA_16BIT |
DMA_PERIPHERAL_DATA_32BIT |
(DCMI_DMA_PRIORITY << DMA_PRIORITY_POS) |
DMA_PERIPHERAL_TO_MEMORY |
DMA_CIRCULAR_MODE |
DMA_TRANSFER_COMPLETE_INTERRUPT;
DMA_StreamConfigure (DMAx_STREAMy(DCMI_DMA_NUMBER, DCMI_DMA_STREAM),
s_ctrl,
DMA_FIFO_DIRECT_MODE_DISABLE |
DMA_FIFO_THRESHOLD_25,
DCMI_SRC_ADDR,
SRAM_ADDR,
1);

I'm not 100% sure what the FIFO Direct mode and threshold does. I've tried changing the NDTR from 1 to 76800, (the amount of pixels I have) but that doesn't seem to make a difference. Should I still use DMA if I am going to be processing every pixel anyway? I'm trying to figure out the best way capture a frame in memory, process it then output the result. As fast as possible. Any advice on this would be greatly appreciated. Thanks in advance. Kind regards, Thomas #dma-dcmi
10 REPLIES 10
Posted on November 05, 2013 at 19:20

You'd need for the DMA to increment the destination address, and have a large enough buffer to hold the frame.

The data is likely coming in too fast to attempt to deal with a pixel at a time. Have the DMA TC interrupt trigger the processing of the frame buffer.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
thomas2
Associate II
Posted on November 06, 2013 at 10:32

Thank you for the quick reply Clive, much appreciated.

Is there a DMA setting I'm missing that would increment the destination address, or should I be doing this manually in the TC interrupt? Also, is there any way to make the TC interrupt only trigger after the entire DCMI frame has been moved, because currently I believe it triggers after every unit of transfer. Does using Direct Mode have any impact on this?

I'm not actually processing each pixel as it comes in (although I have tried that in the TC interrupt with mixed results). Ideally I need a complete frame buffer to work on before applying the post processing effect.

Thanks in advance.

frankmeyer9
Associate II
Posted on November 06, 2013 at 11:02

Is there a DMA setting I'm missing that would increment the destination address, ...

You probably want something like this:

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

Also, is there any way to make the TC interrupt only trigger after the entire DCMI frame has been moved, because currently I believe it triggers after every unit of transfer. The ''transmission complete'' triggers after the configured number of items/words is transfered - which might be byte, half-word (16 bit) or word, depending on your configuration. You might have set just one pixel currently, which is, as you noted, not very efficient.
thomas2
Associate II
Posted on November 06, 2013 at 11:33

That fixed part of the problem, thanks fm.

I've changed the NDTR from 1 to 76800. Each unit is 4 bytes, even though the memory data is set to '16bit' - it seems to pad the data out to 32 bit.. I'm not sure if there is a maximum transfer amount, but it appears to work. What's interesting is that when sending the DCMI data to the LCD memory address, I don't need to enable the increment.

Thanks again.

frankmeyer9
Associate II
Posted on November 06, 2013 at 12:00

I'm not sure if there is a maximum transfer amount,

 

AFAIK, it is 65535 items (bytes, halfwords, or words), but there is the reference manual to check.

What's interesting is that when sending the DCMI data to the LCD memory address, I don't need to enable the increment.

 

Most of the LCD/TFT controllers I know use auto-increment features for faster transfers.

That may explain it.

thomas2
Associate II
Posted on November 06, 2013 at 12:35

Interesting, thanks for the info. So I guess I will have to transfer the DCMI frame in two 38400 'chunks'. Disabling circular mode and altering the destination address accordingly in the TC interrupt each time.

However a couple of things are unclear. As I understand it DCMI streams the data one pixel byte at a time, so I don't need to increment the DMA source address. That being said, could timing be an issue when re-configuring the DMA transfer for the second 'chunk' of the frame? I'm also looking into using FIFO Direct Mode but I'm not 100% what it does/advantage it brings. Thanks in advance and sorry for the barrage of questions.
frankmeyer9
Associate II
Posted on November 06, 2013 at 14:33

In honesty, I didn't mess with DCMI yet, so I cant' tell much about it.

But generally, peripherals deliver data at one register (say, address) only, so ''peripheral address increment'' is set to false.

And second, DMA doesn't care about the semantics of the data, it only moves items as configured, and when triggered.

Basically, I have used DMA mostly for audio applications, with just one buffer, and lower throughput rates. I hope somebody with more profound experience in DMA usage can chime in ...

Posted on November 06, 2013 at 15:09

I'm not familiar, or desire to dissect, the register/library you are using.

Avail yourself of the ST firmware libraries, and the DCMI examples therein.

As fm indicates, the DCMI peripheral address doesn't need to move/increment, the data from the video frame does need to go into memory, and that address does need to increment.

A review of the camera datasheet, and those of the ST part and it's DMA controller might be helpful.

Don't confuse the needs of the LCD, with those of composing a frame in memory.

As you probably can't process the frame as quickly as they arrive, you will need to disable Circular mode, and then light off the next DMA transfer when you are ready.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
thomas2
Associate II
Posted on November 06, 2013 at 19:06

Thanks for the tips. I will try to find some decent DCMI documentation, as the example project with my board provides little to no explanation, hence the queries.

I'm trying to find the standard peripheral firmware examples you suggested which sound very useful, I assume it will be somewhere near here 

http://www.st.com/web/en/catalog/mmc/FM141/SC1169/SS1577

 ? As my board is STM32F400 based. 

Anyway, I've got the image moving into SRAM with circular mode disabled. However I can't seem to re-enable the DMA transfer from within the TC interrupt. After disabling and re-initializing the stream.  I may try using a separate stream for the second half of the transfer. Thanks again for the help.