cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f407 + SDIO Fat Fs multiBlock write error with ov7670

scholar
Associate II
Posted on March 06, 2015 at 14:25

i am using stm32f407 with fatfs to store vedio frames in sd card. i am capturing QQVGA YUV frames from camera to write it to sd card, i tested to write continuously in sd card with using soft flag in frame intterupt and writing data in main file using f_write function when i write continuosly it outputs 0kb data so i have to open and close file, i use user button to unmount file system, but when i do this i get true data only for some lines and random data in between frames, following is my code and intterupt routines, i stop the dcmi and dma till bytes of data are transferred then i start them again to make sure that complete frame is captured into sd card, i tried to write some fixed data in sd card with intterupts enabled but still i got random data, i am using class 10 scandisk micro sd card and i am using library with modified write functions provided by clive, 

int number=0;

int count=0;

int stop = 0;

&sharpdefine size 9600

uint32_t buffer[size]; 

int main(void)

{

NVIC_Configuration();

EXTILine0_Config();

init_GPIO();

MCO1_Init();  

Delay_ms(10);

DCMI_OV7670_Init();

f_mount(0, &filesystem);

f_open(&file, ''DATA.YUV'', FA_READ | FA_WRITE | FA_CREATE_ALWAYS);

GPIOD->BSRRL = 0x1000; // this sets LED1 (green)  0x2000 0x4000 0x8000

f_close(&file);

  DMA_Cmd(DMA2_Stream1, ENABLE);

  DCMI_Cmd(ENABLE); 

  DCMI_CaptureCmd(ENABLE);

f_open(&file, ''DATA.YUV'', FA_WRITE | FA_OPEN_ALWAYS);

while(1){

if((number ==  count) && (!stop))

{

number++;

DMA_Cmd(DMA2_Stream1, DISABLE);

DCMI_Cmd(DISABLE); 

DCMI_CaptureCmd(DISABLE);

f_lseek(&file, file.fsize);

f_write(&file, &buffer[0] , size*4, &bw);

if (bw<(size*4)) while(1);

DMA_Cmd(DMA2_Stream1, ENABLE);

DCMI_Cmd(ENABLE); 

DCMI_CaptureCmd(ENABLE);

}

}

}

and interrupt routine is

void EXTI0_IRQHandler(void)

{

  if(EXTI_GetITStatus(EXTI_Line0) != RESET)

  {

DMA_Cmd(DMA2_Stream1, DISABLE);

DCMI_Cmd(DISABLE);

DCMI_CaptureCmd(DISABLE);

f_close(&file);

if (f_mount(0, NULL) != FR_OK) {

printf(''could not close filesystem \n\r'');

}

GPIOD->BSRRH = 0x1000;

GPIOD->BSRRL = 0x2000;

stop = 1;

    /* Clear the EXTI line 0 pending bit */

    EXTI_ClearITPendingBit(EXTI_Line0);

  }

}

void DCMI_IRQHandler(void)

{     

if (DCMI_GetITStatus(DCMI_IT_FRAME) != RESET) 

{

count++;

DCMI_ClearITPendingBit(DCMI_IT_FRAME); 

}

}

and following is my dma setting

  DMA_InitStructure.DMA_Channel = DMA_Channel_1;  

  DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;

  DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)&buffer[0];//&buffer[0]; //FSMC_LCD_ADDRESS;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

// row * columns * bytes per pixal devided by 4

  DMA_InitStructure.DMA_BufferSize = size; // 160 * 120  / 4*4;  unit depends on unit used in memory data size

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //DMA_MemoryInc_Disable;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //DMA_MemoryDataSize_HalfWord;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //for video DMA_Mode_Circular;

  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;//DMA_FIFOMode_Enable;         

  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 

  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 

any help will be greatly appreciated

#stm32f4-sdio-fatfs-ov7670
5 REPLIES 5
Posted on March 06, 2015 at 16:47

I think this is a bit ugly.

The biggest issue I can see is that you don't use a ping-pong buffer arrangement so you write a non-active portion of the DMA buffer.

I would also lose the f_seek, and not do anything with the file system under interrupt.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
hitsumen
Associate II
Posted on March 07, 2015 at 20:02

Hi,

I am abit off from those stuff, but i can post you my old settings.

I used those to put data from ov5642 directly to

http://www.ebay.com/itm/7-inch-TFT-LCD-module-800x480-SSD1963-w-touchpad-PWM-arduino-AVR-STM32-ARM-/121017488870?pt=LH_DefaultDomain_0&hash=item1c2d3455e6

.

void DCMI_Config(void)

{

  DCMI_InitTypeDef DCMI_InitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

  DMA_InitTypeDef  DMA_InitStructure;

  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable DCMI GPIOs clocks */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE | 

                         RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE); 

  /* Enable DCMI clock */

  RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);

  /* Connect DCMI pins to AF13 ************************************************/

  /* PCLK */

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);

  /* D0-D7 */

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI);

  GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI);

  GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI);

  GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI);

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);

  GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI);

  GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI);

  /* VSYNC */

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);

  /* HSYNC */

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);

  

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

  /* D0 D1(PC6/7) */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;  

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* D2..D4(PE0/1/4) D6/D7(PE5/6) */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 

                              | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;

  GPIO_Init(GPIOE, &GPIO_InitStructure);

  /* D5(PB6), VSYNC(PB7) */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* PCLK(PA6) HSYNC(PA4)*/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  

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

  DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;

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

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

  NVIC_Init(&NVIC_InitStructure); 

//----- mask interrupt for DCMI -----

  DCMI_ITConfig(DCMI_IT_VSYNC, ENABLE);

  DCMI_ITConfig(DCMI_IT_LINE, ENABLE);

  DCMI_ITConfig(DCMI_IT_FRAME, ENABLE);

  DCMI_ITConfig(DCMI_IT_OVF, ENABLE);

  DCMI_ITConfig(DCMI_IT_ERR, ENABLE);

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

//DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&output;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  DMA_InitStructure.DMA_BufferSize = 38400;

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//was DMA_MemoryInc_Disable

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

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

/* Configure the Priority Group to 2 bits */

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

/* Enable the UART3 RX DMA Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

DMA_ITConfig(DMA2_Stream1, DMA_IT_TC, ENABLE);

}

scholar
Associate II
Posted on March 11, 2015 at 02:10

will you please tell me something more about using two buffers in parallel??

Posted on March 11, 2015 at 02:21

will you please tell me something more about using two buffers in parallel??

Not sure parallel is the right term. It can be a single buffer, of double the size, and you can have the DMA interrupt at the HT (Half Transfer) when the first half is filled, and at TC (Transfer Complete) when the second half is filled. In circular mode after the TC it will swing around and start filling the first half again. 

At the HT you signal that it can write the first half of the buffer while the DMA continues to fill the second half. You need to get the data written more quickly than the DMA is filling the other buffer.

Classically this is termed a Ping-Pong buffer, and it goes back-and-forth. It's regularly used for audio applications, or video frames.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
scholar
Associate II
Posted on March 11, 2015 at 02:32

thanks for nice suggestion i will definately check it