From d5437058ca2207159db3ac2a97668eaa081bf76e 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 7288c8b8..9a27491e 100644 --- a/libraries/Camera/src/camera.cpp +++ b/libraries/Camera/src/camera.cpp @@ -49,15 +49,73 @@ Camera::Camera() : byte_swap(false), yuv_to_gray(false), vdev(NULL) { } } +#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 42afca2d..437854bf 100644 --- a/loader/fixups.c +++ b/loader/fixups.c @@ -81,38 +81,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 4d9269ca..12929c12 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 f3f377b3..ce74cd33 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;