AnsweredAssumed Answered

DCMI and DMA interrupts with phenomena

Question asked by berger.patrick on Nov 23, 2013
Latest reply on Nov 23, 2013 by berger.patrick
I'm now trying to receive an image from my OV9655 over the DCMI port and send it then to the pc. With low resolution (160x120 pixel) and saving the image in the ram it worked good. Now I want to geht higher resolution so I've to stream the ram buffer, because there isn't enough space on the STM32F407.
I modified my source code for streaming multiple lines at low resolution. But with the DMA TC and HC interrupts enabled, there are some special bugs:
- I need the full image buffer (160x120) and not the programmed buffer size at the dma init
- The hole buffer is filled with data, and not only the half part

I set up my code to get the image in 4 parts. espected buffer size is 160*60 because I use HC and TC interrupts. But if I set the buffer to "uint16_t DCMI_Buffer[160*60]" the cpu goes to a hard_fault handler.

And the code below gets me the full image:

Init DCMI and DMA:
volatile uint16_t DCMI_Buffer[160 * 120] = {0};
 
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
 
// Reinitialize
DCMI_DeInit();
 
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_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);
 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
 
/* DMA2 Stream1 Configuration */
DMA_Cmd(DMA2_Stream1, DISABLE);
DMA_DeInit(DMA2_Stream1);
while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE);              // Check if the DMA Stream is disabled before enabling it.
 
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DCMI_Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize =  (160 * 60);
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_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);
 
DMA_ITConfig(DMA2_Stream1, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA2_Stream1, DMA_IT_HT, ENABLE);
 
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

Interrup:
void DMA2_Stream1_IRQHandler(void){
    if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_HTIF1) != RESET){
        line += 30;
        if(line > 120){
            line = 0;
        }
        DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_HTIF1);
    }
 
    if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1) != RESET){
        line += 30;
        if(line > 120){
            line = 0;
        }
        DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
    }
}

Main:
if(start_image == 1){
    if(line != sended_lines){
 
        uint32_t start = 160 * sended_lines;
        uint32_t stop = 160 * (30 + sended_lines);
        for(i = start; i < stop; i ++){
            uint16_t temp = DCMI_Buffer[i] >> 8;
            VCP_put_char((uint8_t) temp);
            VCP_put_char((uint8_t)DCMI_Buffer[i]);
 
            if((i % 160) == 0){
                Delay_ms(1);
            }
        }
        sended_lines = line;
    }
}
if(sended_lines == 120) while(1);

So why the hell is the dma writing to DCMI_Buffer[9600] - DCMI_Buffer[19199]?
What is my fault?
I tested also other configuartions: Buffer size to 30, but ther were also parts repeated (and I've always to save the double in ram as I programmed the dma size).

Thank you for helping me. If I can't found a solution I've to manage this with an fpga.
Best regards and thank you
Patrick

Outcomes