2011-11-07 08:23 AM
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, Brad2011-11-07 05:00 PM
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 mode2011-11-08 08:24 AM
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, Brad2011-11-08 09:11 AM
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.2011-11-08 11:59 AM
2011-11-09 05:01 PM
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, Brad2011-11-09 06:18 PM
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, Mike2011-11-09 10:09 PM
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.2011-11-10 09:00 AM
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, Brad2011-11-10 10:41 AM
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 ); }