cancel
Showing results for 
Search instead for 
Did you mean: 

DCMI Issues, looking for insight.

stbbrad3
Associate II
Posted on November 07, 2011 at 17:23

Hello everyone,

I have had a couple porblems resolved by sharing with the community here. I am now moving into the toughest part of my project. I am incorporating a Micron VGA CMOS Digital Image Sensor that I have previously had working on an 8051 through an Altera FPGA chip.

The image sensor only put out intersperesed 8 bit serial LVDS so I have it going through a de-serializer and all the signals look perfectly fine as expected. I have 1 byte of data the Pixel clock and H and V Syncs all wired into the STM3220g eval board, which has the F207IG on board.

Now that the quick introduction is out of the way. Let me get started out with what I am seeing. I have DMA setup to transfer a picture into SRAM and this is happening, except for the fact that all my image data is exactly the same. The DMA is transferring 0x04040404 into memory as that is all that is put in the data register. I know this is not all the data that the camera is putting out as it I have it setup in test mode putting out a grayscale image. I know that it is seeing something from the camera though as it is not getting anythign in the data register when i disconnect the camera.

I do notice some discrepencies between the memory map file and the reference manual from what I am actually seeing in the DCMI_SR. In Crossworks Studio I am seeing:

DRDY

CECS

SECS

CEIS

SEIS

Where in the reference manual it is showing:

FNE

VSYNCE

HSYNC

Has anyone else noticed these differences or know what the CECS,SECS, CEIS, SEIS may stand for?

The DRDY, CECS, and SECS flags are the onse being set. When DRDY is set so is CECS, and SECS is reset. When SECS is set, DRDY and CECS are reset.

Regarding my issue, I know I really didn't address with a question as I am a bit confused still with working with this DCMI. I will at keep everyone posted on my progress.

Please if you have any experience using DCMI and are willing to share I am willing to read!

Thanks,

Brad
47 REPLIES 47
infoinfo989
Associate III
Posted on November 08, 2011 at 02:00

Brad, we're using the DCMI port on a 207 to receive data from an Aptina sensor. We don't have any LVDS in the middle though - the sensor is hooked up directly.

One of the things I found super-uber-confusing in the DCMI documentation is their definitions of the control signal polarities. It might be that you're grabbing data from the DCMI port when the image sensor is not sending data, because the active / inactive polarity is set backwards. Take a look at this, copied from my code:

  // DCMI configuration

  // For the image sensor, vsync is ''frame sync'' and is high when the sensor is transmitting an image.

  // hsync is ''line sync'' and is high when the sensor is transmitting data, low when it's not. It

  // will go high and low many times during a frame. The sensor outputs data on the falling edge

  // of the clock, hence this processor must clock data in on the rising edge of the clock.

  // Note: the F2xx datasheet is incredibly confusing regard V & Hsync polarity. ''Polarity_Low'' here

  // means the DCMI_CR register bit VSPOL/HSPOL is clear, which means the CPU interprets a logic-1 (high)

  // sync as meaning ''valid data available''. Makes no sense I know, but the processor logic is inverted

  // from what you'd expect. Tell it zero, it grabs on a 1.

 

  DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;        // repeatedly process frames

  DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;

  DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;

  DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_Low;

  DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;

  DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;

  DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;

  DCMI_Init(&DCMI_InitStructure);

  DCMI_JPEGCmd (ENABLE);                            // enable DCMI JPEG mode

 

stbbrad3
Associate II
Posted on November 08, 2011 at 17:24

Frank,

Thanks again for replying to another one of my threads. I have already tried messing with the polarity settings and had no success. I am interested to see how you have set your DMA up as well.

Currently I am setup to write to SRAM.

Here is what I have:

    /* Enable DCMI clock */

    RCC_AHB2PeriphClockCmd ( DCMI_CLK, ENABLE );

   

    /* DCMI configuration *****************************************************/

    DCMI_DeInit ( );

   

    DCMI_InitStructure.DCMI_CaptureMode      = DCMI_CaptureMode_SnapShot;//Continuous;

    DCMI_InitStructure.DCMI_SynchroMode      = DCMI_SynchroMode_Hardware;

    DCMI_InitStructure.DCMI_PCKPolarity      = DCMI_PCKPolarity_Falling;

    DCMI_InitStructure.DCMI_VSPolarity       = DCMI_VSPolarity_High;

    DCMI_InitStructure.DCMI_HSPolarity       = DCMI_HSPolarity_High;

    DCMI_InitStructure.DCMI_CaptureRate      = DCMI_CaptureRate_All_Frame;

    DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;

    DCMI_Init ( &DCMI_InitStructure );

   

    /* Configures the DMA to transfer Data from DCMI to the FSMC **************/

    /* Enable DMA clock */

    RCC_AHB1PeriphClockCmd ( DCMI_DMA_CLK, ENABLE ); 

   

    /* 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    = 0x64000000;//FSMC_DR_ADDRESS;

    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory;

    DMA_InitStructure.DMA_BufferSize         = 512;

    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_High;

    DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;//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 );

Thanks again,

Brad

stbbrad3
Associate II
Posted on November 08, 2011 at 18:11

So I have my VSYNC, HSYNC, and PCLK all hooked up to an oscilloscope. I am probing and looking at the data lines and I am certain that the value is changing. Of course there may be a few 0x04 throughout, but it does not explain why the DCMI_DR is always 0x04040404 everytime DRDY is set, or why i get 2KB of 0x04's in memory.

From what I understand there a 4 word length FIFOs to hold the data whilst DMA does the transferring, so I should expect this to change.
stbbrad3
Associate II
Posted on November 08, 2011 at 20:59

Good News!

I am getting some data that actually looks valid to move into memory!

My test pattern is simple. Starts at 0x0F and increments one bit at a time.. OF, 10, 11, 12.... yada yada yada.

So, in memory I am looking at something that resembles it but here is how it is coming out:

0X0F, 0F, 0F, 0F, 10, 10, 10, 10, 11, 11, 11, 11, 10, 12, 12, 12, 13, 13, 13, 13, 12, 1C, 1C, 1C, 1D, 1D,1D,1D,1C,26,26,27,2F.... 

So it looks like I am on the right track and if I had to guess would say that my issue lies in my DMA transferring.

Will keep you guys updated.

Brad

stbbrad3
Associate II
Posted on November 10, 2011 at 02:01

So guys,

I had two issue with the posts before. The first was my camera was setup to do row and colum binning which will put out the same data for four pixel clock cycles. Second my SYSCLK was running too slow to keep up with the camera.

I upped the system clock and know how have good data.

I was wondering... in order to keep the size down if it was possible to get the DCMI to ignore 3 of every 4 pixel clocks. Can this be achieved internally? Right now I have started coding a copy of the data where I am just copying the fourth byte and writing it to a new area in SRAM.

Does anyone know if pixel clocks can be skipped on a regular basis, such as only accepting data 1 of every four cycles?

Cheers,

Brad
infoinfo992
Associate II
Posted on November 10, 2011 at 03:18

Hi Brad,

I'm working on a similar project with similar issues and it would be great if you could post your final config for the DCMI and DMA. Your previous settings were helpful but I'm still only getting 2016 bytes of data when capturing a frame.

I have slowed the pixel clock down with the internal PLL divider on the image sensor, so I don't think SYSCLK is an issue (but will check shortly).

I'm outputting a colour bar test pattern (in theory), but even the 2016 bytes of data I am receiving doesn't seem to match the pattern. I will start looking at the DCMI_DR shortly and see what that looks like but I believe the problem is in the DMA transfer.

I'm also interested in your data skipping question, as we only wishto capture Y from YUV data pattern, I wish I had an answer for you on this one but I think you are about a day ahead of me!

Anybody else have any ideas?

Thanks,

Mike

infoinfo989
Associate III
Posted on November 10, 2011 at 07:09

I don't believe the DCMI port has a mode where it grabs on every 4th (or some other number) clock.  It does have a ''crop'' mode, where it takes only a portion of the image. So with crop  you'd have a small portion of the image at full-resolution. Whereas if you could get every 4th pixel (as you suggested) you'd have the full image at a lower resolution.

I will warn you that simply taking every 4th pixel (for example) does nasty things to image quality, because it introduces aliasing. Binning is a better solution.

It's pretty common for CMOS image sensors to have a binning or decimation mode. That's probably more what you're looking for. With 2x2 binning for example, the sensor takes a 2x2 block of pixels, sums them together and outputs the result as a single pixel. For example, a 1024 x 1024 sensor would end up outputting 512 x 512 pixels when using 2x2 binning.

stbbrad3
Associate II
Posted on November 10, 2011 at 18:00

Thanks for the replay Frank.

This sensor is just a test sensor as it is old and only works in grayscale. U will be getting a new one very soon and will look into binning with that.

As regards to what really helped gettign everything working was the system clock speeds. I ended up kicking the sysclock up to 120 MHz in order to get all the data in from the DCMI correctly.

Now my question is can the STM32 series work on an adjustable clock. Say it is time to get a picture.. can I boost my clock speed up from 32MHz to 120MHz, grab hte picture then clock back down?

Thanks,

Brad

stbbrad3
Associate II
Posted on November 10, 2011 at 19:41

Well I read through the RCC file really good and came up with a routine that appears to be working just as I need.

Here it is in case anyone is interested:

void SetClockSpeed ( uint8_t ucSpeed )

{

    RCC_ClocksTypeDef RCC_Clock;

   

    RCC_GetClocksFreq ( &RCC_Clock );

   

    // Set Clock to default values

    RCC_DeInit ();

   

    // Initialize the HSE and wait for it to startup

    RCC_HSEConfig ( RCC_HSE_ON );

    while ( SUCCESS != RCC_WaitForHSEStartUp () );

   

    // Enable flash prefetch

    FLASH_PrefetchBufferCmd ( ENABLE ); 

   

    // Disable PLL before changing values

    RCC_PLLCmd ( DISABLE );

   

    // Set PLL as clock source

    RCC_SYSCLKConfig ( RCC_SYSCLKSource_PLLCLK );

   

    // Set up PLL, determines final SYSCLK frequency

    if ( 120 == ucSpeed )

    {  

        // Set flash latency

        FLASH_SetLatency ( FLASH_Latency_3 );

       

        // Configure PLL for 120Mhz

        RCC_PLLConfig ( RCC_PLLSource_HSE, 20, 192, 2, 5 );

       

        // Setup the AHB clock

        RCC_HCLKConfig ( RCC_SYSCLK_Div1 );

       

        // Set APB1 clock

        RCC_PCLK1Config ( RCC_HCLK_Div4 );

       

        // Set APB2 clock

        RCC_PCLK2Config ( RCC_HCLK_Div2 );

       

    }

   

    else

    {

        // Set flash latency

        FLASH_SetLatency ( FLASH_Latency_0 );

       

        // Configure PLL for 32Mhz

        RCC_PLLConfig ( RCC_PLLSource_HSE, 25, 192, 6, 4 );

       

        // Setup the AHB clock

        RCC_HCLKConfig ( RCC_SYSCLK_Div2 );

       

        // Set APB1 clock

        RCC_PCLK1Config ( RCC_HCLK_Div1 );

       

        // Set APB2 clock

        RCC_PCLK2Config ( RCC_HCLK_Div1 );      

       

    }

    // Enable the PLL

    RCC_PLLCmd(ENABLE);

   

    RCC_GetClocksFreq ( &RCC_Clock );

}