cancel
Showing results for 
Search instead for 
Did you mean: 

Some more DCMI problems F207IG

stbbrad3
Associate II
Posted on January 09, 2012 at 16:30

Hello everyone,

A couple months back I was having some issues with DCMI that were mostly solved with some help here at the forums. You can see the pevious thread [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/DCMI Issues, looking for insight&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/AllItems.aspx?Paged%3DTRUE%26p_StickyPost%3D%26p_DiscussionLastUpdated%3D20111212%252010%253a46%253a14%26p_ID%3D19852%26View%3D%257bF47A9ED8%252dE726%252d42BE%252dACED%252d732F13B66581%257d%26FolderCTID%3D0x012001%26PageFirstRow%3D121&currentviews=590]here.

I am now attempting to get high resolution images working. I have a new board in with direct connections of the data, sync, and clock lines from the MT9v024 sensor ( previously through LVDS ).

I have no problem capturing low resolution images which has the pixel clock binned by 4 from 14MHz to 3.5MHz. When I try to bin by 2 or without any binning at all I cannot see the end of frame get set. I am clocking the HCLK up from 32MHz to 120MHz, as well as maxing out the peripheral clocks, to capture the image ( even when binning by 4 ).

Has anyone else ran across this type of issue, or have any idea why I would not be seeing end of frame with a faster pixel clock. From my understanding 14MHz should be well within range of the DCMI processing, escpecially with the MCU clocked up to 120MHz.

Any response would be appreciated.

Thanks,

Brad

#dcmi
12 REPLIES 12
infoinfo989
Associate III
Posted on January 10, 2012 at 18:09

From my understanding, end of frame is generated by the de-assertion of vsync. So I presume you've checked on a scope that indeed your vsync is toggling?

I've seen end of frame fail to occur when the DCMI port suffers some kind of an internal error. See this:

http://blog.frankvh.com/2011/08/19/stm32f2xx-digital-camera-interface-dcmi/

There's a scope capture there showing dcmi end of frame's being missed.

In our case, because we've found the end of frame to be a bit flakey, we've also routed vsync to a GPIO pin, so we can get an interrupt that way. We use this GPIO interrupt instead of (as a substitute for) the DCMI  end of frame interrupt.

Also, presumably you're using the DMA to grab data from the dcmi port. We've found problems when using DMA for 3 (or more?) peripherals simultaneously, and we rearranged things to only have 2 DMA transactions active at a time.

stbbrad3
Associate II
Posted on January 17, 2012 at 21:08

Hi Frank,

Thanks for the response. Sorry it took me so long to respond.

Just to share with you the only DMA transfer at the time of capturing a picture is the DCMI to FSMC. I have my memory timing as tight as i can get them and DCMI settings are correct. I have hooked up to a scope and everything is fine. I can now capture low resolution(bin 4:1) and medium resolution(bin 2:1) pictures as I had to do some shuffling of the buffers in my external RAM.

I believe I have located my problem when trying to capture large resolution and it is appears to be directly related to the DMA buffer size. It appears no matter what size I set the DMA buffer size to... the farthest it will write into memory is 4x the buffer size (ie. 0xffff writes as far as 0x3fffc and 0x1000 writes as far as 0x4000).

Do you or anyone else have experience or any ideas/suggestions why this may be happening?

In the reference manual it states,

''

The Circular mode is available to handle circular buffers and continuous data flows (e.g.

ADC scan mode). This feature can be enabled using the CIRC bit in the DMA_SxCR

register.

When the circular mode is activated, the number of data items to be transferred is

automatically reloaded with the initial value programmed during the stream configuration

phase, and the DMA requests continue to be served.''

So from what I understand I should be fine reading all 354,944 bytes of image data, instead I can only read 262,140.  This is the best explanation why my image has noise at the top and what should be at the top is at the bottom ( as well as the fact that I can see it stop filling memory up 0x3fffc bytes away from the start of the buffer ).

The only thing I am unsure is my comforming to the note in the same section...

''Note: In the circular mode, it is mandatory to respect the following rule in case of a burst mode

configured for memory:

DMA_SxNDTR = Multiple of ((Mburst beat) × (Msize)/(Psize)), where:

– (Mburst beat) = 4, 8 or 16 (depending on the MBURST bits in the DMA_SxCR

register)

– ((Msize)/(Psize)) = 1, 2, 4, 1/2 or 1/4 (Msize and Psize represent the MSIZE and

PSIZE bits in the DMA_SxCR register. They are byte dependent)

– DMA_SxNDTR = Number of data items to transfer on the AHB peripheral port

For example: Mburst beat = 8 (INCR8), MSIZE = ‘00’ (byte) and PSIZE = ‘01’ (half-word), in

this case: DMA_SxNDTR must be a multiple of (8 × 1/2 = 4).

If this formula is not respected, the DMA behavior and data integrity are not guaranteed.

NDTR must also be a multiple of the Peripheral burst size

multiplied by the peripheral data </p>

 

size, otherwise this could result in a bad DMA behavior.''

</i>

 

 

 

 Below is the DMA init code:

 

    /* DMA Stream Configuration */ 

 

    DMA_DeInit ( DCMI_DMA_STREAM );

 

   

 

    DMA_InitStructure.DMA_Channel            = DCMI_DMA_CHANNEL; 

 

    DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;  

 

    DMA_InitStructure.DMA_Memory0BaseAddr    = DCMI_IMAGE_SRAM_ADDRESS;

 

    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory;

 

    DMA_InitStructure.DMA_BufferSize         = 0xffff;    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;

 

    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;

 

    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

 

    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;

 

    DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;

 

    DMA_InitStructure.DMA_Priority           = DMA_Priority_VeryHigh;

 

    DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;   // Tried with enable: same results     

 

    DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;

 

    DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;

 

    DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;

 

      

 

    DMA_Init ( DCMI_DMA_STREAM, &DMA_InitStructure );              

 

      

 

Thanks again for reading!

 

 

Please leave any feedback,

 

 

Brad

 

amin23
Associate II
Posted on January 18, 2012 at 07:46

Hi Brad,

See the previous thread [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/DCMI Issues, looking for insight&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/AllItems.aspx?Paged%3DTRUE%26p_StickyPost%3D%26p_DiscussionLastUpdated%3D20111212%252010%253a46%253a14%26p_ID%3D19852%26View%3D%257bF47A9ED8%252dE726%252d42BE%252dACED%252d732F13B66581%257d%26FolderCTID%3D0x012001%26PageFirstRow%3D121&currentviews=590]here

just read the messages posted by AMSN

stbbrad3
Associate II
Posted on January 18, 2012 at 16:56

AMSN,

Thank you for opening my eyes. I tried this setup with the previous camera using LVDS and it didn't work... but doing this has fixed my problem with the DMA.

Thanks a ton!

Brad

infoinfo989
Associate III
Posted on January 19, 2012 at 06:35

The amount of data you're reading in a single DCMI frame is larger than what we do. Our typical frame data size is around 160 kB, whereas you're more like 350 kB. So I can't state from experience that your amount of data is OK - we just don't get that much the way we do it. I certainly don't see anything in particular you're doing wrong, and the fact you receive as much data as you do means it's obviously ''working'', at least mostly. Hmmm.

John F.
Senior
Posted on January 19, 2012 at 08:49

Hi Brad,

Just so the rest of us can keep up ... ''doing

this

has fixed my problem''.

Doing what?

amin23
Associate II
Posted on January 19, 2012 at 15:05

Hi Brad,

I think the previous camera problem it was the FSMC config;

in the previous example you are using FSMC Addresses 0-17, so you are able to address

2^18 = 262144 bytes, but the image size it was 354944 bytes.

to fix this Pb, you have to extend the FSMC bus address (A0 - A18).

stbbrad3
Associate II
Posted on January 19, 2012 at 16:47

Hello everyone,

Actually I am now using FSMC A0 - A19, 2^20 = 1MB. I have a DCMI capture buffer, a rotated image buffer and a JPEG buffer interspaced in the memory so everything is fine there.

My problem was solved by using double buffer mode. I thought that DMA, even with one buffer ( M0AR ) in circular mode, would work by continually incrementing the memory location until the DCMI capture was complete. This was not the case. After writing the max buffer 0xFFFF * 1 word ( 4 ) = 0x3FFFC the buffer would reset back to its original address in M0AR.

I am now setting my second buffer to start at 0x3FFFC and when I am done with the first transfer and the TC flag is set my interrup places the 1st buffer out to 0x7FFF8 ( 0xFFFF * 8 ). This seems to solve all of my issues. One thing I did run into and was solved by reading Frank's blog was the makeing sure to clear the DMA interrupt flags before enabling the DMA again for the next picture.

If you want to have a look the code for this is below:

Init code for DMA:

    /* DMA Stream Configuration */ 

    DMA_DeInit ( DCMI_DMA_STREAM );

   

    DMA_InitStructure.DMA_Channel            = DCMI_DMA_CHANNEL; 

    DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;  

    DMA_InitStructure.DMA_Memory0BaseAddr    = DCMI_IMAGE_SRAM_ADDRESS;

    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory;

    DMA_InitStructure.DMA_BufferSize         = 0xffff;//65535;

    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;

    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;

    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Word;

    DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;

    DMA_InitStructure.DMA_Priority           = DMA_Priority_VeryHigh;

    DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Enable;       

    DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;

    DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;

    DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;

      

    DMA_Init ( DCMI_DMA_STREAM, &DMA_InitStructure );             

     

    

    DMA_DoubleBufferModeConfig(DMA2_Stream1, DCMI_IMAGE_SRAM_ADDRESS + ( 0xffff * 4 ), DMA_Memory_0);

    DMA_DoubleBufferModeCmd(DMA2_Stream1, ENABLE);

    DMA_ITConfig ( DMA2_Stream1, DMA_IT_TC, ENABLE );

Capture code is following:

uint8_t Camera_Capture_Image ( void )

{

    DIL_OS_Set_Clock_Speed ( 120 );

     

    /* Disable any old interrupts before enabling DMA 

       WARNING: This is not specified in the reference manual,

                but MUST be done before enabling stream.       */

    DMA_ClearITPendingBit ( DCMI_DMA_STREAM, DMA_IT_TCIF1  |

                                             DMA_IT_HTIF1  |

                                             DMA_IT_TEIF1  |

                                             DMA_IT_DMEIF1 |

                                             DMA_IT_FEIF1  );

   /* Reset DMA buffer addresses before starting transfer - Safety */

    DMA2_Stream1->M0AR = DCMI_IMAGE_SRAM_ADDRESS;

    DMA_DoubleBufferModeConfig(DMA2_Stream1, DCMI_IMAGE_SRAM_ADDRESS + ( 0xffff * 4 ), DMA_Memory_0);

 

    /* Enable DMA transfer */

    DMA_Cmd ( DCMI_DMA_STREAM, ENABLE );

   

    /* Wait for DMA to start up */

    while ( DISABLE == DMA_GetCmdStatus ( DCMI_DMA_STREAM ) );

    /* Enable DCMI interface */

    DCMI_Cmd ( ENABLE );    

    DCMI_ITConfig ( DCMI_IT_FRAME, ENABLE );  

   

    /* Start Image capture */

    DCMI_CaptureCmd ( ENABLE );

   

    while ( 0 == DCMI_GetFlagStatus ( DCMI_FLAG_FRAMERI ) );

   

    DCMI_CaptureCmd ( DISABLE );   

    DCMI_Cmd ( DISABLE );

    DMA_Cmd ( DCMI_DMA_STREAM, DISABLE );

    /* Wait for DMA to stop */

    while ( ENABLE == DMA_GetCmdStatus ( DCMI_DMA_STREAM ) );

 

    DIL_OS_Set_Clock_Speed ( 32 );

   

    return ERROR_SUCCESS;

}

 The interrupt is as follows :

void DMA2_Stream1_IRQHandler(void)

{

 

    DMA2_Stream1->M0AR = DCMI_IMAGE_SRAM_ADDRESS + ( 0xFFFF * 8 );

}

Thanks again for everyones help!

Brad

simonlee0311
Associate II
Posted on April 15, 2012 at 10:52

Dear Brad:

Good day. I also have same problem with you, and I also try to solve this problem.

May I ask you a question?

As I know,  first setting M0AR to first transfer, and when M0AR was filled and has a interrupt, then setting M1AR to second buffer address, right?

Why you only setting M0AR? It make me a little confuse, would you please tell me more, or is my understanding there is an error.

Best regards,

Simon