From 79d2bf458a4a04710d99683b5ea3ffe19c3ef21a Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sun, 27 Jul 2025 22:21:28 +0200 Subject: [PATCH 1/3] drivers/lepton: Fix infinite loops in the SDK. Signed-off-by: iabdalkader --- drivers/lepton/include/LEPTON_I2C_Protocol.h | 2 +- drivers/lepton/src/LEPTON_I2C_Protocol.c | 55 +++++++------------- 2 files changed, 21 insertions(+), 36 deletions(-) diff --git a/drivers/lepton/include/LEPTON_I2C_Protocol.h b/drivers/lepton/include/LEPTON_I2C_Protocol.h index ac6c75adf..5b4b887cd 100755 --- a/drivers/lepton/include/LEPTON_I2C_Protocol.h +++ b/drivers/lepton/include/LEPTON_I2C_Protocol.h @@ -79,7 +79,7 @@ extern "C" /* Timeout count to wait for I2C command to complete */ - #define LEPTON_I2C_COMMAND_BUSY_WAIT_COUNT 1000 + #define LEPTON_I2C_COMMAND_BUSY_WAIT_COUNT 5000 /******************************************************************************/ /** EXPORTED TYPE DEFINITIONS **/ diff --git a/drivers/lepton/src/LEPTON_I2C_Protocol.c b/drivers/lepton/src/LEPTON_I2C_Protocol.c index 3f0b60a62..87c191c03 100755 --- a/drivers/lepton/src/LEPTON_I2C_Protocol.c +++ b/drivers/lepton/src/LEPTON_I2C_Protocol.c @@ -436,14 +436,12 @@ LEP_RESULT LEP_I2C_SetAttribute(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr, return(result); } - LEP_RESULT LEP_I2C_RunCommand(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr, LEP_COMMAND_ID commandID) { LEP_RESULT result; LEP_UINT16 statusReg; LEP_INT16 statusCode; - LEP_UINT32 done; LEP_UINT16 timeoutCount = LEPTON_I2C_COMMAND_BUSY_WAIT_COUNT; /* Implement the Lepton TWI WRITE Protocol @@ -452,30 +450,25 @@ LEP_RESULT LEP_I2C_RunCommand(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr, ** command by polling the STATUS REGISTER BUSY Bit until it ** reports NOT BUSY. */ - do - { + do { /* Read the Status REGISTER and peek at the BUSY Bit */ result = LEP_I2C_MasterReadRegister( portDescPtr->bus, portDescPtr->deviceAddress, LEP_I2C_STATUS_REG, &statusReg); - if(result != LEP_OK) - { - return(result); + if (result != LEP_OK) { + return result; } - done = (statusReg & LEP_I2C_STATUS_BUSY_BIT_MASK)? 0: 1; - /* Add timout check */ - if( timeoutCount-- == 0 ) - { - /* Timed out waiting for command busy to go away - */ + if (timeoutCount-- == 0) { + return LEP_ERROR; } - }while( !done ); + } while((statusReg & LEP_I2C_STATUS_BUSY_BIT_MASK)); - if( result == LEP_OK ) - { + timeoutCount = LEPTON_I2C_COMMAND_BUSY_WAIT_COUNT; + + if( result == LEP_OK ) { /* Set the Lepton's DATA LENGTH REGISTER first to inform the ** Lepton Camera no 16-bit DATA words being transferred. */ @@ -484,51 +477,43 @@ LEP_RESULT LEP_I2C_RunCommand(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr, LEP_I2C_DATA_LENGTH_REG, (LEP_UINT16)0); - if( result == LEP_OK ) - { + if (result == LEP_OK) { /* Now issue the Run Command */ result = LEP_I2C_MasterWriteRegister( portDescPtr->bus, portDescPtr->deviceAddress, LEP_I2C_COMMAND_REG, commandID); - if( result == LEP_OK ) - { + if( result == LEP_OK ) { /* Now wait until the Camera has completed this command by ** polling the statusReg REGISTER BUSY Bit until it reports NOT ** BUSY. */ - do - { + do { /* Read the statusReg REGISTER and peek at the BUSY Bit */ result = LEP_I2C_MasterReadRegister( portDescPtr->bus, portDescPtr->deviceAddress, LEP_I2C_STATUS_REG, &statusReg); - if(result != LEP_OK) - { + if (result != LEP_OK) { return(result); } - done = (statusReg & LEP_I2C_STATUS_BUSY_BIT_MASK)? 0: 1; - /* Timeout? */ - }while( !done ); + if (timeoutCount-- == 0) { + return LEP_ERROR; + } + } while(statusReg & LEP_I2C_STATUS_BUSY_BIT_MASK); statusCode = (statusReg >> 8) ? ((statusReg >> 8) | 0xFF00) : 0; - if(statusCode) - { - return((LEP_RESULT)statusCode); + if (statusCode) { + return (LEP_RESULT) statusCode; } } } } - /* Check statusReg word for Errors? - */ - - - return(result); + return result; } LEP_RESULT LEP_I2C_DirectReadRegister(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr, From 9bb174454b2ab26ed2c8f0286dd98bdd68080934 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sun, 27 Jul 2025 22:41:46 +0200 Subject: [PATCH 2/3] common/csi: Track elapsed time since last hard-reset. Signed-off-by: iabdalkader --- common/omv_csi.c | 14 +++++++++++++- common/omv_csi.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/common/omv_csi.c b/common/omv_csi.c index cae4cbd28..88b532472 100644 --- a/common/omv_csi.c +++ b/common/omv_csi.c @@ -334,6 +334,17 @@ __weak int omv_csi_reset(omv_csi_t *csi, bool hard) { mp_hal_delay_ms(10); omv_gpio_write(OMV_CSI_RESET_PIN, 1); } + + // Track elapsed time since last hard-reset. + // Note hard-reset is shared between all CSIs. + uint32_t reset_time_ms = mp_hal_ticks_ms(); + + for (size_t i=0; idetected) { + csi->reset_time_ms = reset_time_ms; + } + } #endif mp_hal_delay_ms(OMV_CSI_RESET_DELAY); @@ -501,7 +512,7 @@ int omv_csi_probe(omv_i2c_t *i2c) { dev_count = omv_csi_detect(i2c, dev_list); } - // Set the current ms for tracking elapsed time since power-on. + // Track elapsed time since power-on. uint32_t power_time_ms = mp_hal_ticks_ms(); // Add special devices, such as SPI sensors, soft-CSI etc... @@ -537,6 +548,7 @@ int omv_csi_probe(omv_i2c_t *i2c) { csi->chip_id = dev_list[i].chip_id; csi->slv_addr = dev_list[i].slv_addr; csi->power_time_ms = power_time_ms; + csi->reset_time_ms = power_time_ms; // Find the sensors init function. for (size_t i=0; i Date: Sun, 27 Jul 2025 22:42:17 +0200 Subject: [PATCH 3/3] drivers/sensors: Optimize Lepton delays. - Reduce soft-reboot delay to 1000ms (works fine 2.5 and 3.5). - Replace hard-reset with OemReboot. Hard-reset requires at least 2500ms, while reboot requires only 1000ms. -Optimize `reset()` delay. reset() delay is calculated based on the last hard-reset/power-on timestamp Signed-off-by: iabdalkader --- drivers/sensors/lepton.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/drivers/sensors/lepton.c b/drivers/sensors/lepton.c index 10cacf1e9..319af6798 100644 --- a/drivers/sensors/lepton.c +++ b/drivers/sensors/lepton.c @@ -44,6 +44,8 @@ #include "LEPTON_I2C_Reg.h" #define LEPTON_BOOT_TIMEOUT (3000) +#define LEPTON_COLD_BOOT_DELAY (2000) +#define LEPTON_WARM_BOOT_DELAY (1000) #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) @@ -72,7 +74,7 @@ typedef struct lepton_state { static lepton_state_t lepton; -static int lepton_reset(omv_csi_t *csi, bool measurement_mode, bool high_temp_mode); +static int lepton_config(omv_csi_t *csi, bool measurement_mode, bool high_temp_mode); static int read_reg(omv_csi_t *csi, uint16_t reg_addr) { uint16_t reg_data; @@ -232,7 +234,7 @@ static int ioctl(omv_csi_t *csi, int request, va_list ap) { if (lepton.measurement_mode != measurement_mode_in) { lepton.measurement_mode = measurement_mode_in; lepton.high_temp_mode = high_temp_mode_in; - ret = lepton_reset(csi, lepton.measurement_mode, lepton.high_temp_mode); + ret = lepton_config(csi, lepton.measurement_mode, lepton.high_temp_mode); } break; } @@ -269,20 +271,10 @@ static int ioctl(omv_csi_t *csi, int request, va_list ap) { return ret; } -static int lepton_reset(omv_csi_t *csi, bool measurement_mode, bool high_temp_mode) { +static int lepton_config(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_RESET_PIN, 0); - mp_hal_delay_ms(100); - - omv_gpio_write(OMV_CSI_RESET_PIN, 1); - mp_hal_delay_ms(2500); - } - 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; @@ -293,10 +285,9 @@ 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(1500); - } + // Soft-reboot Lepton + LEP_RunOemReboot(&lepton.port); + mp_hal_delay_ms(LEPTON_WARM_BOOT_DELAY); for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) { LEP_UINT16 status; @@ -348,10 +339,13 @@ static int reset(omv_csi_t *csi) { lepton.min_temp = LEPTON_MIN_TEMP_DEFAULT; lepton.max_temp = LEPTON_MAX_TEMP_DEFAULT; - // Extra delay after power-on - mp_hal_delay_ms(1500); + // Extra delay after hard-reset. + uint32_t ticks_diff = mp_hal_ticks_ms() - csi->reset_time_ms; + if (ticks_diff < LEPTON_COLD_BOOT_DELAY) { + mp_hal_delay_ms(LEPTON_COLD_BOOT_DELAY - ticks_diff); + } - if (lepton_reset(csi, false, false) != 0) { + if (lepton_config(csi, false, false) != 0) { return OMV_CSI_ERROR_CTL_FAILED; } @@ -426,14 +420,14 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) { return OMV_CSI_ERROR_WOULD_BLOCK; } - // Reset the FLIR lepton on timeout, up to LEPTON_SNAPSHOT_RETRY. + // Reset the module on timeout, up to LEPTON_SNAPSHOT_RETRY times. if ((mp_hal_ticks_ms() - tick_start) > LEPTON_SNAPSHOT_TIMEOUT) { if (reset_retry++ == LEPTON_SNAPSHOT_RETRY) { vospi_abort(); return OMV_CSI_ERROR_CAPTURE_TIMEOUT; } - if (lepton_reset(csi, lepton.measurement_mode, lepton.high_temp_mode) != 0) { + if (lepton_config(csi, lepton.measurement_mode, lepton.high_temp_mode) != 0) { return OMV_CSI_ERROR_CTL_FAILED; }