From 1af120da5a39343c1588008fd766387782d3929b 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 c8562094..4cd28733 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 2784179d..3b58af0c 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 1bce0bdf..aeea84e1 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 36643e3d..6141f828 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;