AnsweredAssumed Answered

STM32F4 DCMI Getting Wrong and Duplicated Bytes

Question asked by Hopkins Kong on Oct 11, 2017

Hi,

 

I am using the DCMI peripheral along with DMA2 Channel 1 Stream 7, with OV2640 in JPEG mode connected to I2C2 and DCMI of my STM32F4DISCOVERY board.

 

/* Includes */
#include "stm32f4xx.h"
#include "util.h"
#include "OV2640.h"

#include <stdio.h>

uint32_t DMA_DESTINATION[30720];

void initRCC(void) {
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
if(RCC_WaitForHSEStartUp() == ERROR) {
while(1);
}
RCC_PLLConfig(RCC_PLLSource_HSE, 4, 336, 4, 14); // 8 / 4 * 336 / 4 (USB / 14) [168MHz, USB=48MHz]
RCC_PLLCmd(ENABLE);

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // System clock (SYSCLK)
RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB clock (HCLK)
RCC_PCLK1Config(RCC_HCLK_Div1); // Low Speed APB clock (PCLK1)
RCC_PCLK2Config(RCC_HCLK_Div1); // High Speed APB clock (PCLK2)

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_DMA2, ENABLE);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI | RCC_AHB2Periph_OTG_FS, ENABLE);
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_TIM9, ENABLE);
}

void initGPIO(void) {
GPIO_InitTypeDef GPIO_InitStruct;

// Port A Alternate Functions Configurations
// PA4=CAMERA_HREF; PA6=CAMERA_PCLK; PA9=USB_VBUS; PA10=USB_ID; PA11=USB_DM; PA12=USB_DP;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_OTG_FS);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_OTG_FS);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_OTG_FS);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_OTG_FS);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);

// Port A Output GPIO Configurations
// PA15=SPI_CS;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);

 

// Port B Alternate Functions Configurations
// PB3=SPI1_SCK; PB4=SPI1_MISO; PB5=SPI1_MOSI; PB6=CAMERA_D5; PB7=CAMERA_VSYNC; PB8=CAMERA_D6; PB9=CAMERA_D7; PB10=CAMERA_I2C_SCL; PB11=CAMERA_I2C_SDA;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);

// Port B Output GPIO Configurations
// PB12=CAMERA_RESET;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);

 

// Port C Alternate Functions Configurations
// PC6=CAMERA_D0; PC7=CAMERA_D1; PC8=CAMERA_D2; PC9=CAMERA_D3; PC11=CAMERA_D4;
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_DCMI);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_11;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);


// Port E PE5 for XCLK
GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_TIM9); 
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOE, &GPIO_InitStruct);
}


void initI2C(void) {
I2C_InitTypeDef I2C_InitStruct;

I2C_DeInit(I2C2);
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0xFE;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_ClockSpeed = (8*100);

I2C_Cmd(I2C2, ENABLE);
I2C_Init(I2C2, &I2C_InitStruct);
}

void initDCMI(void) {
DCMI_InitTypeDef DCMI_InitStruct;

DCMI_DeInit();
DCMI_InitStruct.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot;
DCMI_InitStruct.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStruct.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
DCMI_InitStruct.DCMI_HSPolarity = DCMI_HSPolarity_High;
DCMI_InitStruct.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStruct.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStruct.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
DCMI_ITConfig(DCMI_IT_FRAME, ENABLE);

DCMI_Init(&DCMI_InitStruct);

}

void initDMA(void) {
DMA_InitTypeDef DMA_InitStruct;

DMA_DeInit(DMA2_Stream7);
DMA_InitStruct.DMA_Channel = DMA_Channel_1;
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)(&DCMI->DR);
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)DMA_DESTINATION;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStruct.DMA_BufferSize = 10720;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA2_Stream7, &DMA_InitStruct);
DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);

DCMI_JPEGCmd(ENABLE);
DMA_Cmd(DMA2_Stream7, ENABLE);
DCMI_Cmd(ENABLE);
}

void initTIM(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Prescaler = 0; 
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 3; 
TIM_TimeBaseInitStruct.TIM_Period = 7;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM9, &TIM_TimeBaseInitStruct);
TIM_Cmd(TIM9, ENABLE);
}

void initPWM(void) {
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStruct.TIM_Pulse = 3; 
TIM_OC1Init(TIM9, &TIM_OCInitStruct);
TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable);
}

void initNVIC(void) {
NVIC_InitTypeDef NVIC_InitStruct;

NVIC_InitStruct.NVIC_IRQChannel = DMA2_Stream7_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);

NVIC_InitStruct.NVIC_IRQChannel = DCMI_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}

int main(void) {
uint8_t pid, ver, midl, midh;
framesize_t ov2640_fs = FRAMESIZE_SVGA;
pixelformat_t ov2640_fmt = PIXELFORMAT_JPEG;
int i=0;
initRCC();
initGPIO();
initI2C();
initTIM();
initPWM();
initNVIC();

OV2640HWReset();
printf("Probing OV2640...\n");
printf("Trying on I2C address 0x%x...\n", OV2640_I2C_WRITE_ADDR);
OV2640ReadID(&pid, &ver, &midl, &midh);
printf("PID=0x%x VER=0x%x MIDL=0x%x MIDH=0x%x\n", pid, ver, midl, midh);
if(pid == 0x26) {
printf("OV2640 found.\n");
}else{
printf("OV2640 not found, probe failed.\n");
return -1;
}
printf("SW Reset...\n");
OV2640SWReset();
printf("SW Reset Done.\n");
printf("Setting frame size...\n");
OV2640SetFrameSize(ov2640_fs);
printf("Setting pixel format...\n");
OV2640SetPixelFormat(ov2640_fmt);
printf("Configuration completed: %dx%d fmt=%d\n", resolutions[ov2640_fs][0], resolutions[ov2640_fs][1], ov2640_fmt);
initDCMI();
initDMA();
printf("Snapshot...\n");
for(i=0; i<30720; i++) {
DMA_DESTINATION[i]=0x00000000; // clear the buffer
}
DCMI_CaptureCmd(ENABLE); // Setting breakpoint at the ISR of DCMI Frame Done Event, and viewing memory and register contents

while(1);
}

 

 

The camera setup process is fine, however, I always get the same 32-bit word which consist the same random byte at my destination. While debugging the DCMI DR register, it was found that the received byte does not change, and it appears to be random. As DCMI will pack 4 bytes (i.e 4 PIXCLK Cycles) to a 32-bit word then signal DMA2, the data at the destination memory address are all the same byte (and same 32-bit word).

 

Is there any issue in my DCMI/DMA setup sequence? I suspect it is more likely the issue of the DCMI as it always received the same byte and the DMA was working fine by transferring the exactly same (duplicated) data to the destination memory address.

 

Thanks.

Outcomes