Skip to content
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

Camera interface esp32s3 #75331

Closed

Conversation

epc-ake
Copy link
Contributor

@epc-ake epc-ake commented Jul 2, 2024

Pull Request Summary

This pull request introduces video capturing functionality for the ESP32-S3 LCD_CAM interface.
To use this feature, you must first merge pull request #74974.
It depends on the hal espressif being merged and added to the zephyr manifest.
Alternatively drop the last commit so the driver writes directly into the registers and skipping the hal.
Using the xiao_esp32s3 board and the OV2640 camera sensor, I successfully captured low resolution images in RGB565 format.

Open Topics for Discussion

Although the driver is functional, several topics need further discussion:

1. Using External Memory

Due to issues with memory reallocation on the ESP32-S3, testing was limited to internal memory, requiring the imager to be set to the lowest resolution (160x120px).
#76982 enables to choose the video buffer location and to put it into to external ram. This enables this driver also to capture high resolution images.

2. ESP32-HAL

Currently, the driver directly writes to the LCD_CAM register values using the SOC register structs.
It may be more appropriate to move these calls to the hal_espressif.

3. Devicetree structure:

The LCD_CAM module involves four different devices (cam-clk, lcd-clk, lcd-interface, cam-interface).
Initially, I attempted to combine the cam-clk and cam-interface into one device and set the cam-clk rate based on a devicetree property.
This approach failed because the cam-interface references the sensor (OV2640) in the device tree, requiring the sensor to be initialized before the cam-interface, which isn't possible without first initializing the camera clock.

A proposed structure is:

lcd_cam: lcd_cam@60041000 {
    compatible = "espressif,esp32-lcd_cam";
    reg = <0x60041000 DT_SIZE_K(4)>;
    status = "disabled";
    clocks = <&rtc ESP32_LCD_CAM_MODULE>;

    cam-xclk: cam-xclk {
        compatible = "espressif,esp32-cam-xclk";
        clock-rate = <1000000>;
    };

    cam-interface: cam-interface {
        compatible = "espressif,esp32-cam";
        dmas = <&dma 2>;
        dma-names = "rx";
    };

    lcd-clk: lcd-clk {
        compatible = "espressif,esp32-lcd-clk";
        clock-rate = <1000000>;
    };

    lcd-interface: lcd-interface {
        compatible = "espressif,esp32-lcd";
        dmas = <&dma 2>;
        dma-names = "tx";
    };
};

However, this might be overly complex, especially since espressif,esp32-lcd_cam would only enable the peripheral without much additional functionality.
If you have a better idea or see an alternative way to implement this, please leave a comment!

4. Testing

I have some tests locally that only run on the xiao_esp32s3 with the ov2640 sensor. I could add them to the zephyr test folder but I don't know where to place them exactly.
It would also be nice to add support for the sample/subsys/video/ samples.

This PR adds an overlay for the xiao_esp32s3 to the samples/drivers/video/capture/.

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 this driver! I tried to spot a few things that I thought you'd be interested in adjusting. Glad to see more device families part of the Video driver collection.

drivers/video/video_esp32_dvp.c Show resolved Hide resolved
drivers/video/video_esp32_dvp.c Outdated Show resolved Hide resolved
dts/bindings/clock/espressif,esp32-cam-clk.yaml Outdated Show resolved Hide resolved
dts/bindings/clock/espressif,esp32-cam-clk.yaml Outdated Show resolved Hide resolved
drivers/video/video_esp32_dvp.c Outdated Show resolved Hide resolved
dts/bindings/video/espressif,esp32_cam.yaml Outdated Show resolved Hide resolved
dts/bindings/video/espressif,esp32_cam.yaml Outdated Show resolved Hide resolved
drivers/video/video_esp32_dvp.c Show resolved Hide resolved
drivers/video/Kconfig.esp32_dvp Outdated Show resolved Hide resolved
drivers/video/Kconfig.esp32_dvp Outdated Show resolved Hide resolved
@ASerbinski
Copy link
Contributor

I'm no expert with cameras or the differences between successive generations of esp32's, but is this fundamentally bound to the "s3" version of esp32? Or would it also be compatible with older esp32's as well?

@epc-ake
Copy link
Contributor Author

epc-ake commented Jul 4, 2024

@ASerbinski The s3 is the only esp32 model with a dedicated video interface. The other esp32 variants use the I2S interface to "emulate" a video interface. Therefore, this driver is only compatible with the esp32s3.

@epc-ake epc-ake force-pushed the camera_interface_esp32s3 branch 2 times, most recently from 119a3ec to c4e5d10 Compare July 4, 2024 08:10
@havoc-dlt
Copy link

havoc-dlt commented Aug 4, 2024

Concerning the tests/samples, I can't seem to find your sample code anywhere. I'd really like to contribute with testing, so can you point me in the right direction?

@josuah
Copy link
Collaborator

josuah commented Aug 4, 2024

<@epc-ake> I could add them to the zephyr test folder but I don't know where to place them exactly

The best could be to have the upstream examples supported, making modifications to the example only if needed, and using a shield, a bit like how it was done for this OV5640 module.

Maybe one way to figure out how to compose the example together would be to add another example here on this PR, just for the sake of publishing the source and reviewing it, even if it is removed afterward... Or just paste the snippets of code/config if there are just a few.

Thanks again!

@epc-ake
Copy link
Contributor Author

epc-ake commented Aug 5, 2024

Concerning the tests/samples, I can't seem to find your sample code anywhere. I'd really like to contribute with testing, so can you point me in the right direction?

I made a new commit and added the overlays for the xiao_esp32s3 to support for the sample/subsys/video/capture.
I made some temporary changes to the sample it self, since I still didn't figure out how to store the image in external ram.
This should enable you to capture images on the ov2640 and store the image in internal ram.
Remember that you also have to checkout #74974 for this PR to work.

@havoc-dlt
Copy link

havoc-dlt commented Aug 6, 2024

Concerning the tests/samples, I can't seem to find your sample code anywhere. I'd really like to contribute with testing, so can you point me in the right direction?

I made a new commit and added the overlays for the xiao_esp32s3 to support for the sample/subsys/video/capture. I made some temporary changes to the sample it self, since I still didn't figure out how to store the image in external ram. This should enable you to capture images on the ov2640 and store the image in internal ram. Remember that you also have to checkout #74974 for this PR to work.

Thanks for the reminder, but I already have a working setup with your PRs patched in and been tinkering with it and my own zephyr projects a bit. I'm looking forward to test your code in my spare time!

Copy link
Collaborator

@uLipe uLipe left a comment

Choose a reason for hiding this comment

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

Great work! Please check some comments and minor concerns I placed across this patchset

drivers/clock_control/clock_control_esp32_cam.c Outdated Show resolved Hide resolved
drivers/video/video_esp32_dvp.c Show resolved Hide resolved
}

if (dma_block_iter->next_block) {
LOG_ERR("Not enough descriptors available. Increase DMA_ESP32_DESCRIPTOR_NUM");
Copy link
Collaborator

Choose a reason for hiding this comment

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

I noticed there is neither irq_unlock, not goto_unlock which may cause irq state conflict.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good spot

LCD_CAM.cam_ctrl.cam_update = 0;
LCD_CAM.cam_ctrl1.cam_start = 1;

data->is_streaming = true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Question, is it a must to place a giant lock inside of this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

probably not, since the interrupts are inactive when you start the stream any how...
I'll remove it and add a check to make sure we are not already streaming on stream_start().

This commit creates a new node for the lcd_cam interface.
It enables the lcd_cam pheripheral clock and adds the possibiliy
to controll the camera clock frequency trough the `cam-clk` property.
This is its own device for two reasons:
1. It enables to use the camera clock as a standalone clock.
2. It enables to initialize xclk before the sensor driver.

Signed-off-by: Armin Kessler <[email protected]>
Adding support for the esp32s3 camera interface.

Signed-off-by: Armin Kessler <[email protected]>
Remove the VSync interrupt handle, as DMA captures
VSync through the in_suc_eof event.

Signed-off-by: Armin Kessler [email protected]
adding xiao_esp32s3 support to video capture sample

Signed-off-by: Armin Kessler [email protected]
The driver now calls the `<hal/cam_hal.h>` API instead of writing
directly into the registers.

Signed-off-by: Armin Kessler [email protected]
@epc-ake
Copy link
Contributor Author

epc-ake commented Aug 15, 2024

@LucasTambor I've added a new commit to so that the driver now uses the espressif hal instead of writing directly into the registers.

@@ -0,0 +1,4 @@
config CLOCK_CONTROL_ESP32_CAM
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is wrong, it should default to y and have a "depends on DT_HAS...". See Kconfig files for the other clock control drivers

config CLOCK_CONTROL_ESP32_CAM
bool "master clock for esp32 camera interface"
help
This option enables the pheriphery and cam clock for the lcd_cam module.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Spelling

@@ -0,0 +1,6 @@
config VIDEO_ESP32S3
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto: default y / DT_HAS_...

* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT espressif_esp32_cam
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would be better to keep driver file name and compatible consistent. Go for either cam or dvp everywhere (I personally prefer cam, I'd say)

CONFIG_VIDEO_ESP32S3=y
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=40000
CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=3
CONFIG_CLOCK_CONTROL_ESP32_CAM=y
Copy link
Collaborator

Choose a reason for hiding this comment

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

Drop. Not needed when you will have fixed the kconfigs

@@ -0,0 +1,5 @@
CONFIG_DMA=y
CONFIG_VIDEO_ESP32S3=y
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same

Comment on lines +147 to +160
fmt.width = 160;
fmt.height = 120;
fmt.pitch = fmt.width * 2;
fmt.pixelformat = VIDEO_PIX_FMT_RGB565;

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

printk("- Set format: %c%c%c%c %ux%u\n", (char)fmt.pixelformat,
(char)(fmt.pixelformat >> 8), (char)(fmt.pixelformat >> 16),
(char)(fmt.pixelformat >> 24), fmt.width, fmt.height);

Copy link
Collaborator

Choose a reason for hiding this comment

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

What is this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is just a workaround to be able to fit the captured frame into internal ram.
It should and will be removed once #76982 is merged.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah I see. But since this impacts (negatively) users using other drivers, I would not consider this workaround acceptable. If you wanted, I guess you could add Kconfigs to the sample to allow setting a max resolution though, and based on the supported resolutions you get from the call to video_get_capabilities you could set to whatever resolutions is the closest?

int ret = 0;

if (0 == cam_clk) {
LCD_CAM.cam_ctrl.cam_clk_sel =
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you use HAL API here as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I left a comment in the hal/cam PR.

@@ -0,0 +1,6 @@
config VIDEO_ESP32S3
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's use just VIDEO_ESP32, it's more generic for later SoCs

@epc-ake
Copy link
Contributor Author

epc-ake commented Aug 15, 2024

Thanks for all the reviews.
I will be on vacation for the next two weeks and won't be able to work on this.
If you need to expedite it, feel free to create a new PR based on this one.
Otherwise, I will implement your suggestions after I return.

@epc-ake
Copy link
Contributor Author

epc-ake commented Sep 2, 2024

Since @LucasTambor took over this at #77709 and #77879 I close this PR

@epc-ake epc-ake closed this Sep 2, 2024
@epc-ake epc-ake deleted the camera_interface_esp32s3 branch September 19, 2024 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Clock Control area: Devicetree Binding PR modifies or adds a Device Tree binding area: Video Video subsystem area: Xtensa Xtensa Architecture platform: ESP32 Espressif ESP32
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants