From 74f972174ce2695fa0237441493c7b27619ec5c5 Mon Sep 17 00:00:00 2001 From: Kurt Eckhardt Date: Mon, 8 Sep 2025 06:10:58 -0700 Subject: [PATCH] camera: try to defer init of video objects This change, removes the automatic starting of the PWM clock on the GIGA, at startup. Instead it starts the clock if/when the sketch calls the Camera::begin method. But to make this work, we also need to not start up the video objects, until after the MCLK has been started. We can do that with marking them as zephyr,deferred-init --- libraries/Camera/src/camera.cpp | 60 ++++++++++++++++++- loader/fixups.c | 32 ---------- .../arduino_giga_r1_stm32h747xx_m7.overlay | 3 + ...arduino_portenta_h7_stm32h747xx_m7.overlay | 3 + 4 files changed, 65 insertions(+), 33 deletions(-) diff --git a/libraries/Camera/src/camera.cpp b/libraries/Camera/src/camera.cpp index c8562094c..4cd287334 100644 --- a/libraries/Camera/src/camera.cpp +++ b/libraries/Camera/src/camera.cpp @@ -45,15 +45,73 @@ Camera::Camera() : vdev(NULL), byte_swap(false), yuv_to_gray(false) { } } +#if defined(CONFIG_VIDEO) +#include +#include +#include +#include + +int camera_ext_clock_enable(void) { + int ret; + uint32_t rate; + const struct device *cam_ext_clk_dev = DEVICE_DT_GET(DT_NODELABEL(pwmclock)); + + if (!device_is_ready(cam_ext_clk_dev)) { + return -ENODEV; + } + + ret = clock_control_on(cam_ext_clk_dev, (clock_control_subsys_t)0); + if (ret < 0) { + return ret; + } + + ret = clock_control_get_rate(cam_ext_clk_dev, (clock_control_subsys_t)0, &rate); + if (ret < 0) { + return ret; + } + + return 0; +} +#else +#ERROR "CONFIG_VIDEO is not defined for this variant" +#endif + bool Camera::begin(uint32_t width, uint32_t height, uint32_t pixformat, bool byte_swap) { #if DT_HAS_CHOSEN(zephyr_camera) this->vdev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); #endif - if (!this->vdev || !device_is_ready(this->vdev)) { + // start the clock + int ret; + + if (!this->vdev) { return false; } + camera_ext_clock_enable(); + delay(50); + + if (!device_is_ready(this->vdev)) { + // device probably has zephyr,deferred-init + // On GIGA and Portenta H7 and probably others starts DCIM object + if ((ret = device_init(this->vdev)) < 0) { + printk("device_init camera(%p) failed:%d\n", this->vdev, ret); + return false; + } + } + + // Now see if the actual camera is defined in choosen. And see if it is ready +#if DT_HAS_CHOSEN(zephyr_camera_sensor) + const struct device *camera_sensor = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera_sensor)); + if (!device_is_ready(camera_sensor)) { + if ((ret = device_init(camera_sensor)) < 0) { + printk("device_init camera sensor(%p) failed:%d\n", camera_sensor, ret); + return false; + } + } + +#endif + switch (pixformat) { case CAMERA_RGB565: this->byte_swap = byte_swap; diff --git a/loader/fixups.c b/loader/fixups.c index ba6be7f3d..aa6c993b7 100644 --- a/loader/fixups.c +++ b/loader/fixups.c @@ -74,38 +74,6 @@ static void zephyr_input_callback(struct input_event *evt, void *user_data) { INPUT_CALLBACK_DEFINE(NULL, zephyr_input_callback, NULL); #endif -#if defined(CONFIG_BOARD_ARDUINO_GIGA_R1) && defined(CONFIG_VIDEO) -#include -#include -#include -#include - -int camera_ext_clock_enable(void) { - int ret; - uint32_t rate; - const struct device *cam_ext_clk_dev = DEVICE_DT_GET(DT_NODELABEL(pwmclock)); - - if (!device_is_ready(cam_ext_clk_dev)) { - return -ENODEV; - } - - ret = clock_control_on(cam_ext_clk_dev, (clock_control_subsys_t)0); - if (ret < 0) { - return ret; - } - - ret = clock_control_get_rate(cam_ext_clk_dev, (clock_control_subsys_t)0, &rate); - if (ret < 0) { - return ret; - } - - return 0; -} - -SYS_INIT(camera_ext_clock_enable, POST_KERNEL, CONFIG_CLOCK_CONTROL_PWM_INIT_PRIORITY); - -#endif - #if defined(CONFIG_SHARED_MULTI_HEAP) #include #include diff --git a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay index 89cccef63..4c955926f 100644 --- a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay +++ b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay @@ -32,6 +32,7 @@ gc2145: gc2145@3c { compatible = "galaxycore,gc2145"; reg = <0x3c>; + zephyr,deferred-init; reset-gpios = <&gpiod 4 GPIO_ACTIVE_LOW>; pwdn-gpios = <&gpioa 1 GPIO_ACTIVE_LOW>; @@ -148,6 +149,7 @@ &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 @@ -320,6 +322,7 @@ /{ chosen { zephyr,camera = &dcmi; + zephyr,camera-sensor = &gc2145; /* zephyr,console = &board_cdc_acm_uart; */ }; diff --git a/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay b/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay index 9f760d762..62c9c32d0 100644 --- a/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay +++ b/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay @@ -20,6 +20,7 @@ gc2145: gc2145@3c { compatible = "galaxycore,gc2145"; reg = <0x3c>; + zephyr,deferred-init; status = "okay"; reset-gpios = <&gpioe 3 GPIO_ACTIVE_LOW>; @@ -132,6 +133,7 @@ &dcmi { status = "okay"; + zephyr,deferred-init; /* ext-sdram = <&sdram1>; */ pinctrl-0 = <&dcmi_hsync_pa4 &dcmi_pixclk_pa6 &dcmi_vsync_pi5 &dcmi_d0_ph9 &dcmi_d1_ph10 &dcmi_d2_ph11 &dcmi_d3_ph12 @@ -245,6 +247,7 @@ / { chosen { zephyr,camera = &dcmi; + zephyr,camera-sensor = &gc2145; zephyr,console = &usart6; zephyr,shell-uart = &usart6; zephyr,cdc-acm-uart0 = &usart6;