2024-01-24 05:45 PM - edited 2024-01-25 07:27 AM
Hi,
I have a board that I designed using the STM32F750Z8. It transfers data from a Himax hm01b0 image sensor via the DCMI port to USB using DMA.
This is a stripped down version of my FreeRTOS thread that initializes and reads the image sensor. I've removed parts that I feel are irrelevant.
void camera_task(void const* args)
{
camera_frame_ready_semaphore = xSemaphoreCreateBinaryStatic(&camera_frame_ready_semaphore_buffer);
// ...
// initialize image sensor power supply and clock.
// image sensor does not start sending frames yet. pclk, vsync, and hsync are inactive.
// ...
// enable DMA clock
__HAL_RCC_DMA2_CLK_ENABLE();
__HAL_RCC_DCMI_CLK_ENABLE();
osDelay(1);
// setup DCMI
#if 0
DCMI->CWSIZER = (239 << 16) | (((320 * 2) - 1) << 0); // image is 640 x 240 (this is correct.)
DCMI->CWSTRTR = ( 2 << 16) | ( 4 << 0); // 2x4 pixel border around edge.
DCMI->CR |= (1 << 2); // enable crop feature
#endif
DCMI->IER = (1 << 3);
DCMI->CR |= (1 << 14);
// setup DMA2 Stream7 to read double-buffered from DCMI data reg
dma_setup_xfer();
// enable DCMI IRQs in NVIC
HAL_NVIC_SetPriority(DCMI_IRQn, 10, 0);
HAL_NVIC_EnableIRQ(DCMI_IRQn);
// enable DCMI capture
DCMI->CR |= (1 << 0);
osDelay(1);
// ...
// Configure and enable image sensor. Now vsync, hsync, and pixclk start.
// ...
while (1) {
// wait til DMA is finished
xSemaphoreTake(camera_frame_ready_semaphore, portMAX_DELAY);
// do some light processing on the image and enqueue the data for another thread
write_request_t req = {.buf = (void*)camera_packedbuf[backbuf_idx], .len = buflen};
(xQueueSendToBack(write_request_queue, (const void*)&req, 0);
}
With this code I have no problem reading images off my board. As far as I can tell, the board design is correct and it's been assembled correctly. pixclk, hsync, and vsync are all electrically connected to the MCU (I've tested it using regular GPIOs). If they weren't I wouldn't be getting video.
But I'm having 2 issues with the DCMI peripheral.
1. No matter what I do, all of the status bits are stuck at 0 (and so no interrupts are generated).
Even though the DCMI is reading camera data (and clearly must be reading vsync and hsync), the FNE, VSYNC, and HSYNC bits in the DCMI status register are always 0.
Furthermore, all of the raw interrupt status bits are stuck at 0 (except for a single "vsync_ris" that only appears on the very first frame. I've tried re-enabling "vsync_ris" after clearing it, but that doesn't do anything). I have no idea how the DCMI peripheral is working even though none of its status bits are doing anything, but it's working!
I need vsync and hsync interrupts for my application!
2. The crop function appears to be completely broken
If I uncomment the code that enables cropping (and I also adjust the DMA size appropriately), the DCMI peripheral shows no signs of life at all. This isn't a must-have - I can crop in software - but I have no idea why this isn't working. It seems simple enough, and my code does exactly what STM32Cube would've done.
I have 2 boards that I've tested this on, and the behavior is the same as far as I can tell.
I wonder if there's some undocumented errata or setup requirements with the DCMI peripheral. It shouldn't be this hard to use, and the issues I'm running into don't make any sense.
Thanks!
- John
Solved! Go to Solution.
2024-01-25 07:43 AM - edited 2024-01-25 07:44 AM
I ended up resolving my issue this morning.
The image sensor had been configured to output a gated pixclk, meaning that its waveform looked like this:
It appears that there's some logic inside of the DCMI peripheral that assumes that pixclk toggles a few times before hsync or vsync become active. After changing the pixel clock from gated to continuous, the DCMI peripheral works as expected. Interrupts work, status bits are correct, and the cropping function works!
I couldn't find anywhere in RM0385 where this requirement is explicitly stated. It would be very helpful if ST could include this information in the next revision of RM0385.
Thanks!
2024-01-25 12:32 AM
Hello @johnmamish ,
Which camera module are you using?
Are you using Embedded (or internal) synchronization mode ?
Please note, when using the embedded synchronization mode, the DCMI does not support the compressed data (JPEG) and the crop feature.
• Only four interrupts (IT_LINE, IT_FRAME, IT_OVR, and IT_DCMI_VSYNC) can be used in hardware
synchronization mode.
• The five interrupts ((IT_LINE, IT_FRAME, IT_OVR, IT_DCMI_VSYNC and IT_ERR ) can be used in embedded synchronization mode.
I recommend you to refer to AN5020 Application note Introduction to digital camera interface (DCMI) for STM32 MCUs and precisely 8.3DCMI examples based on STM32CubeMX. This example explains how to enable the DCMI Interrupt.
Also, you to take a look to Camera example and get inspired from readme file may help you.
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-01-25 07:26 AM - edited 2024-01-25 07:26 AM
Hi Kaouthar,
I've edited my post to include this information. As you can see from the DCMI configuration setup in my code, I'm using hardware hsync and vsync. I'm using the hm01b0 image sensor, which is a sensor I've used before. (I know it doesn't make a lot of sense to use a < 1mW sensor with a > 100mW MCU, but this is a deliberate choice for this project).
Before posting here, I already saw all the resources you posted, but they weren't helpful. Thanks though!
2024-01-25 07:43 AM - edited 2024-01-25 07:44 AM
I ended up resolving my issue this morning.
The image sensor had been configured to output a gated pixclk, meaning that its waveform looked like this:
It appears that there's some logic inside of the DCMI peripheral that assumes that pixclk toggles a few times before hsync or vsync become active. After changing the pixel clock from gated to continuous, the DCMI peripheral works as expected. Interrupts work, status bits are correct, and the cropping function works!
I couldn't find anywhere in RM0385 where this requirement is explicitly stated. It would be very helpful if ST could include this information in the next revision of RM0385.
Thanks!
2024-02-01 06:27 AM
Hello @johnmamish ,
Glad to know that the issue is solved and thank you for sharing the solution :).
What do you mean by "changing the pixel clock from gated to continuous"?
The DCMI is a slave and doesn't stat work only if DCMI_VSYNC and DCMI_HSYNC signals are coming.
Also as shown in AN5020, if the DCMI_PIXCLK start before the DCMI_VSYNCH and DCMI_HSYNCK the DATA are blanking.
Thank you for your contribution in STCommunity.
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.