diff --git a/common/omv_csi.c b/common/omv_csi.c index 43c04ab65..3476d5ed0 100644 --- a/common/omv_csi.c +++ b/common/omv_csi.c @@ -119,6 +119,7 @@ uint16_t resolution[][2] = { {2592, 1944}, /* WQXGA2 */ }; +static omv_i2c_t csi_i2c; omv_csi_t csi_all[OMV_CSI_MAX_DEVICES] = {0}; __weak void omv_csi_init0() { @@ -149,9 +150,73 @@ __weak void omv_csi_init0() { } __weak int omv_csi_init() { - // Reset the csi state - memset(csi_all, 0, sizeof(csi_all)); - return OMV_CSI_ERROR_CTL_UNSUPPORTED; + int ret = 0; + + // List of I2C buses to scan. + uint32_t buses[][2] = { + { OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED }, + #if defined(OMV_CSI_I2C_ALT_ID) + { OMV_CSI_I2C_ALT_ID, OMV_CSI_I2C_ALT_SPEED }, + #endif + }; + + // Configure CSI GPIOs + #if defined(OMV_CSI_RESET_PIN) + omv_gpio_config(OMV_CSI_RESET_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_LOW, -1); + #endif + #if defined(OMV_CSI_FSYNC_PIN) + omv_gpio_config(OMV_CSI_FSYNC_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_LOW, -1); + #endif + #if defined(OMV_CSI_POWER_PIN) + omv_gpio_config(OMV_CSI_POWER_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_LOW, -1); + #endif + + // Initialize the CSIs using the port's ops as defaults, + // which can be overridden by sensor drivers during probe. + for (size_t i=0; ii2c = &csi_i2c; + csi->fb = framebuffer_get(-1); + csi->color_palette = rainbow_table; + omv_csi_ops_init(csi); + } + + // Configure the csi external clock (XCLK). + if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) { + return OMV_CSI_ERROR_TIM_INIT_FAILED; + } + + // Detect and initialize sensor(s). + for (uint32_t i=0, n_buses=OMV_ARRAY_SIZE(buses); ienabled = 0; + return 0; } omv_csi_t *omv_csi_get(int id) { diff --git a/common/omv_csi.h b/common/omv_csi.h index 4124e5200..e52414ece 100644 --- a/common/omv_csi.h +++ b/common/omv_csi.h @@ -400,6 +400,9 @@ void omv_csi_init0(); // Initializes CSI struct with default ops. int omv_csi_init(); +// Implemented by ports to set the default CSI ops. +int omv_csi_ops_init(omv_csi_t *csi); + // Return CSI instance. // If id == -1, return the main csi, otherwise look up csi by chip-id. omv_csi_t *omv_csi_get(int id); diff --git a/ports/alif/alif_hal.c b/ports/alif/alif_hal.c index ed1badfd7..d5f4f6294 100644 --- a/ports/alif/alif_hal.c +++ b/ports/alif/alif_hal.c @@ -103,6 +103,11 @@ void alif_hal_init(void) { // Configure and enable USB IRQs. NVIC_ClearPendingIRQ(USB_IRQ_IRQn); NVIC_SetPriority(USB_IRQ_IRQn, IRQ_PRI_USB); + + #if MICROPY_PY_CSI + // Enable CSI clock and configure pins. + alif_hal_csi_init(OMV_CSI_BASE); + #endif } int alif_hal_i2c_init(uint32_t bus_id) { @@ -364,14 +369,15 @@ int alif_hal_pdm_deinit(uint32_t pdm_id) { return 0; } -int alif_hal_csi_init(CPI_Type *cpi, uint32_t mode) { - if (mode == 0) { +int alif_hal_csi_init(CPI_Type *cpi) { + // Enable CPI clock. + if (cpi == ((CPI_Type *) CPI_BASE)) { enable_cpi_periph_clk(); } else { enable_lpcpi_periph_clk(); } - // Configure camera sensor interface pins + // Configure CPI pins. omv_gpio_config(OMV_CSI_D0_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1); omv_gpio_config(OMV_CSI_D1_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1); omv_gpio_config(OMV_CSI_D2_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1); @@ -386,18 +392,6 @@ int alif_hal_csi_init(CPI_Type *cpi, uint32_t mode) { omv_gpio_config(OMV_CSI_PXCLK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1); omv_gpio_config(OMV_CSI_MXCLK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1); - // Configure DCMI GPIOs - #if defined(OMV_CSI_RESET_PIN) - omv_gpio_config(OMV_CSI_RESET_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_DOWN, OMV_GPIO_SPEED_LOW, -1); - #endif - #if defined(OMV_CSI_FSYNC_PIN) - omv_gpio_config(OMV_CSI_FSYNC_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_DOWN, OMV_GPIO_SPEED_LOW, -1); - #endif - #if defined(OMV_CSI_POWER_PIN) - omv_gpio_config(OMV_CSI_POWER_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_LOW, -1); - #endif - - NVIC_SetPriority(CAM_IRQ_IRQn, IRQ_PRI_CSI); return 0; } diff --git a/ports/alif/alif_hal.h b/ports/alif/alif_hal.h index 9ce25f618..3a7f9ecef 100644 --- a/ports/alif/alif_hal.h +++ b/ports/alif/alif_hal.h @@ -40,5 +40,5 @@ int alif_hal_spi_init(uint32_t bus_id, bool nss_enable, uint32_t nss_pol); int alif_hal_spi_deinit(uint32_t bus_id); int alif_hal_pdm_init(uint32_t pdm_id); int alif_hal_pdm_deinit(uint32_t pdm_id); -int alif_hal_csi_init(CPI_Type *cpi, uint32_t mode); +int alif_hal_csi_init(CPI_Type *cpi); #endif //__ALIF_HAL_H__ diff --git a/ports/alif/omv_csi.c b/ports/alif/omv_csi.c index de43a9c6a..85c215efe 100644 --- a/ports/alif/omv_csi.c +++ b/ports/alif/omv_csi.c @@ -71,6 +71,66 @@ CAM_INTR_OUTFIFO_OVERRUN | \ CAM_INTR_BRESP_ERR) +static uint32_t omv_csi_get_fb_offset(omv_csi_t *csi); + +void CAM_IRQHandler(void) { + uint32_t mask = 0; + omv_csi_t *csi = omv_csi_get(-1); + CPI_Type *cpi = csi->base; + + uint32_t status = cpi_get_interrupt_status(cpi); + + if (status & CAM_INTR_VSYNC) { + mask |= CAM_INTR_VSYNC; + } + + if (status & CAM_INTR_HSYNC) { + mask |= CAM_INTR_HSYNC; + } + + if (status & CAM_INTR_INFIFO_OVERRUN) { + mask |= CAM_INTR_INFIFO_OVERRUN; + omv_csi_abort(csi, true, true); + } + + if (status & CAM_INTR_OUTFIFO_OVERRUN) { + mask |= CAM_INTR_OUTFIFO_OVERRUN; + omv_csi_abort(csi, true, true); + } + + if (status & CAM_INTR_BRESP_ERR) { + mask |= CAM_INTR_BRESP_ERR; + omv_csi_abort(csi, true, true); + } + + if (status & CAM_INTR_STOP) { + mask |= CAM_INTR_STOP; + cpi->CAM_CTRL = 0; + if (!(status & CPI_ERROR_FLAGS)) { + // Release the current framebuffer. + framebuffer_get_tail(csi->fb, FB_NO_FLAGS); + } + + // Get the current framebuffer (or new tail). + vbuffer_t *buffer = framebuffer_get_tail(csi->fb, FB_PEEK); + + if (buffer != NULL) { + cpi->CAM_CTRL = 0; + cpi->CAM_CTRL = CAM_CTRL_SW_RESET; + cpi->CAM_FRAME_ADDR = LocalToGlobal(buffer->data + omv_csi_get_fb_offset(csi)); + cpi_irq_handler_clear_intr_status(cpi, mask); + cpi->CAM_CTRL = (CAM_CTRL_SNAPSHOT | CAM_CTRL_START | CAM_CTRL_FIFO_CLK_SEL); + } + + if (csi->frame_cb.fun && !(status & CPI_ERROR_FLAGS)) { + csi->frame_cb.fun(csi->frame_cb.arg); + } + } + + // Clear interrupts. + cpi_irq_handler_clear_intr_status(cpi, mask); +} + int alif_csi_config(omv_csi_t *csi, omv_csi_config_t config) { if (config == OMV_CSI_CONFIG_INIT) { CPI_Type *cpi = csi->base; @@ -235,13 +295,13 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) { cpi_irq_handler_clear_intr_status(cpi, CPI_IRQ_FLAGS); cpi_enable_interrupt(cpi, CPI_IRQ_FLAGS); NVIC_ClearPendingIRQ(CAM_IRQ_IRQn); + NVIC_SetPriority(CAM_IRQ_IRQn, IRQ_PRI_CSI); NVIC_EnableIRQ(CAM_IRQ_IRQn); // Reset CSI and start the capture. cpi->CAM_CTRL = 0; - cpi->CAM_CTRL |= CAM_CTRL_SW_RESET; + cpi->CAM_CTRL = CAM_CTRL_SW_RESET; cpi->CAM_CTRL = (CAM_CTRL_SNAPSHOT | CAM_CTRL_START | CAM_CTRL_FIFO_CLK_SEL); - //printf("==== reconfigured ===\n"); } // Let the camera know we want to trigger it now. @@ -364,126 +424,11 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) { return 0; } -int omv_csi_init() { - int init_ret = 0; - static omv_i2c_t i2c; - CPI_Type *base = ((CPI_Type *) CPI_BASE); - - alif_hal_csi_init(base, 0); - - #if defined(OMV_CSI_POWER_PIN) - omv_gpio_write(OMV_CSI_POWER_PIN, 0); - #endif - - #if defined(OMV_CSI_RESET_PIN) - omv_gpio_write(OMV_CSI_RESET_PIN, 0); - #endif - - // Initialize the CSIs using this driver's ops as defaults, - // which can be overridden by sensor drivers during probe. - for (size_t i=0; ii2c = &i2c; - csi->fb = framebuffer_get(-1); - csi->base = base; - csi->abort = alif_csi_abort; - csi->config = alif_csi_config; - csi->snapshot = alif_csi_snapshot; - csi->color_palette = rainbow_table; - } - - // Configure the CSI external clock. - if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) { - // Failed to initialize the csi clock. - return OMV_CSI_ERROR_TIM_INIT_FAILED; - } - - // Initialize the camera bus. - omv_i2c_init(&i2c, OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED); - - // Detect and initialize the image csi. - if ((init_ret = omv_csi_probe(&i2c)) != 0) { - // csi probe/init failed. - return init_ret; - } - - // Configure the DCMI interface. - for (size_t i=0; idetected = true; - } - - // Clear fb_enabled flag. - JPEG_FB()->enabled = 0; - +int omv_csi_ops_init(omv_csi_t *csi) { + csi->base = OMV_CSI_BASE; + csi->abort = alif_csi_abort; + csi->config = alif_csi_config; + csi->snapshot = alif_csi_snapshot; return 0; } - -void CAM_IRQHandler(void) { - uint32_t mask = 0; - omv_csi_t *csi = omv_csi_get(-1); - CPI_Type *cpi = csi->base; - - uint32_t status = cpi_get_interrupt_status(cpi); - - if (status & CAM_INTR_VSYNC) { - mask |= CAM_INTR_VSYNC; - } - - if (status & CAM_INTR_HSYNC) { - mask |= CAM_INTR_HSYNC; - } - - if (status & CAM_INTR_INFIFO_OVERRUN) { - mask |= CAM_INTR_INFIFO_OVERRUN; - omv_csi_abort(csi, true, true); - printf("INFIFO_OVERRUN\n"); - } - - if (status & CAM_INTR_OUTFIFO_OVERRUN) { - mask |= CAM_INTR_OUTFIFO_OVERRUN; - omv_csi_abort(csi, true, true); - printf("OUTFIFO_OVERRUN\n"); - } - - if (status & CAM_INTR_BRESP_ERR) { - mask |= CAM_INTR_BRESP_ERR; - omv_csi_abort(csi, true, true); - printf("BRESP_ERR %lu\n", cpi->CAM_AXI_ERR_STAT); - } - - if (status & CAM_INTR_STOP) { - mask |= CAM_INTR_STOP; - cpi->CAM_CTRL = 0; - if (!(status & CPI_ERROR_FLAGS)) { - // Release the current framebuffer. - framebuffer_get_tail(csi->fb, FB_NO_FLAGS); - } - - // Get the current framebuffer (or new tail). - vbuffer_t *buffer = framebuffer_get_tail(csi->fb, FB_PEEK); - - if (buffer != NULL) { - cpi->CAM_CTRL = 0; - cpi->CAM_CTRL |= CAM_CTRL_SW_RESET; - cpi->CAM_FRAME_ADDR = LocalToGlobal(buffer->data + omv_csi_get_fb_offset(csi)); - cpi_irq_handler_clear_intr_status(cpi, mask); - cpi->CAM_CTRL = (CAM_CTRL_SNAPSHOT | CAM_CTRL_START | CAM_CTRL_FIFO_CLK_SEL); - } - - if (csi->frame_cb.fun && !(status & CPI_ERROR_FLAGS)) { - csi->frame_cb.fun(csi->frame_cb.arg); - } - } - - // Clear interrupts. - cpi_irq_handler_clear_intr_status(cpi, mask); -} #endif // MICROPY_PY_CSI diff --git a/ports/mimxrt/mimxrt_hal.c b/ports/mimxrt/mimxrt_hal.c index 6341e08c6..ece702208 100644 --- a/ports/mimxrt/mimxrt_hal.c +++ b/ports/mimxrt/mimxrt_hal.c @@ -107,6 +107,11 @@ void mimxrt_hal_init() { edma_config_t edma_config = {0}; EDMA_GetDefaultConfig(&edma_config); EDMA_Init(DMA0, &edma_config); + + #if MICROPY_PY_CSI + // Enable CSI clock and configure pins. + mimxrt_hal_csi_init(CSI); + #endif } void mimxrt_hal_bootloader() { @@ -118,9 +123,10 @@ void mimxrt_hal_bootloader() { } int mimxrt_hal_csi_init(CSI_Type *inst) { + // Enable CSI clock. CLOCK_EnableClock(kCLOCK_Csi); - // Configure DCMI pins. + // Configure CSI pins. omv_gpio_config(OMV_CSI_D0_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_MED, -1); omv_gpio_config(OMV_CSI_D1_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_MED, -1); omv_gpio_config(OMV_CSI_D2_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_MED, -1); @@ -135,20 +141,6 @@ int mimxrt_hal_csi_init(CSI_Type *inst) { omv_gpio_config(OMV_CSI_VSYNC_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_MED, -1); omv_gpio_config(OMV_CSI_PXCLK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_MED, -1); - // Configure DCMI GPIOs - #if defined(OMV_CSI_RESET_PIN) - omv_gpio_config(OMV_CSI_RESET_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_DOWN, OMV_GPIO_SPEED_LOW, -1); - #endif - #if defined(OMV_CSI_FSYNC_PIN) - omv_gpio_config(OMV_CSI_FSYNC_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_DOWN, OMV_GPIO_SPEED_LOW, -1); - #endif - #if defined(OMV_CSI_POWER_PIN) - omv_gpio_config(OMV_CSI_POWER_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_LOW, -1); - #endif - - // Configure IRQ priority. - NVIC_SetPriority(CSI_IRQn, IRQ_PRI_CSI); - return 0; } diff --git a/ports/mimxrt/omv_csi.c b/ports/mimxrt/omv_csi.c index dc18b6447..c182c7c7f 100644 --- a/ports/mimxrt/omv_csi.c +++ b/ports/mimxrt/omv_csi.c @@ -56,9 +56,8 @@ extern uint8_t _line_buf[OMV_LINE_BUF_SIZE]; int imx_csi_config(omv_csi_t *csi, omv_csi_config_t config) { if (config == OMV_CSI_CONFIG_INIT) { + // Reset and configure CSI. CSI_Reset(CSI); - NVIC_DisableIRQ(CSI_IRQn); - // CSI_Reset does not zero CR1. CSI_REG_CR1(CSI) = 0; // CSI mode: HSYNC, VSYNC, and PIXCLK signals are used. @@ -94,8 +93,11 @@ int imx_csi_config(omv_csi_t *csi, omv_csi_config_t config) { } static int imx_csi_abort(omv_csi_t *csi, bool fifo_flush, bool in_irq) { - NVIC_DisableIRQ(CSI_IRQn); + // Disable CSI interrupts. CSI_DisableInterrupts(CSI, CSI_IRQ_FLAGS); + NVIC_DisableIRQ(CSI_IRQn); + NVIC_ClearPendingIRQ(CSI_IRQn); + CSI_REG_CR3(CSI) &= ~CSI_CR3_DMA_REQ_EN_RFF_MASK; CSI_REG_CR18(CSI) &= ~CSI_CR18_CSI_ENABLE_MASK; csi->dest_inc = 0; @@ -395,8 +397,10 @@ int imx_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) { (dma_line_bytes << CSI_IMAG_PARA_IMAGE_WIDTH_SHIFT) | (1 << CSI_IMAG_PARA_IMAGE_HEIGHT_SHIFT); - // Configure and enable CSI interrupts. + // Enable CSI interrupts. CSI_EnableInterrupts(CSI, CSI_IRQ_FLAGS); + NVIC_ClearPendingIRQ(CSI_IRQn); + NVIC_SetPriority(CSI_IRQn, IRQ_PRI_CSI); NVIC_EnableIRQ(CSI_IRQn); // Enable CSI @@ -499,60 +503,10 @@ int imx_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) { return 0; } -int omv_csi_init() { - int init_ret = 0; - static omv_i2c_t i2c; - - mimxrt_hal_csi_init(CSI); - - #if defined(OMV_CSI_POWER_PIN) - omv_gpio_write(OMV_CSI_POWER_PIN, 1); - #endif - - #if defined(OMV_CSI_RESET_PIN) - omv_gpio_write(OMV_CSI_RESET_PIN, 1); - #endif - - // Initialize the CSIs using this driver's ops as defaults, - // which can be overridden by sensor drivers during probe. - for (size_t i=0; ii2c = &i2c; - csi->fb = framebuffer_get(-1); - csi->abort = imx_csi_abort; - csi->config = imx_csi_config; - csi->snapshot = imx_csi_snapshot; - csi->color_palette = rainbow_table; - } - - // Configure the csi external clock (XCLK). - if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) { - // Failed to initialize the csi clock. - return OMV_CSI_ERROR_TIM_INIT_FAILED; - } - - // Initialize the camera bus. - omv_i2c_init(&i2c, OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED); - - // Detect and initialize the image sensor. - if ((init_ret = omv_csi_probe(&i2c)) != 0) { - // Sensor probe/init failed. - return init_ret; - } - - // Configure the CSI interfaces. - for (size_t i=0; ienabled = 0; +int omv_csi_ops_init(omv_csi_t *csi) { + csi->abort = imx_csi_abort; + csi->config = imx_csi_config; + csi->snapshot = imx_csi_snapshot; return 0; } #endif // MICROPY_PY_CSI diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 6d12e0d39..b0debe3c6 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -91,13 +91,19 @@ #include "omv_csi.h" #include "mp_utils.h" +extern uint32_t _heap_start; +extern uint32_t _heap_end; + uint32_t HAL_GetHalVersion() { // Hard-coded because it's not defined in SDK return ((2 << 24) | (0 << 16) | (0 << 8) | (0 << 0)); } -extern uint32_t _heap_start; -extern uint32_t _heap_end; +void NORETURN __fatal_error(const char *msg) { + while (1) { + ; + } +} #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE static int vfs_mount_and_chdir(mp_obj_t bdev, mp_obj_t mount_point) { @@ -142,6 +148,7 @@ soft_reset: machine_init(); mp_init(); readline_init0(); + pin_init0(); #if MICROPY_PY_MACHINE_SPI spi_init0(); #endif @@ -163,13 +170,20 @@ soft_reset: #if MICROPY_PY_MACHINE_UART uart_init0(); #endif - pin_init0(); - fb_alloc_init0(); framebuffer_init0(); + #if MICROPY_PY_CSI + omv_csi_init0(); + #endif #if MICROPY_PY_CSI - omv_csi_init(); + // Initialize the csi. + if (first_soft_reset) { + int ret = omv_csi_init(); + if (ret != 0 && ret != OMV_CSI_ERROR_ISC_UNDETECTED) { + __fatal_error("Failed to init the CSI"); + } + } #endif #if (MICROPY_PY_BLE_NUS == 0) && (MICROPY_HW_USB_CDC == 0) @@ -372,7 +386,6 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); #endif #endif - void HardFault_Handler(void) { #if defined(NRF52_SERIES) || defined(NRF91_SERIES) static volatile uint32_t reg; @@ -389,12 +402,6 @@ void HardFault_Handler(void) { #endif } -void NORETURN __fatal_error(const char *msg) { - while (1) { - ; - } -} - void nlr_jump_fail(void *val) { printf("FATAL: uncaught exception %p\n", val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t) val); diff --git a/ports/nrf/omv_csi.c b/ports/nrf/omv_csi.c index 041e8ecc8..908e02b0a 100644 --- a/ports/nrf/omv_csi.c +++ b/ports/nrf/omv_csi.c @@ -206,60 +206,8 @@ static int nrf_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) { return 0; } -int omv_csi_init() { - int init_ret = 0; - static omv_i2c_t i2c; - - #if defined(OMV_CSI_POWER_PIN) - nrf_gpio_cfg_output(OMV_CSI_POWER_PIN); - nrf_gpio_pin_write(OMV_CSI_POWER_PIN, 1); - #endif - - #if defined(OMV_CSI_RESET_PIN) - nrf_gpio_cfg_output(OMV_CSI_RESET_PIN); - nrf_gpio_pin_write(OMV_CSI_RESET_PIN, 1); - #endif - - // Initialize the CSIs using this driver's ops as defaults, - // which can be overridden by sensor drivers during probe. - for (size_t i=0; ii2c = &i2c; - csi->fb = framebuffer_get(-1); - csi->abort = NULL; - csi->config = nrf_csi_config; - csi->snapshot = nrf_csi_snapshot; - csi->color_palette = rainbow_table; - } - - // Configure the csi external clock (XCLK). - if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) { - // Failed to initialize the csi clock. - return OMV_CSI_ERROR_TIM_INIT_FAILED; - } - - // Initialize the camera bus. - omv_i2c_init(&i2c, OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED); - - // Detect and initialize the image sensor. - if ((init_ret = omv_csi_probe(&i2c)) != 0) { - // Sensor probe/init failed. - return init_ret; - } - - // Configure the CSI interfaces. - for (size_t i=0; ienabled = 0; - +int omv_csi_ops_init(omv_csi_t *csi) { + csi->config = nrf_csi_config; + csi->snapshot = nrf_csi_snapshot; return 0; } diff --git a/ports/rp2/main.c b/ports/rp2/main.c index 5aefabbb9..b0c54121f 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -179,14 +179,21 @@ soft_reset: fb_alloc_init0(); framebuffer_init0(); + #if MICROPY_PY_CSI + omv_csi_init0(); + #endif #if MICROPY_PY_FIR py_fir_init0(); #endif // MICROPY_PY_FIR #if MICROPY_PY_CSI - if (omv_csi_init() != 0) { - printf("csi init failed!\n"); + // Initialize the csi. + if (first_soft_reset) { + int ret = omv_csi_init(); + if (ret != 0 && ret != OMV_CSI_ERROR_ISC_UNDETECTED) { + __fatal_error("Failed to init the CSI"); + } } #endif diff --git a/ports/rp2/omv_csi.c b/ports/rp2/omv_csi.c index 1b0a37357..2734e7f24 100644 --- a/ports/rp2/omv_csi.c +++ b/ports/rp2/omv_csi.c @@ -68,6 +68,18 @@ static void dma_irq_handler() { static int rp2_csi_config(omv_csi_t *csi, omv_csi_config_t config) { if (config == OMV_CSI_CONFIG_INIT) { + // PIXCLK + gpio_init(OMV_CSI_PXCLK_PIN); + gpio_set_dir(OMV_CSI_PXCLK_PIN, GPIO_IN); + + // HSYNC + gpio_init(OMV_CSI_HSYNC_PIN); + gpio_set_dir(OMV_CSI_HSYNC_PIN, GPIO_IN); + + // VSYNC + gpio_init(OMV_CSI_VSYNC_PIN); + gpio_set_dir(OMV_CSI_VSYNC_PIN, GPIO_IN); + // Install new DMA IRQ handler. irq_set_enabled(OMV_CSI_DMA_IRQ, false); @@ -213,76 +225,10 @@ static int rp2_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) { return 0; } -int omv_csi_init() { - int init_ret = 0; - static omv_i2c_t i2c; - - // PIXCLK - gpio_init(OMV_CSI_PXCLK_PIN); - gpio_set_dir(OMV_CSI_PXCLK_PIN, GPIO_IN); - - // HSYNC - gpio_init(OMV_CSI_HSYNC_PIN); - gpio_set_dir(OMV_CSI_HSYNC_PIN, GPIO_IN); - - // VSYNC - gpio_init(OMV_CSI_VSYNC_PIN); - gpio_set_dir(OMV_CSI_VSYNC_PIN, GPIO_IN); - - #if defined(OMV_CSI_POWER_PIN) - gpio_init(OMV_CSI_POWER_PIN); - gpio_set_dir(OMV_CSI_POWER_PIN, GPIO_OUT); - gpio_pull_down(OMV_CSI_POWER_PIN); - gpio_put(OMV_CSI_POWER_PIN, 1); - #endif - - #if defined(OMV_CSI_RESET_PIN) - gpio_init(OMV_CSI_RESET_PIN); - gpio_set_dir(OMV_CSI_RESET_PIN, GPIO_OUT); - gpio_pull_up(OMV_CSI_RESET_PIN); - gpio_put(OMV_CSI_RESET_PIN, 1); - #endif - - // Initialize the CSIs using this driver's ops as defaults, - // which can be overridden by sensor drivers during probe. - for (size_t i=0; ii2c = &i2c; - csi->fb = framebuffer_get(-1); - csi->abort = rp2_csi_abort; - csi->config = rp2_csi_config; - csi->snapshot = rp2_csi_snapshot; - csi->color_palette = rainbow_table; - } - - // Configure the csi external clock (XCLK). - if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) { - // Failed to initialize the csi clock. - return OMV_CSI_ERROR_TIM_INIT_FAILED; - } - - // Initialize the camera bus. - omv_i2c_init(&i2c, OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED); - - // Detect and initialize the image sensor. - if ((init_ret = omv_csi_probe(&i2c)) != 0) { - // Sensor probe/init failed. - return init_ret; - } - - // Configure the DCMI interface. - for (size_t i=0; ienabled = 0; +int omv_csi_ops_init(omv_csi_t *csi) { + csi->abort = rp2_csi_abort; + csi->config = rp2_csi_config; + csi->snapshot = rp2_csi_snapshot; return 0; } #endif // MICROPY_PY_CSI diff --git a/ports/stm32/omv_csi.c b/ports/stm32/omv_csi.c index 53a90b539..ece7acafe 100644 --- a/ports/stm32/omv_csi.c +++ b/ports/stm32/omv_csi.c @@ -1067,65 +1067,10 @@ static int stm_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) { return 0; } -int omv_csi_init() { - int ret = 0; - static omv_i2c_t i2c; - - // List of I2C buses to scan. - uint32_t buses[][2] = { - {OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED}, - #if defined(OMV_CSI_I2C_ALT_ID) - {OMV_CSI_I2C_ALT_ID, OMV_CSI_I2C_ALT_SPEED}, - #endif - }; - - // Initialize the CSIs using this driver's ops as defaults, - // which can be overridden by sensor drivers during probe. - for (size_t i=0; ii2c = &i2c; - csi->fb = framebuffer_get(-1); - csi->abort = stm_csi_abort; - csi->config = stm_csi_config; - csi->shutdown = stm_csi_shutdown; - csi->snapshot = stm_csi_snapshot; - csi->color_palette = rainbow_table; - } - - // Configure the csi external clock (XCLK). - if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) { - return OMV_CSI_ERROR_TIM_INIT_FAILED; - } - - // Detect and initialize sensor(s). - for (uint32_t i = 0, n_buses = OMV_ARRAY_SIZE(buses); i < n_buses; i++) { - // Initialize the camera bus. - omv_i2c_init(&i2c, buses[i][0], buses[i][1]); - - if (!(ret = omv_csi_probe(&i2c))) { - break; - } - - omv_i2c_deinit(&i2c); - - // Scan the next bus or fail if this is the last one. - if ((i + 1) == n_buses) { - return ret; - } - } - - // Configure the DCMI interface. - for (size_t i=0; ienabled = 0; +int omv_csi_ops_init(omv_csi_t *csi) { + csi->abort = stm_csi_abort; + csi->config = stm_csi_config; + csi->shutdown = stm_csi_shutdown; + csi->snapshot = stm_csi_snapshot; return 0; } diff --git a/ports/stm32/stm32_hal_msp.c b/ports/stm32/stm32_hal_msp.c index 445e84d24..45f3c4b6f 100644 --- a/ports/stm32/stm32_hal_msp.c +++ b/ports/stm32/stm32_hal_msp.c @@ -271,16 +271,6 @@ void HAL_MspInit(void) { OMV_AXI_QOS_LTDC_W_SET(OMV_AXI_QOS_LTDC_W_PRI); #endif - #if defined(OMV_CSI_RESET_PIN) - omv_gpio_config(OMV_CSI_RESET_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_DOWN, OMV_GPIO_SPEED_LOW, -1); - #endif - #if defined(OMV_CSI_FSYNC_PIN) - omv_gpio_config(OMV_CSI_FSYNC_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_DOWN, OMV_GPIO_SPEED_LOW, -1); - #endif - #if defined(OMV_CSI_POWER_PIN) - omv_gpio_config(OMV_CSI_POWER_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_LOW, -1); - #endif - #if defined(OMV_FIR_LEPTON_RESET_PIN) omv_gpio_config(OMV_FIR_LEPTON_RESET_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_LOW, -1); omv_gpio_write(OMV_FIR_LEPTON_RESET_PIN, 0);