Skip to content

Conversation

KurtE
Copy link
Contributor

@KurtE KurtE commented Jul 29, 2025

Added support to video_stm32_dcmi for the new
set and get selection. These implementations simply forward the message to the underlying
camera object if they support these messages.

Also added support for a snapshot mode instead of
always using continuous capture mode. Tried
to make it semi-transparent when you desire it to be

The stm32_dcmi code now also allows you to work
with only one buffer. This will force it into snap shot mode. There is also new calls added to the api for: video_get_snapshot_mode and video_set_snapshot_mode.

That allows you to set it with more than one buffer and query what mode you are in.

GC2145 was updated first to try out these changes. The camera now allows me to follow the call order
that @josuah mentioned in another pr/issue.

With this driver I also updated it to allow more or less any video resolution:
{
.pixelformat = format, .width_min = width_l, .width_max = width_h,
.height_min = height_l, .height_max = height_h, .width_step = 0, .height_step = 0,
}

static const struct video_format_cap fmts[] = {
	GC2145_VIDEO_FORMAT_CAP_HL(128, 1600, 128, 1200, VIDEO_PIX_FMT_RGB565),
	GC2145_VIDEO_FORMAT_CAP_HL(128, 1600, 128, 1200, VIDEO_PIX_FMT_YUYV),

When resolution is set, it computes the scale factor. If you then later call set_crop, the same code is
used except it uses the ratios computed from the set_resolution.

With these changes: I was able to setup a test app, for the Arduino Nicla vision and send out a 480x320 image over USB.

More to come

Note: this is a replacement for #91975

My current test sketch/app is up at:
https://github.com/KurtE/zephyr_test_sketches/tree/master/camera_capture_to_usb
built using:

west build -p -b arduino_nicla_vision//m7
west flash

I am using the Arducam viewer with this on my PC. I am using the one at:
https://github.com/mjs513/Teensy_Camera/tree/main/extras/host_app

Picture using GC2145 on Arduino Nicla Vision shown on Arducam mini viewer.
image

Edit: current summary of changes:
There are several changes some of which will likely change if/when code reviews happen. Things like:
a) The stm_dcmi driver handles the get/set selection APIs and if the camera has also implemented these APIs, it
forwards the messages to them, else return error not implemented.

a1) GC2145 camera implements them.

b) Currently I allow arbitrary size of the frame GC2145, that is I have one fmt (per RGB...) which sets min and max versus the
ones where it current code which has 3 arbitrary sizes (1600x1200 - ratio 1, 640x480 ratio 2, 320x240 ratio 3). I instead
compute ratio and allow you to choose for example 800x600 which is less arbitrary than the 640x480... Note 320x240
computes ratio=5, except I currently limit to max ratio=3 per seeing other implementations that do so... Maybe should
make that max configurable.

c) Setting to allow the code to run in SNAPSHOT mode, which starts the camera, waits for one frame to come back and then deactivates.

This is the way that Arduino library works at least on MBED. Note snapshot mode also has some ability to recover from
failures...

d) Allow you to configure to only have one buffer, before it required at least two, If set to 1, it set forces SNAPSHOT mode.

With this running on Zephyr, I for example was able to program a Nicla Vision, which has no SDRAM and output at
480x320 over USB to an Arducam viewer. My test sketch (not sure what to call them on Zephyr)
is up at https://github.com/KurtE/zephyr_test_sketches/tree/master/camera_capture_to_usb

Also have others that output to Portenta H7 to an ST7796 display...

@KurtE KurtE force-pushed the camera_snapshot branch 13 times, most recently from 558b218 to aa416e3 Compare July 30, 2025 13:58
@KurtE
Copy link
Contributor Author

KurtE commented Jul 30, 2025

@josuah @mjs513 @dkalowsk @iabdalkader and all:

As @josuah mentioned in my previous PR:
#91975 (comment)
Which I closed as per his earlier comments about using the new set/get selection video stuff.

This might make more sense when considering there is only one particular order users are expected to follow:

  1. Set the format with video_set_format()
  2. Set the cropping region with video_set_selection(dev, VIDEO_SET_TGT_CROP)
  3. Set the scaling parameter with video_set_selection(dev, VIDEO_SET_TGT_COMPOSE)
    Every step reset the values of what is below it: "select the native size, remove margins, and scale it up/down" always in this order.

Which makes sense: But now wondering about a few details. In my own test case app I have:

	LOG_INF("- Video format: %s %ux%u",
		VIDEO_FOURCC_TO_STR(fmt.pixelformat), fmt.width, fmt.height);

	if (video_set_format(video_dev, &fmt)) {
		LOG_ERR("Unable to set format");
		return 0;
	}

#if CONFIG_VIDEO_FRAME_HEIGHT || CONFIG_VIDEO_FRAME_WIDTH
#if CONFIG_VIDEO_FRAME_HEIGHT
	fmt.height = CONFIG_VIDEO_FRAME_HEIGHT;
#endif

#if CONFIG_VIDEO_FRAME_WIDTH
	fmt.width = CONFIG_VIDEO_FRAME_WIDTH;
#endif
#endif	

	/* First set the format which has the size of the frame defined */
	LOG_INF("video_set_format: %u %u", fmt.width, fmt.height);
	if (video_set_format(video_dev, &fmt)) {
		LOG_ERR("Unable to set format");
		return 0;
	}

	/* initialize the bsize to the size of the frame */
	bsize = fmt.width * fmt.height * 2;
	/* Set the crop setting if necessary */
#if CONFIG_VIDEO_SOURCE_CROP_WIDTH && CONFIG_VIDEO_SOURCE_CROP_HEIGHT
	sel.target = VIDEO_SEL_TGT_CROP;
	sel.rect.left = CONFIG_VIDEO_SOURCE_CROP_LEFT;
	sel.rect.top = CONFIG_VIDEO_SOURCE_CROP_TOP;
	sel.rect.width = CONFIG_VIDEO_SOURCE_CROP_WIDTH;
	sel.rect.height = CONFIG_VIDEO_SOURCE_CROP_HEIGHT;
	LOG_INF("video_set_selection: VIDEO_SEL_TGT_CROP(%u, %u, %u, %u)", 
			sel.rect.left, sel.rect.top, sel.rect.width, sel.rect.height);
	if (video_set_selection(video_dev, &sel)) {
		LOG_ERR("Unable to set selection crop  (%u,%u)/%ux%u",
			sel.rect.left, sel.rect.top, sel.rect.width, sel.rect.height);
		return 0;
	}
	LOG_INF("Selection crop set to (%u,%u)/%ux%u",
		sel.rect.left, sel.rect.top, sel.rect.width, sel.rect.height);
	bsize = sel.rect.width * sel.rect.height * 2;
#endif

	if (video_get_format(video_dev, &fmt)) {
		LOG_ERR("Unable to retrieve video format");
		return 0;
	}
	LOG_INF("video_get_format: ret fmt:%u w:%u h:%u pitch:%u",fmt.pixelformat, fmt.width, fmt.height, fmt.pitch);

And the CONF file has:

CONFIG_VIDEO_FRAME_WIDTH=800
CONFIG_VIDEO_FRAME_HEIGHT=600
CONFIG_VIDEO_SOURCE_CROP_WIDTH=480
CONFIG_VIDEO_SOURCE_CROP_HEIGHT=320

But if I was not using my updated fmts, which allows more resolutions, I would have done FRAME_WIDTH=640 and HEIGHT=480

So now assume:

CONFIG_VIDEO_FRAME_WIDTH=640
CONFIG_VIDEO_FRAME_HEIGHT=480

With this, the call to video_set_format would have a width=640 and height= 480
Which internally sets the ratio (scaling to 2) and crop to 640x480.

Note: If you now (first commit) call video_get_selection with VIDEO_SEL_TGT_NATIVE_SIZE, it will return 800x600

So now to do step 2) to crop it to 480x320 - Currently I ignore the passed in top and left in the crop rectangle, but that
is what I wish to update in the next commit, The current code sets the crop rectangle top=0, left=0. However internally
it actually sets the crop to (80,60, 640, 480) to center the image in the sensor.

So with this setup, I would expect on the TGT_CROP that I should be able to pass in rectangles in the range:
(0, 0, 480, 320) - Upper left area of sensor. to
(159, 139, 480, 320) - lower right (not sure about if 159 or 160...)
Which would allow you to pan over the entire sensor...

But in this case: should step 1) have set the top=0, left=0 or should it instead of set it to 80,60?
Should the sketch calling the setting the TGT_CROP compute this themself, that is currently if you set it to 0, 0
it would be at one end of the sensor? Should there be a default value?

Thanks
Kurt

@KurtE
Copy link
Contributor Author

KurtE commented Jul 30, 2025

Having problems with this PR first commit on getting signoff to be accepted:

I actually copy/pasted the signoff line from previous PRS which worked then but not on this one?

Signed-off-by: Kurt Eckhardt <kurte@rockisland.com>
I tried using:
Signed-off-by: Kurt E <kurte@rockisland.com>
which I had changed my profile to have: Kurt E instead of KurtE for profile name...
I tried what: git commit -s added:
`Signed-off-by: KurtE kurte@rockisland.com

All of which failed like:

  -- Run compliance checks on patch series (PR): Identity.txt#L0See https://docs.zephyrproject.org/latest/contribute/guidelines.html#commit-guidelines for more details 52ea30be81e17759c1725a3ef7e7c2c64d6ed5c0: Signed-off-by line (Signed-off-by: Kurt Eckhardt ) does not follow the syntax: First Last .  


[Run compliance checks on patch series (PR): Identity.txt#L0](https://github.com//pull/93797/files#annotation_37244444845) See https://docs.zephyrproject.org/latest/contribute/guidelines.html#commit-guidelines for more details

52ea30be81e17759c1725a3ef7e7c2c64d6ed5c0: Signed-off-by line (Signed-off-by: Kurt Eckhardt kurte@rockisland.com) does not follow the syntax: First Last .

@KurtE KurtE force-pushed the camera_snapshot branch 2 times, most recently from f1d99dd to acb2521 Compare July 30, 2025 16:03
@KurtE
Copy link
Contributor Author

KurtE commented Jul 31, 2025

More mumbling to self ;)
Reworking some of this, based on what was done elsewhere including our Teensy_camera code.

With this, the call to video_set_format would have a width=640 and height= 480 Which internally sets the ratio (scaling to 2) and crop to 640x480.

Note: If you now (first commit) call video_get_selection with VIDEO_SEL_TGT_NATIVE_SIZE, it will return 800x600

Reworking: Currently I have the crop code recalculate most of the window and crop registers. Will instead have it
only update the crop registers... As such if you passed in 640x480 on set_format, that is what you are limited to.
So VIDEO_SEL_TGT_NATIVE_SIZE will return 640x480, so I need to save that away and/or grab it from registers.

As the setting the crop updates the fmt structure:

		drv_data->fmt.width = drv_data->crop.width;
		drv_data->fmt.height = drv_data->crop.height;
		drv_data->fmt.pitch = drv_data->fmt.width
			* video_bits_per_pixel(drv_data->fmt.pixelformat) / BITS_PER_BYTE;

Why? Because the buffer management code requires the buffers to be that size:

static int video_stm32_dcmi_enqueue(const struct device *dev, struct video_buffer *vbuf)
{
	struct video_stm32_dcmi_data *data = dev->data;
	const uint32_t buffer_size = data->fmt.pitch * data->fmt.height;

	if (buffer_size > vbuf->size) {
		return -EINVAL;
	}
...

So for example if I setup for the GC2145 camera to output 480x320 the buffer size needed is: 307200 bytes
which the STM32H747 like the Nicla Vision can hold in its memory. Now if the buffer size calculation is based on:
640x480 (614400 bytes) or worse 800x600 (960000 bytes), won't fit in memory.

This also effects the range of crop LEFT and TOP to fit the 480x320 within the range of 640x480...

@KurtE KurtE force-pushed the camera_snapshot branch 4 times, most recently from 3b43aca to 019f84b Compare August 6, 2025 02:26
KurtE added a commit to KurtE/ArduinoCore-zephyr that referenced this pull request Aug 6, 2025
Note: this all uses the Zephyr updates from my PR
zephyrproject-rtos/zephyr#93797

Which I added to the STM dcmi driver the ability to have the camera work in snapshot mode
instead of in continuous video mode.  This allows for example that we start the camera
it grabs a frame and stops, we then take the buffer and process it, and repeat this.
This helps minimize how much the SDRAM gets used concurrently.

In addition, I added to the VIDEO_STM32_DCMI and GC2145 the ability to use some of the
new set_selection and get_selection code that was added for the DCMIPP.  In particular
the DCMI simply forwards these messages to the camera if it defined thise apis...

And with this it allows you to setup a viewport into the frame.  For example:
You can setup the frame on the GC2145 to be 800x600 and then define a view port
to be 480x320 to fill an ST7796/ILI9486 tft display or you could do it 400x240 to half fill
the GIGA display.  You can also move that view port around within the frame (pan)
I have examples that do this on Portenta H7 on the ST7796 display and another one
that does this on the GIGA display shield.

Still WIP as we probably need to refine the APIS and the like
@KurtE KurtE force-pushed the camera_snapshot branch 2 times, most recently from 0cb0ea4 to 74b3afe Compare August 6, 2025 20:28
@KurtE KurtE marked this pull request as ready for review August 6, 2025 20:28
@zephyrbot zephyrbot added the platform: STM32 ST Micro STM32 label Aug 6, 2025
@KurtE
Copy link
Contributor Author

KurtE commented Sep 25, 2025

@avolmat-st @josuah @JarmouniA - I pushed up some changes to the snapshot mode, that if it finds it already
has started but not received an image, it sees how long that image has been pending. I put in a hard coded
5 second timeout, which if expires, stops and then restarts. This appears to handle the cases where the snapshot
just stops.

I believe I Should not hard code, but should allow the program to set it. Not sure which was is best to do this.
Could add property to DCMI? Maybe add the runtime controls?

Should I also change to init controls for setting being in snapshot?

Thanks
Kurt

EDIT: Been running now for a few hours, >45K frames received and displayed on display.
I do get timeouts, but it recovers.

[03:42:24.909,000] <wrn> video_stm32_dcmi: Snapshot: Timed out!
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
[03:43:50.875,000] <wrn> video_stm32_dcmi: Snapshot: Timed out!
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
[03:44:12.296,000] <wrn> video_stm32_dcmi: Snapshot: Timed out!
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
ERROR: Unable to dequeue video buf
[05:12:47.326,000] <wrn> video_stm32_dcmi: Snapshot: Timed out!

Note: I think my sketch semi paused when my computer went to sleep, probably because it could not output to the USB
That is outputting data every 10 frames:

45569 10 RD: 661396 66139 WR: 2096874 209687
45579 10 RD: 661633 66163 WR: 2097455 209745
45589 10 RD: 662042 66204 WR: 2096214 209621
45599 10 RD: 661693 66169 WR: 2096815 209681
45609 10 RD: 661843 66184 WR: 2096722 209672
45619 10 RD: 661123 66112 WR: 2097720 209772

@KurtE KurtE force-pushed the camera_snapshot branch 2 times, most recently from 249a951 to 30f3420 Compare September 26, 2025 15:54
@KurtE
Copy link
Contributor Author

KurtE commented Sep 26, 2025

@avolmat-st - I redid the timeouts code mentioned yesterday. I now do it at the end of the dequeue if it did
not receive a buffer. Also added a setting for what the timeout is in MS.

Note: I split the dequeue up into two functions. The main one checks if it is snaphot and if so calls off to different function.
Leaves the non-snapshot as very simple.

I have run both ways this morning and both are recovering from errors now. The nice this is having the setting and checking
at the end has an added ability. You can set that value very small and you have it so it only times out once.. Or you can set
it to what you really want as a timeout, and you can call with no wait and poll.

I am thinking maybe time to squash back to just two commits.

Thoughts?

Error recovery code done in callback for both modes.

Timeout fixes/changes in snapshot.  Two different
timeouts.  First is a timeout for the call to dequeue.
Which can return before a snapshot completes.
Additional calls to dequeue will continue to wait
if necessary, for a frame to be received.

A second timeout was added, which can be configured
as parameter to DCMI.  This handles cases where the
snapshot start completes successfully, but does not
return a frame in the prescribed time frame.
It currently defaults to one second.

Signed-off-by: Kurt Eckhardt <kurte@rockisland.com>
@sonarqubecloud
Copy link

@KurtE
Copy link
Contributor Author

KurtE commented Sep 29, 2025

@avolmat-st @mjs513 and all. I believe that it is working reasonably well. Both continuous and snapshot. Today I ported it back
to the Arduino version of zephyr: In particular to some of the DMA changes.

In: stm32_dma_init
Newer stuff has:

	hdma.Instance			= STM32_DMA_GET_INSTANCE(config->dma.reg,
								 config->dma.channel);

switched back to:

#if defined(CONFIG_SOC_SERIES_STM32F7X) || defined(CONFIG_SOC_SERIES_STM32H7X)
	hdma.Instance = __LL_DMA_GET_STREAM_INSTANCE(config->dma.reg,
						config->dma.channel);
#elif defined(CONFIG_SOC_SERIES_STM32L4X) || defined(CONFIG_SOC_SERIES_STM32U5X)
	hdma.Instance = __LL_DMA_GET_CHANNEL_INSTANCE(config->dma.reg, config->dma.channel);
#endif

And in the newer stuff it has:
ret = dma_config(config->dma.dma_dev, config->dma.channel, &dma_cfg);
switched back to:

	/* Because of the STREAM OFFSET, the DMA channel given here is from 1 - 8 */
	ret = dma_config(config->dma.dma_dev,
			config->dma.channel + STM32_DMA_STREAM_OFFSET, &dma_cfg);

With these changes I am able to read in frames and display them on the GIGA display shield. Without these changes
it would die after maybe a few frames.

With them it has run for a long period of time. Currently running with 3 frame buffers (no snapshot)
I am getting a lot of the DMA errors, but it is recovering and continuing.

@KurtE KurtE requested a review from avolmat-st September 29, 2025 01:32
@erwango
Copy link
Member

erwango commented Sep 29, 2025

@KurtE About the dma changes. What is the dts dma configuraiton you're using ?

@KurtE
Copy link
Contributor Author

KurtE commented Sep 29, 2025

@KurtE About the dma changes. What is the dts dma configuraiton you're using ?

Sorry, not sure what exactly you are asking, but will guess:

With the Arduino build which is based off of zephyr v4.2.0 on the Arduino Giga board the DMA on the dcmi is configured:


&dcmi {
	status = "okay";
	zephyr,deferred-init;
	/* ext-sdram = <&sdram1>; */
	pinctrl-0 = <&dcmi_hsync_ph8 &dcmi_pixclk_pa6 &dcmi_vsync_pi5
				&dcmi_d0_ph9 &dcmi_d1_ph10 &dcmi_d2_ph11 &dcmi_d3_pg11
				&dcmi_d4_ph14 &dcmi_d5_pi4 &dcmi_d6_pi6 &dcmi_d7_pi7>;
	pinctrl-names = "default";
	dmas = <&dma1 0 75 (STM32_DMA_PERIPH_TO_MEMORY | STM32_DMA_PERIPH_NO_INC |
			STM32_DMA_MEM_INC | STM32_DMA_PERIPH_32BITS | STM32_DMA_MEM_32BITS |
			STM32_DMA_PRIORITY_HIGH) STM32_DMA_FIFO_1_4>;

	port {
		dcmi_ep_in: endpoint {
			remote-endpoint-label = "gc2145_ep_out";
			bus-width = <8>;
			hsync-active = <0>;
			vsync-active = <0>;
			pclk-sample = <0>;
		};
	};
};

Since v4.2.0 released, the DCMI DMA code (video_stm32_dcmi) has changed in a couple of PRs.
Your commit: rivers: stm32: Keep DMA stream offset handling internal to driver
Which removed the offset:

	ret = dma_config(config->dma.dma_dev,
			config->dma.channel + STM32_DMA_STREAM_OFFSET, &dma_cfg);

And your commit: drivers: stm32: Make use of new GET_INSTANCE DMA macro
Which did not exist when 4.2 was released, so I to run on it on 4.2 I had to remove it (in my ArduinoCore Zephyr tests.

On Current stuff: I am using:

	dmas = <&dma1 1 75 (STM32_DMA_PERIPH_TO_MEMORY | STM32_DMA_PERIPH_NO_INC |
			STM32_DMA_MEM_INC | STM32_DMA_PERIPH_32BITS | STM32_DMA_MEM_32BITS |
			STM32_DMA_PRIORITY_HIGH) STM32_DMA_FIFO_1_4>;

And pulled in the PR:
#95803

Note: I tried on my testing of camera code back on ArduinoCore-zephyr tried to pull in the updated version (minus new macro) and neither the camera nor display worked properly. Not sure it interferred with the Display driver. Don't know how to test
the display natively on Zephyr yet.

KurtE added a commit to KurtE/zephyr that referenced this pull request Oct 11, 2025
This was extracted from my snapshot PR: zephyrproject-rtos#93797

Been wondering if we should split off from there and at least get the
simple recovery mechanism in place?

Signed-off-by: Kurt Eckhardt <kurte@rockisland.com>
KurtE added a commit to KurtE/zephyr that referenced this pull request Oct 11, 2025
This was extracted from my snapshot PR: zephyrproject-rtos#93797

Been wondering if we should split off from there and at least get the
simple recovery mechanism in place?

Signed-off-by: Kurt Eckhardt <kurte@rockisland.com>
KurtE added a commit to KurtE/zephyr that referenced this pull request Oct 11, 2025
This was extracted from my snapshot PR: zephyrproject-rtos#93797

Been wondering if we should split off from there and at least get the
simple recovery mechanism in place?

Signed-off-by: Kurt Eckhardt <kurte@rockisland.com>
@KurtE
Copy link
Contributor Author

KurtE commented Oct 12, 2025

@josuah @ngphibang @avolmat-st @mjs513

I am wondering if it would be best to maybe split this up into two (or three) Pull Requests

a) b) Support for the cropping in GC2145 plus DCMI
DCMI Recovery from DMA failures. (which I extracted off to use in another PR) but the commit changes are shown in
a93d2cc

c) Snapshot mode - which I still think would be good for longer term,

but it would be nice to have a) and b) soon - hopefully in time for next Arduino zephyr release as it at least
makes the cameras useable on Arduino Giga and Portenta H7.

Thanks

@avolmat-st
Copy link

Hi @KurtE, sorry for the long delay without a reply. Yeah, it would be great to have this merged before the freeze period start. I will look again at the PR very very shortly.
Sorry again for the delay.

@KurtE
Copy link
Contributor Author

KurtE commented Oct 13, 2025

Hi @KurtE, sorry for the long delay without a reply. Yeah, it would be great to have this merged before the freeze period start. I will look again at the PR very very shortly. Sorry again for the delay.

Thanks, As I mentioned if there are issues with doing snapshot, that could it split it up... So this morning I thought I would try
it, and created a different branch, cherrypicked in the changes for GC2145, Edited in changes for DCMI to forward the
apis to GC2145 (or other cameras) and cherry picked in from my multi-camera branch the simply recovery code which
I extracted from this one...

Then tried building... Since it was based off my main branch it picked up the most recent changes (aagh) and so
first would not build as: the SPI CS pins changes does not build on the STM32 boards (or at least giga/portenta),
there was a draft PR that fixed it, I copied that back in...

Then found my test sketches still don't build as to the changes in: #97197 by @ngphibang
Time to take a break...

And figure out what changes I need to make plus see how it will interact with some of the other tests I was playing with earlier.
Like how to handle the hm01b0, which returns 8 bits per pixel, but the camera can be configured to return 1, 4, or 8 bits
of data per pixel clock...

@josuah
Copy link
Contributor

josuah commented Oct 13, 2025

It is always easier to make smaller PRs.

Currently all reviewers are being quite much solicited as we are approaching a new release and every vendor try to pack their code in place for the new release. Might explain unusual latency in addition to the usual delay. 😬

KurtE added a commit to KurtE/zephyr that referenced this pull request Oct 13, 2025
This was extracted from my snapshot PR: zephyrproject-rtos#93797

Been wondering if we should split off from there and at least get the
simple recovery mechanism in place?

Signed-off-by: Kurt Eckhardt <kurte@rockisland.com>
@KurtE
Copy link
Contributor Author

KurtE commented Oct 13, 2025

It is always easier to make smaller PRs.

Currently all reviewers are being quite much solicited as we are approaching a new release and every vendor try to pack their code in place for the new release. Might explain unusual latency in addition to the usual delay. 😬

I appreciate all that you all do.
If you are you are curious, I did push up a new branch:
https://github.com/KurtE/zephyr/tree/camera_snapshot_minus_snap

Question, should I simplify this branch of this PR? Issue a new PR? Or hold off for now and try to push this branch/PR
through?

Thanks,

Note:
I hacked up one of my examples to get around, the changes that were causing it not to compile. Most of it was debug code
that printed out the information that is no longer there.

@josuah @avolmat-st - I ran a simple sketch (sorry Arduino term - my own sample) that reads image in and displays it
on a TFT display, my own sort of driver for the display and repeats... There is some other stuff that can try to pan around
in an image and also can set viewpoint.

With my default of 320x240 on GC2145, I can display a lot of images. It does error, but then recovers, with some
printk messages like:

Starting main loop
Dequeue: 250085
ERROR: Unable to dequeue video buf
[00:00:07.479,000] <wrn> video_stm32_dcmi: HAL_DCMI_ErrorCallback 0x24000668
[00:00:07.488,000] <wrn> video_stm32_dcmi: Restart DMA after Error!
Dequeue: 2
Dequeue: 50020
Dequeue: 50019
Dequeue: 50019
Dequeue: 50019
Dequeue: 50018
Dequeue: 50018
Dequeue: 50019
Dequeue: 50016
Dequeue: 50018
Dequeue: 49984
Dequeue: 50018
Dequeue: 50018
Dequeue: 50018
Dequeue: 50018
Dequeue: 50019
Dequeue: 50018
Dequeue: 50018
Dequeue: 50018
[00:00:12.716,000] <wrn> video_stm32_dcmi: HAL_DCMI_ErrorCallback 0x24000668
[00:00:12.725,000] <wrn> video_stm32_dcmi: Restart DMA after Error!
Dequeue: 45507
Dequeue: 49984
Dequeue: 50018
Dequeue: 50018
Dequeue: 50019
Dequeue: 50019
Dequeue: 50019
Dequeue: 50017
[00:00:14.941,000] <wrn> video_stm32_dcmi: HAL_DCMI_ErrorCallback 0x24000668
[00:00:14.951,000] <wrn> video_stm32_dcmi: Restart DMA after Error!

The Dequeue messages are where it has received an image. And you can see the warning about errors.

If however I bump this up to 480x320 image then I start getting different DMA errors. At best I might get one image.
And I get repeating error messages like:

        Ty:1 Tar:2 R:0 0 480 320
Starting main loop
Dequeue: 250085
ERROR: Unable to dequeue video buf
Dequeue: 1
[00:00:07.489,000] <err> dma_stm32_v1: FiFo error.
[00:00:07.496,000] <inf> dma_stm32_v1: tc: 0, ht: 1, te: 0, dme: 0, fe: 1
[00:00:07.506,000] <err> dma_stm32: Unexpected irq happened.
[00:00:07.514,000] <err> video_stm32_dcmi: DMA callback error with channel 0.
[00:00:07.524,000] <wrn> video_stm32_dcmi: Restart DMA after Error!
[00:00:07.536,000] <err> dma_stm32: Transfer Error.
[00:00:07.544,000] <inf> dma_stm32_v1: tc: 0, ht: 0, te: 0, dme: 0, fe: 0
[00:00:07.553,000] <err> video_stm32_dcmi: DMA callback error with channel 0.
[00:00:07.563,000] <wrn> video_stm32_dcmi: Restart DMA after Error!
[00:00:07.577,000] <err> dma_stm32: Transfer Error.
[00:00:07.584,000] <inf> dma_stm32_v1: tc: 0, ht: 0, te: 0, dme: 0, fe: 0
[00:00:07.594,000] <err> video_stm32_dcmi: DMA callback error with channel 0.
[00:00:07.604,000] <wrn> video_stm32_dcmi: Restart DMA after Error!
[00:00:07.617,000] <err> dma_stm32: Transfer Error.
[00:00:07.625,000] <inf> dma_stm32_v1: tc: 0, ht: 0, te: 0, dme: 0, fe: 0
[00:00:07.634,000] <err> video_stm32_dcmi: DMA callback error with channel 0.
[00:00:07.644,000] <wrn> video_stm32_dcmi: Restart DMA after Error!
[00:00:07.657,000] <err> dma_stm32: Transfer Error.

Note: I pretty sure I would get these same errors on my other branch associated with this PR.

@JarmouniA
Copy link
Contributor

Question, should I simplify this branch of this PR? Issue a new PR? Or hold off for now and try to push this branch/PR
through?

In my opinion, because of the number of comments here, open a new PR with the crop support for GC2145 and DCMI with absolute minimal changes to get it working.

@JarmouniA
Copy link
Contributor

However probably not many errors with this board as it does not have any SDRAM, so using normal memory for buffers.

My guess is SDRAM instability is mainly due to its location in the bus matrix

IMG1

(DCMI is on AHB2، SDRAM on FMC)

Screenshot2

From AN5020

@KurtE
Copy link
Contributor Author

KurtE commented Oct 21, 2025

I split up this PR into two:
The first one #97491 - (GC2145 plus DCMI CROP and basic DMA recovery) Has been merged in.

2nd one: #98004 - Snapshot mode added to DCMI

Will close out this one for now.

@KurtE KurtE closed this Oct 21, 2025
KurtE added a commit to KurtE/zephyr that referenced this pull request Oct 21, 2025
This was extracted from my snapshot PR: zephyrproject-rtos#93797

Been wondering if we should split off from there and at least get the
simple recovery mechanism in place?

Signed-off-by: Kurt Eckhardt <kurte@rockisland.com>
@KurtE KurtE deleted the camera_snapshot branch October 22, 2025 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: Video Video subsystem platform: STM32 ST Micro STM32

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants