From 23706f77a6a7cc439220a638596b33fff30cebaf Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 21 Dec 2017 18:53:36 +0800 Subject: [PATCH 1/7] allow pins configured as RTC IOs by default (32,33) to be used --- components/camera/camera.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/camera/camera.c b/components/camera/camera.c index 45d4a9d..da80eb2 100644 --- a/components/camera/camera.c +++ b/components/camera/camera.c @@ -37,6 +37,7 @@ #include "soc/i2s_struct.h" #include "soc/io_mux_reg.h" #include "driver/gpio.h" +#include "driver/rtc_io.h" #include "driver/periph_ctrl.h" #include "esp_intr_alloc.h" #include "esp_log.h" @@ -543,6 +544,9 @@ static void i2s_init() .intr_type = GPIO_INTR_DISABLE }; for (int i = 0; i < sizeof(pins) / sizeof(gpio_num_t); ++i) { + if (rtc_gpio_is_valid_gpio(pins[i])) { + rtc_gpio_deinit(pins[i]); + } conf.pin_bit_mask = 1LL << pins[i]; gpio_config(&conf); } From a944a0dbbcf4aa46978624f5b78c588ab0b0366f Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 21 Dec 2017 18:55:34 +0800 Subject: [PATCH 2/7] Use gpio interrupt service instead of registering own ISR Fixes https://github.com/igrr/esp32-cam-demo/issues/58 --- components/camera/camera.c | 31 +++++++++++++++++-------------- components/camera/camera_common.h | 1 - main/app_main.c | 2 ++ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/components/camera/camera.c b/components/camera/camera.c index da80eb2..7d02f5d 100644 --- a/components/camera/camera.c +++ b/components/camera/camera.c @@ -115,6 +115,17 @@ static size_t i2s_bytes_per_sample(i2s_sampling_mode_t mode) } } +static void vsync_intr_disable() +{ + gpio_set_intr_type(s_state->config.pin_vsync, GPIO_INTR_DISABLE); +} + +static void vsync_intr_enable() +{ + gpio_set_intr_type(s_state->config.pin_vsync, GPIO_INTR_NEGEDGE); +} + + esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera_model) { if (s_state != NULL) { @@ -321,13 +332,10 @@ esp_err_t camera_init(const camera_config_t* config) } ESP_LOGD(TAG, "Initializing GPIO interrupts"); - gpio_set_intr_type(s_state->config.pin_vsync, GPIO_INTR_NEGEDGE); - gpio_intr_enable(s_state->config.pin_vsync); - err = gpio_isr_register(&gpio_isr, (void*) TAG, - ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM, - &s_state->vsync_intr_handle); + vsync_intr_disable(); + err = gpio_isr_handler_add(s_state->config.pin_vsync, &gpio_isr, NULL); if (err != ESP_OK) { - ESP_LOGE(TAG, "gpio_isr_register failed (%x)", err); + ESP_LOGE(TAG, "gpio_isr_handler_add failed (%x)", err); goto fail; } @@ -364,10 +372,7 @@ esp_err_t camera_deinit() if (s_state->frame_ready) { vSemaphoreDelete(s_state->frame_ready); } - if (s_state->vsync_intr_handle) { - esp_intr_disable(s_state->vsync_intr_handle); - esp_intr_free(s_state->vsync_intr_handle); - } + gpio_isr_handler_remove(s_state->config.pin_vsync); if (s_state->i2s_intr_handle) { esp_intr_disable(s_state->i2s_intr_handle); esp_intr_free(s_state->i2s_intr_handle); @@ -605,7 +610,7 @@ static void i2s_init() static void i2s_stop() { esp_intr_disable(s_state->i2s_intr_handle); - esp_intr_disable(s_state->vsync_intr_handle); + vsync_intr_disable(); i2s_conf_reset(); I2S0.conf.rx_start = 0; size_t val = SIZE_MAX; @@ -649,7 +654,7 @@ static void i2s_run() I2S0.int_ena.in_done = 1; esp_intr_enable(s_state->i2s_intr_handle); if (s_state->config.pixel_format == CAMERA_PF_JPEG) { - esp_intr_enable(s_state->vsync_intr_handle); + vsync_intr_enable(); } I2S0.conf.rx_start = 1; @@ -684,8 +689,6 @@ static void IRAM_ATTR i2s_isr(void* arg) static void IRAM_ATTR gpio_isr(void* arg) { - GPIO.status1_w1tc.val = GPIO.status1.val; - GPIO.status_w1tc = GPIO.status; bool need_yield = false; ESP_EARLY_LOGV(TAG, "gpio isr, cnt=%d", s_state->dma_received_count); if (gpio_get_level(s_state->config.pin_vsync) == 0 && diff --git a/components/camera/camera_common.h b/components/camera/camera_common.h index d2dfc67..9973dd5 100644 --- a/components/camera/camera_common.h +++ b/components/camera/camera_common.h @@ -65,7 +65,6 @@ typedef struct { i2s_sampling_mode_t sampling_mode; dma_filter_t dma_filter; intr_handle_t i2s_intr_handle; - intr_handle_t vsync_intr_handle; QueueHandle_t data_ready; SemaphoreHandle_t frame_ready; TaskHandle_t dma_filter_task; diff --git a/main/app_main.c b/main/app_main.c index 8107e0d..0da4a72 100644 --- a/main/app_main.c +++ b/main/app_main.c @@ -69,6 +69,8 @@ void app_main() ESP_ERROR_CHECK( nvs_flash_init() ); } + ESP_ERROR_CHECK(gpio_install_isr_service(0)); + camera_config_t camera_config = { .ledc_channel = LEDC_CHANNEL_0, .ledc_timer = LEDC_TIMER_0, From 37d0dc8d3dfad51019633358b6917251b5d5ab5e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 21 Dec 2017 18:59:46 +0800 Subject: [PATCH 3/7] Add sanity check for the framebuffer pointer Framebuffer is allocated right before the DMA filter task is created. Because of this, writing past the end of framebuffer can corrupt the stack of the DMA filter task, causing crashes which are hard to debug. This assert helps catch some of the out-of-bounds writes early. --- components/camera/camera.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/components/camera/camera.c b/components/camera/camera.c index 7d02f5d..69f86a7 100644 --- a/components/camera/camera.c +++ b/components/camera/camera.c @@ -719,10 +719,13 @@ static void IRAM_ATTR dma_filter_task(void *pvParameters) continue; } - uint8_t* pfb = s_state->fb + get_fb_pos(); + size_t fb_pos = get_fb_pos(); + assert(fb_pos <= s_state->fb_size + s_state->width * + s_state->fb_bytes_per_pixel / s_state->dma_per_line); + + uint8_t* pfb = s_state->fb + fb_pos; const dma_elem_t* buf = s_state->dma_buf[buf_idx]; lldesc_t* desc = &s_state->dma_desc[buf_idx]; - ESP_LOGV(TAG, "dma_flt: pos=%d ", get_fb_pos()); (*s_state->dma_filter)(buf, desc, pfb); s_state->dma_filtered_count++; ESP_LOGV(TAG, "dma_flt: flt_count=%d ", s_state->dma_filtered_count); From de844bf9486503433ce56048e62d597bb978137e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 21 Dec 2017 19:09:48 +0800 Subject: [PATCH 4/7] Remove OpenMV copyright header from camera.c OpenMV sensor_ functions are no longer part of camera.c. --- components/camera/camera.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/components/camera/camera.c b/components/camera/camera.c index 69f86a7..6bbedef 100644 --- a/components/camera/camera.c +++ b/components/camera/camera.c @@ -1,14 +1,3 @@ -/* - * Portions of this file come from OpenMV project (see sensor_* functions in the end of file) - * Here is the copyright for these parts: - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * - * Rest of the functions are licensed under Apache license as found below: - */ - // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); From e4abedb93b98cbdeb5dc77db0426eef7c2e788b0 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 22 Dec 2017 14:31:14 +0800 Subject: [PATCH 5/7] Move camera configuration into component menu --- components/camera/{Kconfig.projbuild => Kconfig} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename components/camera/{Kconfig.projbuild => Kconfig} (100%) diff --git a/components/camera/Kconfig.projbuild b/components/camera/Kconfig similarity index 100% rename from components/camera/Kconfig.projbuild rename to components/camera/Kconfig From 70849ceb9564348747e672bef1c5d82f75a891aa Mon Sep 17 00:00:00 2001 From: Rasmus Olsen Date: Tue, 26 Dec 2017 23:16:58 +0100 Subject: [PATCH 6/7] Update README.md Camera Power Down pin mapping should refer to note 3 instead of note 2 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 22df502..5af4a6d 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Specific pins used in this example to connect ESP32 and camera are shown in tabl | Pixel Data Bit 6 | D8 | IO34 | IO36 | | Pixel Data Bit 7 | D9 | IO35 | IO19 | | Camera Reset | RESET | IO2 | IO15 | -| Camera Power Down | PWDN | *see Note 2* | *see Note 2* | +| Camera Power Down | PWDN | *see Note 3* | *see Note 3* | | Power Supply 3.3V | 3V3 | 3V3 | 3V3 | | Ground | GND | GND | GND | @@ -330,4 +330,4 @@ You are welcome to contribute to this repository by providing documentation to c This application is using code developed by: * OpenMV implementation for OV7725 by Ibrahim Abdelkader -* Software I2C library for ESP31B by Hristo Gochkov \ No newline at end of file +* Software I2C library for ESP31B by Hristo Gochkov From 14b6170060d03847ece370013be7448b25be1f19 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 18 Sep 2018 17:55:32 +0800 Subject: [PATCH 7/7] fix xclk for latest IDF --- components/camera/xclk.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/components/camera/xclk.c b/components/camera/xclk.c index 8bf0123..4ad050f 100644 --- a/components/camera/xclk.c +++ b/components/camera/xclk.c @@ -10,24 +10,26 @@ esp_err_t camera_enable_out_clock(camera_config_t* config) { periph_module_enable(PERIPH_LEDC_MODULE); - ledc_timer_config_t timer_conf; - timer_conf.duty_resolution = 1; - timer_conf.freq_hz = config->xclk_freq_hz; - timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE; - timer_conf.timer_num = config->ledc_timer; + ledc_timer_config_t timer_conf = { + .duty_resolution = 1, + .freq_hz = config->xclk_freq_hz, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_num = config->ledc_timer + }; esp_err_t err = ledc_timer_config(&timer_conf); if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err); return err; } - ledc_channel_config_t ch_conf; - ch_conf.channel = config->ledc_channel; - ch_conf.timer_sel = config->ledc_timer; - ch_conf.intr_type = LEDC_INTR_DISABLE; - ch_conf.duty = 1; - ch_conf.speed_mode = LEDC_HIGH_SPEED_MODE; - ch_conf.gpio_num = config->pin_xclk; + ledc_channel_config_t ch_conf = { + .channel = config->ledc_channel, + .timer_sel = config->ledc_timer, + .intr_type = LEDC_INTR_DISABLE, + .duty = 1, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .gpio_num = config->pin_xclk + }; err = ledc_channel_config(&ch_conf); if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err);