AnsweredAssumed Answered

STM32F407 DCMI DMA doesn't seem to fill the right memory

Question asked by crump.philip.001 on Apr 10, 2015
Hi,

I'm trying to copy JPEG data out of an OV2640 Camera using the DCMI interface on the STM32F407, currently using the STM32F4 Discovery Board. I have used code from the STM32 1.1.0 Peripheral Example.

I've verified that the OV2640 is responding correctly to the SCCB. When configured it outputs the data (which looks random enough to be legitimate) with the expected Pixel Clock, VSYNC and HSYNC signals, verified with a logic analyzer.

I set up interrupts for the DCMI vsync, line, frame, error and overflow. The vsync, line and frame interrupts arrived as expected.

I set up interrupts for the DMA Transfer Error, FIFO Error, Direct Mode Error and Transfer Complete. The Transfer Complete interrupt arrives following the DCMI frame interrupt, and I am now using it to trigger the read-out of the Buffer following the image capture.

However the buffer when I read it out is full of 0x00. Assigning a value into the start of the buffer at MCU boot is not overwritten, despite many 'Transfer Complete' Interrupts.

The problem appears to be that the DMA is successfully writing to a piece of memory different to where I want it to?

Relevant Code is below, let me know if more is needed:

001./* GPIO Setup */
002. 
003.void Camera_HW_Init(void)
004.{
005.  GPIO_InitTypeDef GPIO_InitStructure;
006.  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
007.  TIM_OCInitTypeDef TIM_OCInitStructure;
008.  I2C_InitTypeDef  I2C_InitStruct;
009. 
010.  /*** Configures the DCMI GPIOs to interface with the OV2640 camera module ***/
011.  /* Enable DCMI GPIOs clocks */
012.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
013.                         RCC_AHB1Periph_GPIOC, ENABLE);
014. 
015.  /* Connect DCMI pins to AF13 */
016.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);
017.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI);
018.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_DCMI);
019.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_DCMI);
020.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_DCMI);
021.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_DCMI);
022.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_DCMI);
023. 
024.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
025.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);
026.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_DCMI);
027.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_DCMI);
028.   
029.  GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);
030.  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);
031.   
032.  /* DCMI GPIO configuration */
033.  /* PORTC */
034.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 |
035.                                GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
036.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
037.  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
038.  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
039.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
040.  GPIO_Init(GPIOC, &GPIO_InitStructure);
041. 
042.  /* PORTB */
043.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
044.  GPIO_Init(GPIOB, &GPIO_InitStructure);
045.   
046.  /* PORTA */
047.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6;
048.  GPIO_Init(GPIOA, &GPIO_InitStructure);
049. 
050.  /* XCLK(PB4) */
051.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
052.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
053.  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
054.  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
055.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
056.  GPIO_Init(GPIOB, &GPIO_InitStructure);
057.   
058.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
059.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_TIM3);
060.   
061.  /* Set up PWM for XCLK(PB4) */
062.  TIM_TimeBaseStructure.TIM_Prescaler = 0; // 72 to 1 MHz
063.  TIM_TimeBaseStructure.TIM_Period = 3;
064.  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
065.  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
066.  
067.  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
068.  
069.  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
070.  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
071.  TIM_OCInitStructure.TIM_Pulse = 2;
072.  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
073.  
074.  TIM_OC1Init(TIM3, &TIM_OCInitStructure);
075.  
076.  TIM_Cmd(TIM3, ENABLE);
077. 
078.  /****** Configures the I2C2 used for OV2640 camera module configuration *****/
079. 
080.  /* GPIOB clock enable */
081.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
082.   
083.  /* Configure I2C2 GPIOs */ 
084.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
085.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
086.  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
087.  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
088.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
089.  GPIO_Init(GPIOB, &GPIO_InitStructure);
090. 
091.  /* Connect I2C2 pins to AF4 */
092.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2);
093.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2);
094.   
095. /* I2C2 clock enable */
096.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
097. 
098.  /* I2C DeInit */
099.  I2C_DeInit(I2C2);
100.     
101.  
102.  /* Set the I2C structure parameters */
103.  I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
104.  I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
105.  I2C_InitStruct.I2C_OwnAddress1 = 0x30; //0xFE;
106.  I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;//Enable;
107.  I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
108.  I2C_InitStruct.I2C_ClockSpeed = 100000;
109.   
110.  /* Initialize the I2C peripheral w/ selected parameters */
111.  I2C_Init(I2C2, &I2C_InitStruct);
112.   
113.  /* Enable the I2C peripheral */
114.  I2C_Cmd(I2C2, ENABLE);
115.   
116.}
117. 
118./* DMA Setup */
119. 
120.static uint32_t dcmi_image_buffer[10000];
121. 
122.void Camera_DMA_Init(ImageFormat_TypeDef ImageFormat)
123.{
124.  DCMI_InitTypeDef DCMI_InitStructure;
125.  DMA_InitTypeDef  DMA_InitStructure;
126.  NVIC_InitTypeDef NVIC_InitStructure;
127. 
128.  /*** Configures the DCMI to interface with the OV2640 camera module ***/
129.  /* Enable DCMI clock */
130.  RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
131. 
132.  /* DCMI configuration */
133.  DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot;
134.  DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
135.  DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
136.  DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_Low;
137.  DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
138.  DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
139.  DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
140.   
141.  /* DCMI configuration */
142.  DCMI_Init(&DCMI_InitStructure);
143.   
144.  DCMI_JPEGCmd(ENABLE);
145.  /*
146.  DCMI_ITConfig(DCMI_IT_VSYNC, ENABLE);
147.  DCMI_ITConfig(DCMI_IT_LINE, ENABLE);
148.  DCMI_ITConfig(DCMI_IT_FRAME, ENABLE);
149.  DCMI_ITConfig(DCMI_IT_ERR, ENABLE);
150.  DCMI_ITConfig(DCMI_IT_OVF, ENABLE);
151.   
152.  DCMI_ClearFlag(DCMI_FLAG_VSYNCRI);
153.    DCMI_ClearFlag(DCMI_FLAG_LINERI);
154.    DCMI_ClearFlag(DCMI_FLAG_FRAMERI);
155.    DCMI_ClearFlag(DCMI_FLAG_ERRRI);
156.    DCMI_ClearFlag(DCMI_FLAG_OVFRI);
157.        
158.  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
159.  NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
160.  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
161.  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
162.  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
163.  NVIC_Init(&NVIC_InitStructure);
164.  */
165. 
166.  /* Configures the DMA2 to transfer Data from DCMI */
167.  /* Enable DMA2 clock */
168.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
169.   
170. 
171.  /* DMA2 disable */
172.  DMA_Cmd(DMA2_Stream1, DISABLE);
173.  DMA_ClearFlag(DMA2_Stream1, DMA_FLAG_FEIF1 | DMA_FLAG_DMEIF1 | DMA_FLAG_TEIF1 | DMA_FLAG_HTIF1 | DMA_FLAG_TCIF1);
174.   
175.  /* DMA2 Stream1 Configuration */ 
176.  DMA_DeInit(DMA2_Stream1);
177. 
178.  DMA_InitStructure.DMA_Channel = DMA_Channel_1;
179.  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DCMI_DR_ADDRESS;
180.  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&dcmi_image_buffer[0];
181.  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
182.  DMA_InitStructure.DMA_BufferSize = IMAGE_BUFFER_SIZE;
183.  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
184.  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
185.  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
186.  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
187.  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
188.  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
189.  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;//Enable;
190.  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
191.  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
192.  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
193. 
194.  /* DMA2 IRQ channel Configuration */
195.  DMA_Init(DMA2_Stream1, &DMA_InitStructure);
196.   
197.  //DMA_ITConfig(DMA2_Stream1, DMA_IT_HT | DMA_IT_TC | DMA_IT_TE, ENABLE);
198.  DMA_ITConfig(DMA2_Stream1, DMA_IT_TC, ENABLE);
199.   
200.  /* Configure and enable DMA interrupt */
201.  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
202.  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
203.  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
204.  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
205.  NVIC_Init(&NVIC_InitStructure);
206.}

The following function is called to capture an image:

01.void Camera_TakePic(ImageFormat_TypeDef ImageFormat)
02.{
03.    Camera_HW_Init();
04.    Camera_DMA_Init(ImageFormat);
05.    OV2640_JPEGConfig(ImageFormat);
06.     
07.    DMA_Cmd(DMA2_Stream1, ENABLE);
08.    DCMI_Cmd(ENABLE);   
09.     
10.    _delay_ms(200);
11.    DCMI_CaptureCmd(ENABLE);
12.}

I am lost as to what more I can do to debug this, any help is greatly appreciated.

Thanks,
Phil

Outcomes