2013-11-05 08:50 AM
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
2013-11-05 10:20 AM
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.2013-11-06 01:32 AM
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.2013-11-06 02:02 AM
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.
2013-11-06 02:33 AM
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.2013-11-06 03:00 AM
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.
2013-11-06 03:35 AM
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.2013-11-06 05:33 AM
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 ...2013-11-06 06:09 AM
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.2013-11-06 10:06 AM
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 ? 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.