2015-03-06 05:25 AM
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 9600uint32_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 isvoid 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-ov76702015-03-06 07:47 AM
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.2015-03-07 11:02 AM
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.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); }2015-03-10 06:10 PM
2015-03-10 06:21 PM
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.2015-03-10 06:32 PM