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 10, 2011 at 20:43

Well I was going to reply and say ''I'm sure it can'', but you've already answered your own question. The real question I would have, is can the rest of your system handle this? Things like SD Cards, ethernet ports, USB interfaces, USARTs, etc, may not take kindly to seeing their clocks change.

Also, I don't know how you generate the master clock for your image sensor, but it might not like it either. In our case we use a timer output pin to generate the image sensor clock (saves the cost of an oscillator on the image sensor board). Changing the CPU clock frequency would change this timer output frequency (in our example).

infoinfo992
Associate II
Posted on November 14, 2011 at 02:40

Hi,

I've managed to get a nice valid image in the ram, some confusion over the memory width and what the DMA 'buffer' (transaction counter) was actually doing were slowing things down there.

Now the current issue is that there seems to be an image frame size limitation through using the transaction counter. At the moment I'm setup for QVGA YUV (422), so that's 320 x 240 = 76800 pixels with 2 bytes per pixel that's 153600 bytes...but then we are transferring 4 bytes on each count so that's 38400 transfers to get the image. The count has a max value of 65535 so it's okay. Now I would also like to capture a VGA image and that will exceed the max allowable transfer count.

Does anyone know if it is possible to use the peripheral flow controller with the DCMI? Is it possible to have this operate on the pixel clock or HSYNC?

Brad - I haven't thought to hard about it but a dirty trick that might work to capture every 4th byte would be to only up your memory location address by 1 for every 4 bytes captured, overwriting 3 bytes from the previous capture every time, then trim the extra 3 off the end. Very dirty - don't tell my boss or I'll be fired for even mentioning such a dirty thought!

Posted on November 14, 2011 at 03:53

For big transfers you could presumably use a smaller receiving buffer, set the DMA to cyclic, and then catch two halves of a ping/pong arrangement with the HT/TC (Half/Terminal) interrupts, and either shovel it somewhere else or chain through a list of new DMA buffers.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
infoinfo989
Associate III
Posted on November 15, 2011 at 06:59

The only peripheral that the DMA allows as a peripheral flow controller is the SDIO. For all other peripherals the DMA needs to be the boss.

As Clive says, to handle larger images, create 2 or more buffers, and use the double-buffer mode of the DMA to flip between them. For 2 buffers the DMA will do it by itself. For more than 2 buffers you'll need to change the ''next buffer'' address (M0AR or M1AR) yourself in the DMA interrupt service routine.

infoinfo992
Associate II
Posted on November 16, 2011 at 21:34

Thanks for the tips guys, will have a look at that shortly.

Just come across another problem that I can't find an answer for. When starting out I had slowed down the image sensor PCLK output down to 12MHz (YUV). Now if I try and speed that up I get data overun errors in the DCMI at about the PCLK 24MHz area.

My first thought was that the clocks weren't setup up properly, so I checked that and it looks as though everything is running at full speed 120MHz/60/30. The default camera output for YUV VGA is PCLK 48MHz which would still meet the criteria of 1/2.5 HCLK and so I thought would still be okay. If the clocks are right then something must be setup non-optimally...and ideas what?

Current settings:

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

  DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot;   

  DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;

  DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;

  DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;

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

  /* Configures the DMA2 to transfer Data from DCMI to the LCD ****************/

  /* Enable DMA2 clock */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);  

 

  /* DMA2 Stream1 Configuration */  

  DMA_DeInit(DMA2_Stream1);

  DMA_InitStructure.DMA_Channel = DMA_Channel_1;  

  DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;   

  //DMA_InitStructure.DMA_Memory0BaseAddr = FSMC_LCD_ADDRESS;   // Dev Kit setup for 9655 transfer to LCD

  DMA_InitStructure.DMA_Memory0BaseAddr = Bank1_SRAM2_ADDR;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  //DMA_InitStructure.DMA_BufferSize = 1;                       // Dev Kit setup for 9655 transfer to LCD

  DMA_InitStructure.DMA_BufferSize =  65535; // 0x9600; //this sets the number of data itmes to transfer in NDTR register

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

 // DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;    // Dev Kit setup for 9655 transfer to LCD

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

  // DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  // Dev Kit setup for 9655 transfer to LCD

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //temp comment for test

  //DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  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(DMA2_Stream1, &DMA_InitStructure);

infoinfo989
Associate III
Posted on November 17, 2011 at 00:00

Do you have DMA2 being used for anything else, beyond the DCMI port?

stbbrad3
Associate II
Posted on November 22, 2011 at 16:55

So guys I am going to have to bring this discussion back.

Previously I was testing with with my camera binning by 4 but the resolution still set to 752x472, so I was getting 4 bytes of data per pixel and handling in firmware to remove the 3 uneeded bytes. After that point my data looked pefectly fine and my BMP test image looked great at a resolution of 188x138 (not 118 as I am adding 20 rows of whitesapce to the bottom).

I recently setup into double buffer mode and everything still works fine with the low res image. The problem lies in the high resolution image. In both situations I am receiving 354,944 bytes from the camera on the DCMI transfered by DMA. For some odd reason the high res image has a wrap from the top to bottom and it has duplicated data. I have my DMA double-buffer setup with the NDTR at 64,000, which writes 256,000 bytes to M0AR and switches to M1AR, which is offset 256,000 bytes, and writes the remainder of the data. I honestly don't see why this is necessary but if I left my old initialization structures as seen towards the top of this thread the image looked even worse with more wrapping and multiple areas of duplicate data.

I have links to each of the images below for veiwing. Note that the lower resolution image has code to add 20 rows of white space at the bottom for a future area of text.

http://i352.photobucket.com/albums/r360/stbbrad3/LowRes.jpg

http://i352.photobucket.com/albums/r360/stbbrad3/ORIG.jpg

One thing I have noticed it that data is actually writing below M0AR and M1AR... I do not think it is possible that I am getting more data then when I was doing low resolution pictures so I dont understand why data would be writting below 0x64060000 ( DCMI_IMAGE_SRAM_ADDRESS )... I have enabled the transfer complete interrupt just to se what may be putting it there and at the first time through the interrupt I have written all the way through SRAM... I am guessing maybe double buffer is a bad idea for this, but I have tried circular and get nearly the same results but I do not wrap through the SRAM.

Does anyone have any idea what might be going on?

Below is my DCMI and DMA initialization code.

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

    DCMI_DeInit ( );

   

    DCMI_InitStructure.DCMI_CaptureMode          = DCMI_CaptureMode_SnapShot;

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

   

    /* 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    = DCMI_IMAGE_SRAM_ADDRESS;   

    DMA_InitStructure.DMA_DIR                            = DMA_DIR_PeripheralToMemory;

    DMA_InitStructure.DMA_BufferSize                   = 64000;   

    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_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 + 0x3E800 ), DMA_Memory_1 );

    DMA_DoubleBufferModeCmd ( DMA2_Stream1, ENABLE );  
amin23
Associate II
Posted on November 23, 2011 at 09:05

Hi Brad,

I did a test with high resolution images, it works well, below the main difference between our codes:

/* DMA Stream Configuration */  

DMA_InitStructure.DMA_Memory0BaseAddr = 0x64000000; //SRAM base address

DMA_InitStructure.DMA_BufferSize = 0xFFFF; //64*1024 Max Buffer size

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //it is possible with FSMC

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;

DMA_Init(DMA2_Stream1, &DMA_InitStructure);

DMA_DoubleBufferModeConfig(DMA2_Stream1, 0x6403FFFC, DMA_Memory_0);

DMA_DoubleBufferModeCmd(DMA2_Stream1, ENABLE);

DMA_ITConfig(DMA2_Stream1, DMA_IT_TC , ENABLE);

stbbrad3
Associate II
Posted on November 23, 2011 at 15:06

AMSN,

Thanks for the response.

I will give it a try. I have two questions. I seen this elsewhere as well, but if you initialize the M0AR with 0x64000000, wouldn't the call to -  DMA_DoubleBufferModeConfig(DMA2_Stream1, 0x6403FFFC, DMA_Memory_0);

changes the address?  Would you not want to set M1AR there? Just kind of confusing to me. I would also like to see what you are doing in your interrupt.

Thanks,

Brad

amin23
Associate II
Posted on November 24, 2011 at 07:48

Hi Brad,

- This function configures the DMA double buffer mode (set the M1AR) and the current memory target(which memory will be the first buffer for the transactions M0AR or M1AR). look at function description in stm32f2xx_dma.c file.

- Using this configuration you should receive 524280 bytes (0xFFFF*2*4)

- In the DMA TC interrupt, you should update the M0AR and M1AR if the image size is more than 524280 bytes.