Skip to content

Add support for Renesas RA CEU (Capture Engine Unit) for RA8M1 and RA8D1 #92146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

thaoluonguw
Copy link
Collaborator

Add support for Renesas RA CEU (Capture Engine Unit):

  • Add video driver use CEU
  • Add dts for CEU on RA8M1 and RA8D1
  • Enable CEU support for EK-RA8D1
  • Add support for EK-RA8D1 on Video capture to LVGL sample.
    It works with OV7670 camera, and MIPI graphics expansion board included in the Kit

KhanhNguyen-RVC and others added 7 commits June 25, 2025 09:50
Update hal_renesas to support CEU on RA SoCs

Signed-off-by: Duy Vo <[email protected]>
Signed-off-by: Khanh Nguyen <[email protected]>
Add support for the Renesas RA Capture Engine Unit (CEU),
including driver source files, Kconfig options, and DTS bindings.

- Add initial implementation of the RA CEU driver
- Add dedicated Kconfig and CMake integration
- Provide Devicetree bindings for the RA CEU
- Update module Kconfig to include the new driver

This enables image capture functionality using the CEU peripheral
on Renesas RA series MCUs.

Signed-off-by: Duy Vo <[email protected]>
Signed-off-by: Khanh Nguyen <[email protected]>
Add pin definitions required by the RA Capture Engine Unit

Signed-off-by: Duy Vo <[email protected]>
Signed-off-by: Khanh Nguyen <[email protected]>
Add CEU to r7fa8d1xh.dtsi and r7fa8m1xh.dtsi

Signed-off-by: Khanh Nguyen <[email protected]>
- Add CEU pin configuration to ek_ra8d1-pinctrl.dtsi
- Enable CEU node and Arducam 20-pin connector in ek_ra8d1.dts
- Configure PWM3 as external XCLK via pwm-clock node
- Update board YAML to declare video support

Signed-off-by: Duy Vo <[email protected]>
Signed-off-by: Khanh Nguyen <[email protected]>
Add EK-RA8D1 board support for the capture_to_lvgl sample
- Add board-specific configuration in ek_ra8d1.conf
- Add Devicetree overlay enabling CEU and display path

Signed-off-by: Duy Vo <[email protected]>
Signed-off-by: Khanh Nguyen <[email protected]>
Add SW1 configuration for using Camera Exapansion Port (J59)

Signed-off-by: Thao Luong <[email protected]>
Copy link

The following west manifest projects have changed revision in this Pull Request:

Name Old Revision New Revision Diff
hal_renesas zephyrproject-rtos/hal_renesas@0769fe1 (main) zephyrproject-rtos/hal_renesas#113 zephyrproject-rtos/hal_renesas#113/files

DNM label due to: 1 project with PR revision

Note: This message is automatically posted and updated by the Manifest GitHub Action.

@github-actions github-actions bot added manifest manifest-hal_renesas DNM (manifest) This PR should not be merged (controlled by action-manifest) labels Jun 25, 2025
Copy link

Copy link
Collaborator

@josuah josuah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for implementing the Renesas video driver!

The driver appears in a good shape WRT video APIs, with a few key points to modify (marked with :x), and a few proposal to improve it further, non-blocking (i.e. could be improved over time eventually, although appreciated if modified now).

Let me know if anything needs clarifications.

Comment on lines +14 to +19
config VIDEO_RENESAS_BUFFER_SDRAM
bool "Allocate the video buffer into SDRAM"
depends on VIDEO_RENESAS_RA_CEU
select MEMC
help
Allocate the video buffer into SDRAM
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking]
If interested, there is another mechanism to select the type of memory for use as video buffer memory: Shared Multi-Heap (SMH).

Here is an example that compares how this was implemented in both ST and Espressif side for information:
56e69e5

This gives the user the final choice of what memory source to use.

Comment on lines +122 to +129
if (fmt->width % CEU_WIDTH_ALIGN) {
LOG_DBG("Width %d not a multiple of %d", fmt->width, CEU_WIDTH_ALIGN);
return -ENOTSUP;
}
if (fmt->height % CEU_HEIGHT_ALIGN) {
LOG_DBG("Height %d not a multiple of %d", fmt->height, CEU_HEIGHT_ALIGN);
return -ENOTSUP;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking]
To help with compliance effort in the future, is it possible to compare against 0 so that the expression is a boolean?

Suggested change
if (fmt->width % CEU_WIDTH_ALIGN) {
LOG_DBG("Width %d not a multiple of %d", fmt->width, CEU_WIDTH_ALIGN);
return -ENOTSUP;
}
if (fmt->height % CEU_HEIGHT_ALIGN) {
LOG_DBG("Height %d not a multiple of %d", fmt->height, CEU_HEIGHT_ALIGN);
return -ENOTSUP;
}
if (fmt->width % CEU_WIDTH_ALIGN != 0) {

The subset of MISRA recommended for Zephyr developers is listed here.

Comment on lines +166 to +174
if (!enable) {
if (video_stream_stop(config->source_dev, type)) {
LOG_DBG("Failed to stop source device stream");
return -EIO;
}

data->is_streaming = false;
R_CEU->CAPSR = R_CEU_CAPSR_CPKIL_Msk;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking]
If enable == false, then the if will execute, but what is after it as well as there is no return 0;, maybe this was not intentional.

Comment on lines +192 to +195
if (video_stream_start(config->source_dev, type)) {
LOG_DBG("Failed to start source device stream");
return -EIO;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking]
While this code is working, the following would be slightly more conventional:

Suggested change
if (video_stream_start(config->source_dev, type)) {
LOG_DBG("Failed to start source device stream");
return -EIO;
}
int ret;
...
ret = video_stream_start(config->source_dev, type)
if (ret < 0) {
LOG_DBG("Failed to start source device stream");
return ret;
}

Comment on lines +167 to +170
if (video_stream_stop(config->source_dev, type)) {
LOG_DBG("Failed to stop source device stream");
return -EIO;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking]
While this code is working, the following would be slightly more conventional:

Suggested change
if (video_stream_stop(config->source_dev, type)) {
LOG_DBG("Failed to stop source device stream");
return -EIO;
}
int ret;
...
video_stream_stop(config->source_dev, type);
if (ret < 0) {
LOG_DBG("Failed to stop source device stream");
return ret;
}

There does not seem to be any policy for use of ret vs err or ret < 0 vs ret != 0.

One possible way to handle error codes from the HAL and error codes from Zephyr is to use err for HAL errors and ret for Zephyr errors.

Coding guidelines are non-blocking at the moment, however! This is only anticipating the moment where certification would video drivers.

Comment on lines +24 to +29
bus-width = <8>;
hsync-active = <1>;
vsync-active = <1>;
pclk-sample = <1>;
hsync-sample = <0>;
vsync-sample = <0>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking]
It seems like all these properties are specific to the ov7670 more than specific to this board. For instance, if the user wants to try with a different image sensor shield, they might need different values at this place.

It might be possible to move these properties to boards/shields/dvp_20pin_ov7670/dvp_20pin_ov7670.overlay:

&dvp_20pin_ep_in {
	bus-width = <8>;
	hsync-active = <1>;
	vsync-active = <1>;
	pclk-sample = <1>;
	hsync-sample = <0>;
	vsync-sample = <0>;
};

All these properties are expected to always exist, even if they are not used by drivers, so this is not expected t to break the other boards... Except for hsync-sample and vsync-sample not defined on dts/bindings/video/video-interfaces.yaml.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then, on boards/renesas/ek_ra8d1/ek_ra8d1.dts, it is possible to define an empty endpoint, just for the purpose of declaring the label:

&ceu {
	...
	port {
		dvp_20pin_ep_in: endpoint {
			remote-endpoint-label = "";
		};
	};
};

};

&dvp_20pin_i2c {
status = "okay";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking]
status = "okay"; should have been enabled in the ov7670 module: a bug in the module definition.
Do feel free to move this line to here if you wish, otherwise I will open a new pull request to fix OV7670:

Comment on lines +7 to +9
&dvp_20pin_connector {
status = "okay";
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocking ❌]
The connector is a mere mapping of GPIO pins usually without an associated device.
It is also not status = "disabled"; by the boards/renesas/ek_ra8d1/ek_ra8d1.dts where it is defined.
As far as I understand, this is redundant. Let me know if I missed something.

Comment on lines +16 to +17
&dvp_20pin_interface {
status = "okay";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking]
The status = "okay"; is already performed by the shield, and does not seems necessary there.

&dvp_20pin_interface {
status = "okay";

Comment on lines +18 to +20
swap-8bits;
swap-16bits;
swap-32bits;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking]
The remaining properties may be added to the shield-specific configuration file.
It will be possible to add a /boards/shields/dvp_20pin_ov7670/boards/ek_ra8d1.overlay that contains all the board-specific integration with a module.
This way, you do not need to re-define these parameters on every sample, and users can select any sensor.

@josuah
Copy link
Collaborator

josuah commented Jun 26, 2025

[blocking ❌]
In order to make sure this driver always compiles even after Video APIs are refactored, you may want to add it to this test that will run on CI on every video-related commit:
tests/drivers/build_all/video/app.overlay

}
}

static int video_renesas_ra_ceu_get_format(const struct device *dev, struct video_format *fmt)
Copy link
Collaborator

@ngphibang ngphibang Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function name is rather long, could it be shorten like ra_ceu_get_format ?. Idem for others

fsp_err_t err;
int ret;

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a big deal but fmt->pitch should be computed at the end when everything is OK as it is the value that application will read back.

Comment on lines +46 to +78
child-binding:
child-binding:
include: video-interfaces.yaml

properties:
hsync-active:
required: true

vsync-active:
required: true

pclk-sample:
required: true

vsync-sample:
required: true
type: int
enum:
- 0 # Falling edge
- 1 # Rising edge
description: |
Sample on the falling or rising edge of the vsync signal.

hsync-sample:
required: true
type: int
enum:
- 0 # Falling edge
- 1 # Rising edge
description: |
Sample on the falling or rising edge of the hsync signal.

bus-width:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you redefine many properties that are already defined in video-interfaces.yaml ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Pinctrl area: Samples Samples area: Video Video subsystem DNM (manifest) This PR should not be merged (controlled by action-manifest) manifest manifest-hal_renesas platform: Renesas RA Renesas Electronics Corporation, RA
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants