Merge pull request #2787 from openmv/fix_lepton_driver
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

drivers/sensors: Optimize Lepton delays.
This commit is contained in:
Ibrahim Abdelkader 2025-08-02 14:38:04 +03:00 committed by GitHub
commit a11eb9d6a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 51 additions and 59 deletions

View File

@ -334,6 +334,17 @@ __weak int omv_csi_reset(omv_csi_t *csi, bool hard) {
mp_hal_delay_ms(10); mp_hal_delay_ms(10);
omv_gpio_write(OMV_CSI_RESET_PIN, 1); 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; i<OMV_CSI_MAX_DEVICES; i++) {
omv_csi_t *csi = &csi_all[i];
if (csi->detected) {
csi->reset_time_ms = reset_time_ms;
}
}
#endif #endif
mp_hal_delay_ms(OMV_CSI_RESET_DELAY); 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); 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(); uint32_t power_time_ms = mp_hal_ticks_ms();
// Add special devices, such as SPI sensors, soft-CSI etc... // 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->chip_id = dev_list[i].chip_id;
csi->slv_addr = dev_list[i].slv_addr; csi->slv_addr = dev_list[i].slv_addr;
csi->power_time_ms = power_time_ms; csi->power_time_ms = power_time_ms;
csi->reset_time_ms = power_time_ms;
// Find the sensors init function. // Find the sensors init function.
for (size_t i=0; i<OMV_ARRAY_SIZE(sensor_config_table); i++) { for (size_t i=0; i<OMV_ARRAY_SIZE(sensor_config_table); i++) {

View File

@ -355,6 +355,7 @@ typedef struct _omv_csi {
framebuffer_t *fb; // Frame buffer pointer framebuffer_t *fb; // Frame buffer pointer
omv_clk_t *clk; // Clock controller. omv_clk_t *clk; // Clock controller.
uint32_t clk_hz; // Clock freqeuency request by this CSI. uint32_t clk_hz; // Clock freqeuency request by this CSI.
uint32_t reset_time_ms; // To track elapsed time since hard-reset.
uint32_t power_time_ms; // To track elapsed time since power on. uint32_t power_time_ms; // To track elapsed time since power on.
#ifdef OMV_CSI_PORT_BITS #ifdef OMV_CSI_PORT_BITS

View File

@ -79,7 +79,7 @@ extern "C"
/* Timeout count to wait for I2C command to complete /* 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 **/ /** EXPORTED TYPE DEFINITIONS **/

View File

@ -436,14 +436,12 @@ LEP_RESULT LEP_I2C_SetAttribute(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr,
return(result); return(result);
} }
LEP_RESULT LEP_I2C_RunCommand(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr, LEP_RESULT LEP_I2C_RunCommand(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr,
LEP_COMMAND_ID commandID) LEP_COMMAND_ID commandID)
{ {
LEP_RESULT result; LEP_RESULT result;
LEP_UINT16 statusReg; LEP_UINT16 statusReg;
LEP_INT16 statusCode; LEP_INT16 statusCode;
LEP_UINT32 done;
LEP_UINT16 timeoutCount = LEPTON_I2C_COMMAND_BUSY_WAIT_COUNT; LEP_UINT16 timeoutCount = LEPTON_I2C_COMMAND_BUSY_WAIT_COUNT;
/* Implement the Lepton TWI WRITE Protocol /* 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 ** command by polling the STATUS REGISTER BUSY Bit until it
** reports NOT BUSY. ** reports NOT BUSY.
*/ */
do do {
{
/* Read the Status REGISTER and peek at the BUSY Bit /* Read the Status REGISTER and peek at the BUSY Bit
*/ */
result = LEP_I2C_MasterReadRegister( portDescPtr->bus, result = LEP_I2C_MasterReadRegister( portDescPtr->bus,
portDescPtr->deviceAddress, portDescPtr->deviceAddress,
LEP_I2C_STATUS_REG, LEP_I2C_STATUS_REG,
&statusReg); &statusReg);
if(result != LEP_OK) if (result != LEP_OK) {
{ return result;
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 /* Set the Lepton's DATA LENGTH REGISTER first to inform the
** Lepton Camera no 16-bit DATA words being transferred. ** 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_I2C_DATA_LENGTH_REG,
(LEP_UINT16)0); (LEP_UINT16)0);
if( result == LEP_OK ) if (result == LEP_OK) {
{
/* Now issue the Run Command /* Now issue the Run Command
*/ */
result = LEP_I2C_MasterWriteRegister( portDescPtr->bus, result = LEP_I2C_MasterWriteRegister( portDescPtr->bus,
portDescPtr->deviceAddress, portDescPtr->deviceAddress,
LEP_I2C_COMMAND_REG, LEP_I2C_COMMAND_REG,
commandID); commandID);
if( result == LEP_OK ) if( result == LEP_OK ) {
{
/* Now wait until the Camera has completed this command by /* Now wait until the Camera has completed this command by
** polling the statusReg REGISTER BUSY Bit until it reports NOT ** polling the statusReg REGISTER BUSY Bit until it reports NOT
** BUSY. ** BUSY.
*/ */
do do {
{
/* Read the statusReg REGISTER and peek at the BUSY Bit /* Read the statusReg REGISTER and peek at the BUSY Bit
*/ */
result = LEP_I2C_MasterReadRegister( portDescPtr->bus, result = LEP_I2C_MasterReadRegister( portDescPtr->bus,
portDescPtr->deviceAddress, portDescPtr->deviceAddress,
LEP_I2C_STATUS_REG, LEP_I2C_STATUS_REG,
&statusReg); &statusReg);
if(result != LEP_OK) if (result != LEP_OK) {
{
return(result); 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; statusCode = (statusReg >> 8) ? ((statusReg >> 8) | 0xFF00) : 0;
if(statusCode) if (statusCode) {
{ return (LEP_RESULT) 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, LEP_RESULT LEP_I2C_DirectReadRegister(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr,

View File

@ -44,6 +44,8 @@
#include "LEPTON_I2C_Reg.h" #include "LEPTON_I2C_Reg.h"
#define LEPTON_BOOT_TIMEOUT (3000) #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_RETRY (3)
#define LEPTON_SNAPSHOT_TIMEOUT (5000) #define LEPTON_SNAPSHOT_TIMEOUT (5000)
#define LEPTON_I2C_STATUS_BOOT (LEP_I2C_STATUS_BOOT_MODE_MASK | LEP_I2C_STATUS_BOOT_STAT_MASK) #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 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) { static int read_reg(omv_csi_t *csi, uint16_t reg_addr) {
uint16_t reg_data; 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) { if (lepton.measurement_mode != measurement_mode_in) {
lepton.measurement_mode = measurement_mode_in; lepton.measurement_mode = measurement_mode_in;
lepton.high_temp_mode = high_temp_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; break;
} }
@ -269,20 +271,10 @@ static int ioctl(omv_csi_t *csi, int request, va_list ap) {
return ret; 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_RAD_ENABLE_E rad;
LEP_AGC_ROI_T roi; 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)) { 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) { if (LEP_OpenPort(csi->i2c, LEP_CCI_TWI, 0, &lepton.port) == LEP_OK) {
break; break;
@ -293,10 +285,9 @@ static int lepton_reset(omv_csi_t *csi, bool measurement_mode, bool high_temp_mo
} }
} }
if (csi->auxiliary) { // Soft-reboot Lepton
LEP_RunOemReboot(&lepton.port); LEP_RunOemReboot(&lepton.port);
mp_hal_delay_ms(1500); mp_hal_delay_ms(LEPTON_WARM_BOOT_DELAY);
}
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) { for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
LEP_UINT16 status; LEP_UINT16 status;
@ -348,10 +339,13 @@ static int reset(omv_csi_t *csi) {
lepton.min_temp = LEPTON_MIN_TEMP_DEFAULT; lepton.min_temp = LEPTON_MIN_TEMP_DEFAULT;
lepton.max_temp = LEPTON_MAX_TEMP_DEFAULT; lepton.max_temp = LEPTON_MAX_TEMP_DEFAULT;
// Extra delay after power-on // Extra delay after hard-reset.
mp_hal_delay_ms(1500); 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; 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; 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 ((mp_hal_ticks_ms() - tick_start) > LEPTON_SNAPSHOT_TIMEOUT) {
if (reset_retry++ == LEPTON_SNAPSHOT_RETRY) { if (reset_retry++ == LEPTON_SNAPSHOT_RETRY) {
vospi_abort(); vospi_abort();
return OMV_CSI_ERROR_CAPTURE_TIMEOUT; 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; return OMV_CSI_ERROR_CTL_FAILED;
} }