cancel
Showing results for 
Search instead for 
Did you mean: 

DCMI and DMA interrupts with phenomena

pa
Associate II
Posted on November 23, 2013 at 18:50

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 STM32F4

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
4 REPLIES 4
Posted on November 23, 2013 at 20:13

So why the hell is the dma writing to DCMI_Buffer[9600] - DCMI_Buffer[19199]?

Hard Faults are CPU side issues, not DMA unless it's trashing context. Honestly your fault here seems like the start/sended<sic> stuff is massively violating the scope of the buffer. ie 160 * (120 + 30) !!

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
pa
Associate II
Posted on November 23, 2013 at 20:45

No, the code above works fine, but why?

this results in a hard fault:

volatile
uint16_t DCMI_Buffer[160*60];
DMA_InitStructure.DMA_BufferSize = (160 * 60);

And this works:

volatile
uint16_t DCMI_Buffer[160*120];
DMA_InitStructure.DMA_BufferSize = (160 * 60);

BUT the image is in the full array: DCMI_Buffer[0] is the first pixel and DCMI_Buffer[19199] is the last. But 160*60=9600 and not 19200?!? I expect that place 9600 to 19199 are 0, but this isn't the case. And the problem is, that the hardfault results ONLY when the dma interrupts are ENABLED.
Posted on November 23, 2013 at 20:59

And the problem is, that the hardfault results ONLY when the dma interrupts are ENABLED.

 

No kidding, and that's when you're incrementing the lines variable, right? Try not doing that and see if it still fails.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
pa
Associate II
Posted on November 23, 2013 at 21:22

This gets also a Hardfault:

volatile
uint16_t DCMI_Buffer[160 * 60] = {0};
volatile
uint32_t line = 0;
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);
}
}
int
main(
void
){
if
(DCMI_OV9655Config()){
DMA_Cmd(DMA2_Stream1, ENABLE);
DCMI_Cmd(ENABLE);
Delay_ms(100);
DCMI_CaptureCmd(ENABLE);
}
USBD_Init(&USB_OTG_dev, 
// OTG core handle
USB_OTG_FS_CORE_ID, 
// OTG core id
&USR_desc, 
// USB descriptors
&USBD_CDC_cb, 
// CDC callback
&USR_cb); 
// User callback
Delay_ms(5000);
while
(1){
if
(gbUsbDeviceStatus == gbUsbDevice_Configured) 
// Check if the usb connection is ready
{
VCP_send_str(
''hallo
''
);
Delay_ms(200);
}
};
reutrn 0;
}

So, the interrupts are the problem. BUT something else: If I comment the USBD_Init, the hard fault doesn't occours. So are there something special things with the usb modul and the dma modul?