Merge pull request #2743 from openmv/add_csi_shutdown
Some checks are pending
🔥 Firmware Build / build-firmware (ARDUINO_GIGA) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_33_BLE_SENSE) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_RP2040_CONNECT) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NICLA_VISION) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_PORTENTA_H7) (push) Waiting to run
🔥 Firmware Build / build-firmware (DOCKER) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV2) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4P) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMVPT) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_AE3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_N6) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_RT1060) (push) Waiting to run
🔥 Firmware Build / code-size-report (push) Blocked by required conditions
🔥 Firmware Build / stable-release (push) Blocked by required conditions
🔥 Firmware Build / development-release (push) Blocked by required conditions

common/csi: Add csi shutdown op.
This commit is contained in:
Ibrahim Abdelkader 2025-07-01 00:51:36 +03:00 committed by GitHub
commit 7bd8c2ce53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 198 additions and 167 deletions

View File

@ -50,7 +50,7 @@
#define OMV_LEPTON_ENABLE (1)
#define OMV_PAG7936_ENABLE (1)
#define OMV_PAG7936_MIPI_CSI2 (1)
#define OMV_SOFTCSI_ENABLE (0)
#define OMV_SOFTCSI_ENABLE (1)
#define OMV_PS5520_ENABLE (1)
#define OMV_GENX320_EHC_ENABLE (1)
#define OMV_GENX320_HSYNC_VALUE (0x1)

View File

@ -130,9 +130,6 @@ __weak void omv_csi_init0() {
continue;
}
// Abort ongoing transfer
omv_csi_abort(csi, true, false);
// Reset delays
csi->disable_delays = false;
@ -202,9 +199,23 @@ __weak int omv_csi_abort(omv_csi_t *csi, bool fifo_flush, bool in_irq) {
return 0;
}
void omv_csi_abort_all(void) {
for (size_t i=0; i<OMV_CSI_MAX_DEVICES; i++) {
omv_csi_t *csi = &csi_all[i];
// Abort ongoing transfer
if (csi->detected) {
omv_csi_abort(csi, true, false);
}
}
}
__weak int omv_csi_reset(omv_csi_t *csi, bool hard) {
// Disable any ongoing frame capture.
omv_csi_abort(csi, true, false);
if (csi->power_on) {
omv_csi_abort(csi, true, false);
}
// Reset the csi state
csi->sde = 0;
@ -224,16 +235,15 @@ __weak int omv_csi_reset(omv_csi_t *csi, bool hard) {
#else
csi->auto_rotation = false;
#endif // MICROPY_PY_IMU
csi->vsync_cb = (omv_csi_cb_t) { NULL, NULL };
csi->frame_cb = (omv_csi_cb_t) { NULL, NULL };
// Reset default color palette.
csi->color_palette = rainbow_table;
csi->disable_full_flush = false;
csi->vsync_cb = (omv_csi_cb_t) { NULL, NULL };
csi->frame_cb = (omv_csi_cb_t) { NULL, NULL };
// Restore shutdown state on reset.
omv_csi_shutdown(csi, false);
if (!csi->power_on) {
omv_csi_shutdown(csi, false);
}
if (hard) {
// Disable the bus before reset.
@ -437,22 +447,21 @@ int omv_csi_probe(omv_i2c_t *i2c) {
// Initialize detected sensors.
for (size_t i=0; i<dev_count; i++) {
omv_csi_t *csi = &csi_all[i];
sensor_init_t init_fun = NULL;
csi->detected = true;
csi->power_on = true;
csi->power_pol = power_pol;
csi->reset_pol = reset_pol;
csi->chip_id = dev_list[i].chip_id;
csi->slv_addr = dev_list[i].slv_addr;
csi->detected = true;
uint32_t clk_hz = 0;
sensor_init_t init_fun = NULL;
// Find the sensors init function.
for (size_t i=0; i<OMV_ARRAY_SIZE(sensor_config_table); i++) {
const sensor_config_t *config = &sensor_config_table[i];
if (csi->chip_id == config->chip_id) {
clk_hz = config->clk_hz;
init_fun = config->init_fun;
csi->clk_hz = config->clk_hz;
break;
}
}
@ -466,35 +475,34 @@ int omv_csi_probe(omv_i2c_t *i2c) {
// Special case for OV5640.
#if (OMV_OV5640_REV_Y_CHECK == 1)
if (csi->chip_id == OV5640_ID && HAL_GetREVID() < 0x2003) {
clk_hz = OMV_OV5640_REV_Y_FREQ;
csi->clk_hz = OMV_OV5640_REV_Y_FREQ;
}
#endif
// Allow reconfiguring (or disabling) the external clock
// if just one sensor is detected, or for main sensors.
if (dev_count == 1 || !csi->auxiliary) {
omv_csi_set_clk_frequency(clk_hz);
omv_csi_set_clk_frequency(csi->clk_hz);
}
// Count aux devices.
aux_count += csi->auxiliary;
}
// Special case: A single aux sensor was detected, clear
// the auxiliary flag so it gets used as the main sensor.
if (dev_count == 1 && csi_all[0].auxiliary) {
csi_all[0].auxiliary = 0;
aux_count--;
}
// Special case: Soft-CSI and another aux sensor detected,
// (Lepton for example). Use Soft-CSI for the main sensor.
// Special case: all detected sensors are aux (e.g., Soft-CSI or
// Soft-CSI + Lepton). If only one is found, use it as main. If
// multiple, pick the first non-Soft-CSI sensor as main.
if (dev_count == aux_count) {
for (size_t i=0; i<dev_count; i++) {
omv_csi_t *csi = &csi_all[i];
if (csi->chip_id == SOFTCSI_ID) {
csi->auxiliary = 0;
if (dev_count == 1 || csi->chip_id != SOFTCSI_ID) {
aux_count--;
csi->auxiliary = 0;
// If more than one aux sensor was detected, the clock
// hasn't been changed, so reconfigure using this freq.
if (dev_count > 1) {
omv_csi_set_clk_frequency(csi->clk_hz);
}
break;
}
}
@ -576,10 +584,18 @@ __weak int omv_csi_shutdown(omv_csi_t *csi, int enable) {
} else {
omv_gpio_write(OMV_CSI_POWER_PIN, 1);
}
mp_hal_delay_ms(OMV_CSI_POWER_DELAY);
}
#endif
mp_hal_delay_ms(10);
// Call csi-specific shutdown function
if (csi->shutdown != NULL &&
csi->shutdown(csi, enable) != 0) {
return OMV_CSI_ERROR_CTL_FAILED;
}
// Update power-on flag.
csi->power_on = !enable;
return ret;
}

View File

@ -115,9 +115,10 @@ typedef enum {
typedef enum {
OMV_CSI_CONFIG_INIT = (1 << 0),
OMV_CSI_CONFIG_FRAMESIZE = (1 << 1),
OMV_CSI_CONFIG_PIXFORMAT = (1 << 2),
OMV_CSI_CONFIG_WINDOWING = (1 << 3),
OMV_CSI_CONFIG_DEINIT = (1 << 1),
OMV_CSI_CONFIG_FRAMESIZE = (1 << 2),
OMV_CSI_CONFIG_PIXFORMAT = (1 << 3),
OMV_CSI_CONFIG_WINDOWING = (1 << 4),
} omv_csi_config_t;
typedef enum {
@ -337,6 +338,8 @@ typedef struct _omv_csi {
bool transpose; // Transpose Image
bool auto_rotation; // Rotate Image Automatically
bool detected; // Set to true when the sensor is initialized.
bool power_on; // Set to true when the sensor is active.
uint32_t clk_hz; // Clock frequency requested by the driver.
omv_i2c_t *i2c; // SCCB/I2C bus.
framebuffer_t *fb; // Frame buffer pointer
@ -354,6 +357,7 @@ typedef struct _omv_csi {
// Sensor function pointers
int (*reset) (omv_csi_t *csi);
int (*sleep) (omv_csi_t *csi, int enable);
int (*shutdown) (omv_csi_t *csi, int enable);
int (*match) (omv_csi_t *csi, size_t id);
int (*read_reg) (omv_csi_t *csi, uint16_t reg_addr);
int (*write_reg) (omv_csi_t *csi, uint16_t reg_addr, uint16_t reg_data);
@ -413,6 +417,9 @@ int omv_csi_config(omv_csi_t *csi, omv_csi_config_t config);
// Abort frame capture and disable IRQs, DMA etc..
int omv_csi_abort(omv_csi_t *csi, bool fifo_flush, bool in_irq);
// Call on soft-reboot
void omv_csi_abort_all(void);
// Reset the sensor to its default state.
int omv_csi_reset(omv_csi_t *csi, bool hard);

View File

@ -136,10 +136,8 @@ void vospi_callback(omv_spi_t *spi, void *userdata, void *buf) {
|| (!vospi_check_crc(base))
#endif
|| (vospi.lepton_3 && (pid == VOSPI_SPECIAL_PACKET) && (sid != vospi.sid))) {
vospi.pid = 0;
vospi.sid = 0;
omv_spi_transfer_abort(&vospi.spi_bus);
vospi.flags |= VOSPI_FLAGS_RESYNC;
vospi_abort();
vospi.flags |= VOSPI_FLAGS_CAPTURE;
return;
}
@ -196,6 +194,15 @@ int vospi_deinit() {
return omv_spi_deinit(&vospi.spi_bus);
}
int vospi_abort(void) {
vospi.flags &= ~VOSPI_FLAGS_CAPTURE;
int ret = omv_spi_transfer_abort(&vospi.spi_bus);
vospi.pid = 0;
vospi.sid = 0;
vospi.flags |= VOSPI_FLAGS_RESYNC;
return ret;
}
bool vospi_active(void) {
return vospi.flags & VOSPI_FLAGS_CAPTURE;
}
@ -224,10 +231,7 @@ int vospi_snapshot(uint32_t timeout_ms) {
}
if ((mp_hal_ticks_ms() - tick_start) > timeout_ms) {
omv_spi_transfer_abort(&vospi.spi_bus);
vospi.pid = 0;
vospi.sid = 0;
vospi.flags = VOSPI_FLAGS_RESYNC;
vospi_abort();
return -1;
}

View File

@ -28,6 +28,7 @@
#include "framebuffer.h"
int vospi_init(uint32_t n_packets, framebuffer_t *fb);
int vospi_deinit();
int vospi_abort(void);
bool vospi_active(void);
int vospi_snapshot(uint32_t timeout_ms);
#endif // __VOSPI_H__

View File

@ -129,7 +129,8 @@ extern "C"
#define LEP_I2C_DATA_BUFFER_1_LENGTH 0x400
#define LEP_I2C_STATUS_BUSY_BIT_MASK 0x0001 /* Bit 0 is the Busy Bit */
#define LEP_I2C_STATUS_BOOT_MODE_MASK 0x0002 /* Bit 1 is the boot mode */
#define LEP_I2C_STATUS_BOOT_STAT_MASK 0x0004 /* Bit 2 is the boot status */
/******************************************************************************/
/** EXPORTED TYPE DEFINITIONS **/

View File

@ -43,9 +43,10 @@
#include "LEPTON_RAD.h"
#include "LEPTON_I2C_Reg.h"
#define LEPTON_BOOT_TIMEOUT (1000)
#define LEPTON_BOOT_TIMEOUT (3000)
#define LEPTON_SNAPSHOT_RETRY (3)
#define LEPTON_SNAPSHOT_TIMEOUT (5000)
#define LEPTON_I2C_STATUS_BOOT (LEP_I2C_STATUS_BOOT_MODE_MASK | LEP_I2C_STATUS_BOOT_STAT_MASK)
// Min/Max temperatures in Celsius.
#define LEPTON_MIN_TEMP_NORM (-10.0f)
@ -271,23 +272,18 @@ static int ioctl(omv_csi_t *csi, int request, va_list ap) {
static int lepton_reset(omv_csi_t *csi, bool measurement_mode, bool high_temp_mode) {
LEP_RAD_ENABLE_E rad;
LEP_AGC_ROI_T roi;
memset(&lepton.port, 0, sizeof(LEP_CAMERA_PORT_DESC_T));
if (!csi->auxiliary) {
omv_gpio_write(OMV_CSI_POWER_PIN, 0);
mp_hal_delay_ms(10);
omv_gpio_write(OMV_CSI_POWER_PIN, 1);
mp_hal_delay_ms(10);
omv_gpio_write(OMV_CSI_RESET_PIN, 0);
mp_hal_delay_ms(10);
mp_hal_delay_ms(100);
omv_gpio_write(OMV_CSI_RESET_PIN, 1);
mp_hal_delay_ms(1000);
mp_hal_delay_ms(2500);
}
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(1)) {
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
if (LEP_OpenPort(csi->i2c, LEP_CCI_TWI, 0, &lepton.port) == LEP_OK) {
break;
}
@ -299,31 +295,14 @@ static int lepton_reset(omv_csi_t *csi, bool measurement_mode, bool high_temp_mo
if (csi->auxiliary) {
LEP_RunOemReboot(&lepton.port);
mp_hal_delay_ms(1000);
mp_hal_delay_ms(1500);
}
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(1)) {
LEP_SDK_BOOT_STATUS_E status;
if (LEP_GetCameraBootStatus(&lepton.port, &status) != LEP_OK) {
return -1;
}
if (status == LEP_BOOT_STATUS_BOOTED) {
break;
}
if ((mp_hal_ticks_ms() - start) >= LEPTON_BOOT_TIMEOUT) {
return -1;
}
}
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(1)) {
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
LEP_UINT16 status;
if (LEP_DirectReadRegister(&lepton.port, LEP_I2C_STATUS_REG, &status) != LEP_OK) {
return -1;
}
LEP_DirectReadRegister(&lepton.port, LEP_I2C_STATUS_REG, &status);
if (!(status & LEP_I2C_STATUS_BUSY_BIT_MASK)) {
if (status == LEPTON_I2C_STATUS_BOOT) {
break;
}
@ -332,23 +311,16 @@ static int lepton_reset(omv_csi_t *csi, bool measurement_mode, bool high_temp_mo
}
}
if (LEP_GetRadEnableState(&lepton.port, &rad) != LEP_OK
|| LEP_GetAgcROI(&lepton.port, &roi) != LEP_OK) {
return -1;
}
// Use the low gain mode to enable high temperature readings (~450C) on Lepton 3.5
LEP_SYS_GAIN_MODE_E gain_mode = lepton.high_temp_mode ? LEP_SYS_GAIN_MODE_LOW : LEP_SYS_GAIN_MODE_HIGH;
if (LEP_SetSysGainMode(&lepton.port, gain_mode) != LEP_OK) {
return -1;
}
LEP_SYS_GAIN_MODE_E gain_mode = high_temp_mode ? LEP_SYS_GAIN_MODE_LOW : LEP_SYS_GAIN_MODE_HIGH;
if (!lepton.measurement_mode) {
if (LEP_SetRadEnableState(&lepton.port, LEP_RAD_DISABLE) != LEP_OK
|| LEP_SetAgcEnableState(&lepton.port, LEP_AGC_ENABLE) != LEP_OK
|| LEP_SetAgcCalcEnableState(&lepton.port, LEP_AGC_ENABLE) != LEP_OK) {
return -1;
}
if (LEP_SetSysGainMode(&lepton.port, gain_mode) != LEP_OK ||
LEP_GetAgcROI(&lepton.port, &roi) != LEP_OK ||
LEP_SetRadEnableState(&lepton.port, measurement_mode) != LEP_OK ||
LEP_SetAgcEnableState(&lepton.port, !measurement_mode) != LEP_OK ||
LEP_SetAgcCalcEnableState(&lepton.port, !measurement_mode) != LEP_OK ||
LEP_GetRadEnableState(&lepton.port, &rad) != LEP_OK) {
return -1;
}
lepton.h_res = roi.endCol + 1;
@ -373,7 +345,7 @@ static int reset(omv_csi_t *csi) {
lepton.max_temp = LEPTON_MAX_TEMP_DEFAULT;
// Extra delay after power-on
mp_hal_delay_ms(1000);
mp_hal_delay_ms(1500);
if (lepton_reset(csi, false, false) != 0) {
return OMV_CSI_ERROR_CTL_FAILED;
@ -386,6 +358,42 @@ static int reset(omv_csi_t *csi) {
return 0;
}
static int _abort(omv_csi_t *csi, bool fifo_flush, bool in_irq) {
return vospi_abort();
}
static int config(omv_csi_t *csi, omv_csi_config_t config) {
if (config == OMV_CSI_CONFIG_INIT) {
if (reset(csi) != 0) {
return OMV_CSI_ERROR_CSI_INIT_FAILED;
}
LEP_OEM_PART_NUMBER_T part;
if (LEP_GetOemFlirPartNumber(&lepton.port, &part) != LEP_OK) {
return OMV_CSI_ERROR_CSI_INIT_FAILED;
}
// 500 == Lepton
// xxxx == Version
// 01/00 == Shutter/NoShutter
if (!strncmp(part.value, "500-0771", 8)) {
csi->chip_id = LEPTON_3_5;
} else if (!strncmp(part.value, "500-0726", 8)) {
csi->chip_id = LEPTON_3_0;
} else if (!strncmp(part.value, "500-0763", 8)) {
csi->chip_id = LEPTON_2_5;
} else if (!strncmp(part.value, "500-0659", 8)) {
csi->chip_id = LEPTON_2_0;
} else if (!strncmp(part.value, "500-0690", 8)) {
csi->chip_id = LEPTON_1_6;
} else if (!strncmp(part.value, "500-0643", 8)) {
csi->chip_id = LEPTON_1_5;
}
}
return 0;
}
static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
framebuffer_t *fb = csi->fb;
@ -493,43 +501,12 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
return 0;
}
static int config(omv_csi_t *csi, omv_csi_config_t config) {
if (config == OMV_CSI_CONFIG_INIT) {
if (reset(csi) != 0) {
return -1;
}
LEP_OEM_PART_NUMBER_T part;
if (LEP_GetOemFlirPartNumber(&lepton.port, &part) != LEP_OK) {
return OMV_CSI_ERROR_CSI_INIT_FAILED;
}
// 500 == Lepton
// xxxx == Version
// 01/00 == Shutter/NoShutter
if (!strncmp(part.value, "500-0771", 8)) {
csi->chip_id = LEPTON_3_5;
} else if (!strncmp(part.value, "500-0726", 8)) {
csi->chip_id = LEPTON_3_0;
} else if (!strncmp(part.value, "500-0763", 8)) {
csi->chip_id = LEPTON_2_5;
} else if (!strncmp(part.value, "500-0659", 8)) {
csi->chip_id = LEPTON_2_0;
} else if (!strncmp(part.value, "500-0690", 8)) {
csi->chip_id = LEPTON_1_6;
} else if (!strncmp(part.value, "500-0643", 8)) {
csi->chip_id = LEPTON_1_5;
}
}
return 0;
}
int lepton_init(omv_csi_t *csi) {
csi->reset = reset;
csi->sleep = sleep;
csi->config = config;
csi->abort = NULL;
csi->abort = _abort;
csi->shutdown = NULL;
csi->match = match;
csi->snapshot = snapshot;
csi->read_reg = read_reg;

View File

@ -235,6 +235,9 @@ soft_reset:
soft_reset_exit:
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
#if MICROPY_PY_CSI
omv_csi_abort_all();
#endif
#if MICROPY_PY_AUDIO
py_audio_deinit();
#endif

View File

@ -75,7 +75,6 @@
#include "file_utils.h"
#include "mp_utils.h"
#include "mimxrt_hal.h"
#include "vospi.h"
int main(void) {
bool first_soft_reset = true;
@ -223,8 +222,8 @@ soft_reset:
soft_reset_exit:
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
#if OMV_ENABLE_VOSPI || OMV_LEPTON_ENABLE
vospi_deinit();
#if MICROPY_PY_CSI
omv_csi_abort_all();
#endif
#if MICROPY_PY_MACHINE_CAN
machine_can_irq_deinit();

View File

@ -318,12 +318,15 @@ soft_reset:
soft_reset_exit:
printf("MPY: soft reboot\n");
#if MICROPY_PY_MACHINE_HW_PWM
pwm_deinit_all();
#if MICROPY_PY_CSI
omv_csi_abort_all();
#endif
#if MICROPY_PY_AUDIO
py_audio_deinit();
#endif
#if MICROPY_PY_MACHINE_HW_PWM
pwm_deinit_all();
#endif
#if BLUETOOTH_SD
sd_softdevice_disable();
#endif

View File

@ -252,6 +252,9 @@ soft_reset:
soft_reset_exit:
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
#if MICROPY_PY_CSI
omv_csi_abort_all();
#endif
#if MICROPY_PY_AUDIO
py_audio_deinit();
#endif

View File

@ -88,7 +88,6 @@
#include "fb_alloc.h"
#include "dma_alloc.h"
#include "file_utils.h"
#include "vospi.h"
#include "py_image.h"
#include "py_fir.h"
@ -373,9 +372,8 @@ soft_reset:
soft_reset_exit:
// soft reset
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
#if OMV_ENABLE_VOSPI || OMV_LEPTON_ENABLE
vospi_deinit();
#if MICROPY_PY_CSI
omv_csi_abort_all();
#endif
#if MICROPY_PY_LWIP
systick_disable_dispatch(SYSTICK_DISPATCH_LWIP);

View File

@ -179,11 +179,27 @@ static int stm_csi_config(omv_csi_t *csi, omv_csi_config_t config) {
NVIC_SetPriority(DCMI_IRQn, IRQ_PRI_DCMI);
HAL_NVIC_EnableIRQ(DCMI_IRQn);
#endif
} else if (config == OMV_CSI_CONFIG_DEINIT) {
#if USE_DCMI
HAL_NVIC_DisableIRQ(DCMI_IRQn);
HAL_DCMI_DeInit(&csi->dcmi);
#else
HAL_NVIC_DisableIRQ(DCMIPP_IRQn);
HAL_DCMIPP_DeInit(&csi->dcmi);
#endif
} else if (config == OMV_CSI_CONFIG_PIXFORMAT) {
#if USE_DCMI
DCMI->CR &= ~(DCMI_CR_JPEG_Msk << DCMI_CR_JPEG_Pos);
DCMI->CR |= (csi->pixformat == PIXFORMAT_JPEG) ? DCMI_JPEG_ENABLE : DCMI_JPEG_DISABLE;
#else
// Reset DCMI and pipes states to allow reconfiguring them. Note
// that abort() doesn't reset the state unless the pipe is active.
csi->dcmi.State = HAL_DCMIPP_STATE_INIT;
for (size_t i=0; i<DCMIPP_NUM_OF_PIPES; i++) {
csi->dcmi.PipeState[i] = HAL_DCMIPP_PIPE_STATE_RESET;
}
// Select and configure the DCMIPP source.
if (csi->mipi_if) {
DCMIPP_CSI_ConfTypeDef scfg = {
@ -200,6 +216,7 @@ static int stm_csi_config(omv_csi_t *csi, omv_csi_config_t config) {
.DataTypeIDA = DCMIPP_DT_RAW10,
.DataTypeIDB = DCMIPP_DT_RAW10,
};
if (HAL_DCMIPP_CSI_SetVCConfig(&csi->dcmi, DCMIPP_VIRTUAL_CHANNEL0,
DCMIPP_CSI_DT_BPP10) != HAL_OK) {
return OMV_CSI_ERROR_CSI_INIT_FAILED;
@ -354,6 +371,16 @@ static int stm_csi_abort(omv_csi_t *csi, bool fifo_flush, bool in_irq) {
return 0;
}
static int stm_csi_shutdown(omv_csi_t *csi, int enable) {
int ret = 0;
if (enable) {
ret = omv_csi_config(csi, OMV_CSI_CONFIG_DEINIT);
} else {
ret = omv_csi_config(csi, OMV_CSI_CONFIG_INIT);
}
return ret;
}
uint32_t omv_csi_get_clk_frequency() {
omv_csi_t *csi = omv_csi_get(-1);
@ -429,37 +456,6 @@ int omv_csi_set_clk_frequency(uint32_t frequency) {
return 0;
}
int omv_csi_shutdown(omv_csi_t *csi, int enable) {
int ret = 0;
omv_csi_abort(csi, true, false);
if (enable) {
#if defined(OMV_CSI_POWER_PIN)
if (csi->power_pol == OMV_CSI_ACTIVE_HIGH) {
omv_gpio_write(OMV_CSI_POWER_PIN, 1);
} else {
omv_gpio_write(OMV_CSI_POWER_PIN, 0);
}
#endif
#if USE_DCMI
HAL_NVIC_DisableIRQ(DCMI_IRQn);
HAL_DCMI_DeInit(&csi->dcmi);
#endif
} else {
#if defined(OMV_CSI_POWER_PIN)
if (csi->power_pol == OMV_CSI_ACTIVE_HIGH) {
omv_gpio_write(OMV_CSI_POWER_PIN, 0);
} else {
omv_gpio_write(OMV_CSI_POWER_PIN, 1);
}
#endif
ret = omv_csi_config(csi, OMV_CSI_CONFIG_INIT);
}
mp_hal_delay_ms(10);
return ret;
}
int omv_csi_set_vsync_callback(omv_csi_t *csi, omv_csi_cb_t cb) {
if (cb.fun == NULL) {
#if (DCMI_VSYNC_EXTI_SHARED == 0)
@ -1093,6 +1089,7 @@ int omv_csi_init() {
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;
}

View File

@ -320,6 +320,15 @@ int omv_i2c_scan(omv_i2c_t *i2c, uint8_t *list, uint8_t size) {
return idx;
}
static int omv_i2c_reset(omv_i2c_t *i2c) {
__HAL_I2C_DISABLE(i2c->inst);
mp_hal_delay_ms(10);
__HAL_I2C_ENABLE(i2c->inst);
i2c->inst->ErrorCode = 0;
i2c->inst->State = HAL_I2C_STATE_READY;
return 0;
}
int omv_i2c_enable(omv_i2c_t *i2c, bool enable) {
if (i2c->initialized) {
if (enable) {
@ -333,6 +342,7 @@ int omv_i2c_enable(omv_i2c_t *i2c, bool enable) {
int omv_i2c_gencall(omv_i2c_t *i2c, uint8_t cmd) {
if (HAL_I2C_Master_Transmit(i2c->inst, 0x00, &cmd, 1, I2C_TIMEOUT) != HAL_OK) {
omv_i2c_reset(i2c);
return -1;
}
return 0;
@ -343,6 +353,7 @@ int omv_i2c_readb(omv_i2c_t *i2c, uint8_t slv_addr, uint8_t reg_addr, uint8_t *r
if ((HAL_I2C_Master_Transmit(i2c->inst, slv_addr, &reg_addr, 1, I2C_TIMEOUT) != HAL_OK)
|| (HAL_I2C_Master_Receive(i2c->inst, slv_addr, reg_data, 1, I2C_TIMEOUT) != HAL_OK)) {
omv_i2c_reset(i2c);
ret = -1;
}
return ret;
@ -353,6 +364,7 @@ int omv_i2c_writeb(omv_i2c_t *i2c, uint8_t slv_addr, uint8_t reg_addr, uint8_t r
uint8_t buf[] = {reg_addr, reg_data};
if (HAL_I2C_Master_Transmit(i2c->inst, slv_addr, buf, 2, I2C_TIMEOUT) != HAL_OK) {
omv_i2c_reset(i2c);
ret = -1;
}
return ret;
@ -362,6 +374,7 @@ int omv_i2c_readb2(omv_i2c_t *i2c, uint8_t slv_addr, uint16_t reg_addr, uint8_t
int ret = 0;
if (HAL_I2C_Mem_Read(i2c->inst, slv_addr, reg_addr,
I2C_MEMADD_SIZE_16BIT, reg_data, 1, I2C_TIMEOUT) != HAL_OK) {
omv_i2c_reset(i2c);
ret = -1;
}
return ret;
@ -371,6 +384,7 @@ int omv_i2c_writeb2(omv_i2c_t *i2c, uint8_t slv_addr, uint16_t reg_addr, uint8_t
int ret = 0;
if (HAL_I2C_Mem_Write(i2c->inst, slv_addr, reg_addr,
I2C_MEMADD_SIZE_16BIT, &reg_data, 1, I2C_TIMEOUT) != HAL_OK) {
omv_i2c_reset(i2c);
ret = -1;
}
return ret;
@ -380,6 +394,7 @@ int omv_i2c_readw(omv_i2c_t *i2c, uint8_t slv_addr, uint8_t reg_addr, uint16_t *
int ret = 0;
if (HAL_I2C_Mem_Read(i2c->inst, slv_addr, reg_addr,
I2C_MEMADD_SIZE_8BIT, (uint8_t *) reg_data, 2, I2C_TIMEOUT) != HAL_OK) {
omv_i2c_reset(i2c);
ret = -1;
}
*reg_data = (*reg_data >> 8) | (*reg_data << 8);
@ -391,6 +406,7 @@ int omv_i2c_writew(omv_i2c_t *i2c, uint8_t slv_addr, uint8_t reg_addr, uint16_t
reg_data = (reg_data >> 8) | (reg_data << 8);
if (HAL_I2C_Mem_Write(i2c->inst, slv_addr, reg_addr,
I2C_MEMADD_SIZE_8BIT, (uint8_t *) &reg_data, 2, I2C_TIMEOUT) != HAL_OK) {
omv_i2c_reset(i2c);
ret = -1;
}
return ret;
@ -400,6 +416,7 @@ int omv_i2c_readw2(omv_i2c_t *i2c, uint8_t slv_addr, uint16_t reg_addr, uint16_t
int ret = 0;
if (HAL_I2C_Mem_Read(i2c->inst, slv_addr, reg_addr,
I2C_MEMADD_SIZE_16BIT, (uint8_t *) reg_data, 2, I2C_TIMEOUT) != HAL_OK) {
omv_i2c_reset(i2c);
ret = -1;
}
*reg_data = (*reg_data >> 8) | (*reg_data << 8);
@ -411,6 +428,7 @@ int omv_i2c_writew2(omv_i2c_t *i2c, uint8_t slv_addr, uint16_t reg_addr, uint16_
reg_data = (reg_data >> 8) | (reg_data << 8);
if (HAL_I2C_Mem_Write(i2c->inst, slv_addr, reg_addr,
I2C_MEMADD_SIZE_16BIT, (uint8_t *) &reg_data, 2, I2C_TIMEOUT) != HAL_OK) {
omv_i2c_reset(i2c);
ret = -1;
}
return ret;
@ -431,6 +449,7 @@ int omv_i2c_read_bytes(omv_i2c_t *i2c, uint8_t slv_addr, uint8_t *buf, int len,
if (HAL_I2C_Master_Seq_Receive_IT(i2c->inst, slv_addr, buf, len, xfer_flags) != HAL_OK
|| omv_i2c_wait_timeout(i2c, I2C_TIMEOUT) != 0) {
omv_i2c_reset(i2c);
ret = -1;
}
@ -453,6 +472,7 @@ int omv_i2c_write_bytes(omv_i2c_t *i2c, uint8_t slv_addr, uint8_t *buf, int len,
if (HAL_I2C_Master_Seq_Transmit_IT(i2c->inst, slv_addr, buf, len, xfer_flags) != HAL_OK
|| omv_i2c_wait_timeout(i2c, I2C_TIMEOUT) != 0) {
omv_i2c_reset(i2c);
ret = -1;
}

View File

@ -278,10 +278,12 @@ int omv_spi_transfer_start(omv_spi_t *spi, omv_spi_transfer_t *xfer) {
}
int omv_spi_transfer_abort(omv_spi_t *spi) {
if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) {
HAL_SPI_Abort_IT(spi->descr);
} else {
HAL_SPI_Abort(spi->descr);
if (spi && spi->initialized) {
if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) {
HAL_SPI_Abort_IT(spi->descr);
} else {
HAL_SPI_Abort(spi->descr);
}
}
return 0;
}