diff --git a/furi/core/timer.c b/furi/core/timer.c index 17347e5c..027e4cf4 100644 --- a/furi/core/timer.c +++ b/furi/core/timer.c @@ -122,17 +122,10 @@ FuriStatus furi_timer_stop(FuriTimer* instance) { furi_assert(instance); TimerHandle_t hTimer = (TimerHandle_t)instance; - FuriStatus stat; - if(xTimerIsTimerActive(hTimer) == pdFALSE) { - stat = FuriStatusErrorResource; - } else { - furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS); - stat = FuriStatusOk; - } + furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS); - /* Return execution status */ - return (stat); + return FuriStatusOk; } uint32_t furi_timer_is_running(FuriTimer* instance) { diff --git a/furi/core/timer.h b/furi/core/timer.h index d27ef502..f8f40c56 100644 --- a/furi/core/timer.h +++ b/furi/core/timer.h @@ -32,6 +32,9 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co void furi_timer_free(FuriTimer* instance); /** Start timer + * + * @warning This is asynchronous call, real operation will happen as soon as + * timer service process this request. * * @param instance The pointer to FuriTimer instance * @param[in] ticks The interval in ticks @@ -41,6 +44,9 @@ void furi_timer_free(FuriTimer* instance); FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks); /** Restart timer with previous timeout value + * + * @warning This is asynchronous call, real operation will happen as soon as + * timer service process this request. * * @param instance The pointer to FuriTimer instance * @param[in] ticks The interval in ticks @@ -50,6 +56,9 @@ FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks); FuriStatus furi_timer_restart(FuriTimer* instance, uint32_t ticks); /** Stop timer + * + * @warning This is asynchronous call, real operation will happen as soon as + * timer service process this request. * * @param instance The pointer to FuriTimer instance * @@ -58,6 +67,10 @@ FuriStatus furi_timer_restart(FuriTimer* instance, uint32_t ticks); FuriStatus furi_timer_stop(FuriTimer* instance); /** Is timer running + * + * @warning This cal may and will return obsolete timer state if timer + * commands are still in the queue. Please read FreeRTOS timer + * documentation first. * * @param instance The pointer to FuriTimer instance * diff --git a/targets/f7/furi_hal/furi_hal_flash.c b/targets/f7/furi_hal/furi_hal_flash.c index 284d48bf..7ac7a8bd 100644 --- a/targets/f7/furi_hal/furi_hal_flash.c +++ b/targets/f7/furi_hal/furi_hal_flash.c @@ -101,7 +101,7 @@ void furi_hal_flash_init() { // WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR); /* Actually, reset all error flags on start */ if(READ_BIT(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS)) { - FURI_LOG_E(TAG, "FLASH->SR 0x%08lX", FLASH->SR); + FURI_LOG_W(TAG, "FLASH->SR 0x%08lX(Known ERRATA)", FLASH->SR); WRITE_REG(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS); } } diff --git a/targets/f7/furi_hal/furi_hal_power.c b/targets/f7/furi_hal/furi_hal_power.c index 119dee81..9e3a70da 100644 --- a/targets/f7/furi_hal/furi_hal_power.c +++ b/targets/f7/furi_hal/furi_hal_power.c @@ -71,12 +71,37 @@ void furi_hal_power_init() { furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); // Find and init gauge - if(bq27220_init(&furi_hal_i2c_handle_power)) { - furi_hal_power.gauge_ok = bq27220_apply_data_memory( - &furi_hal_i2c_handle_power, furi_hal_power_gauge_data_memory); + size_t retry = 2; + while(retry > 0) { + furi_hal_power.gauge_ok = bq27220_init(&furi_hal_i2c_handle_power); + if(furi_hal_power.gauge_ok) { + furi_hal_power.gauge_ok = bq27220_apply_data_memory( + &furi_hal_i2c_handle_power, furi_hal_power_gauge_data_memory); + } + if(furi_hal_power.gauge_ok) { + break; + } else { + // Normal startup time is 250ms + // But if we try to access gauge at that stage it will become unresponsive + // 2 seconds timeout needed to restart communication + furi_delay_us(2020202); + } + retry--; } // Find and init charger - furi_hal_power.charger_ok = bq25896_init(&furi_hal_i2c_handle_power); + retry = 2; + while(retry > 0) { + furi_hal_power.charger_ok = bq25896_init(&furi_hal_i2c_handle_power); + if(furi_hal_power.charger_ok) { + break; + } else { + // Most likely I2C communication error + // 2 seconds should be enough for all chips on the line to timeout + // Also timing out here is very abnormal + furi_delay_us(2020202); + } + retry--; + } furi_hal_i2c_release(&furi_hal_i2c_handle_power); FURI_LOG_I(TAG, "Init OK"); diff --git a/targets/f7/furi_hal/furi_hal_subghz.c b/targets/f7/furi_hal/furi_hal_subghz.c index f7514635..a00ca7bf 100644 --- a/targets/f7/furi_hal/furi_hal_subghz.c +++ b/targets/f7/furi_hal/furi_hal_subghz.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,7 @@ static uint32_t furi_hal_subghz_debug_gpio_buff[2]; /** SubGhz state */ typedef enum { SubGhzStateInit, /**< Init pending */ - + SubGhzStateBroken, /**< Chip power-on self test failed */ SubGhzStateIdle, /**< Idle, energy save mode */ SubGhzStateAsyncRx, /**< Async RX started */ @@ -69,46 +70,67 @@ const GpioPin* furi_hal_subghz_get_data_gpio() { void furi_hal_subghz_init() { furi_assert(furi_hal_subghz.state == SubGhzStateInit); - furi_hal_subghz.state = SubGhzStateIdle; + furi_hal_subghz.state = SubGhzStateBroken; furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - + do { #ifdef FURI_HAL_SUBGHZ_TX_GPIO - furi_hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init( + &FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); #endif - // Reset - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - cc1101_reset(&furi_hal_spi_bus_handle_subghz); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); + // Reset + furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + cc1101_reset(&furi_hal_spi_bus_handle_subghz); + cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); - // Prepare GD0 for power on self test - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + // Prepare GD0 for power on self test + furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); - // GD0 low - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW); - while(furi_hal_gpio_read(&gpio_cc1101_g0) != false) - ; + // GD0 low + FuriHalCortexTimer timeout = furi_hal_cortex_timer_get(10000); + cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW); + while(furi_hal_gpio_read(&gpio_cc1101_g0) != false && + !furi_hal_cortex_timer_is_expired(timeout)) + ; - // GD0 high - cc1101_write_reg( - &furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); - while(furi_hal_gpio_read(&gpio_cc1101_g0) != true) - ; + if(furi_hal_gpio_read(&gpio_cc1101_g0) != false) { + break; + } - // Reset GD0 to floating state - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + // GD0 high + timeout = furi_hal_cortex_timer_get(10000); + cc1101_write_reg( + &furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); + while(furi_hal_gpio_read(&gpio_cc1101_g0) != true && + !furi_hal_cortex_timer_is_expired(timeout)) + ; - // RF switches - furi_hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); + if(furi_hal_gpio_read(&gpio_cc1101_g0) != true) { + break; + } - // Go to sleep - cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); + // Reset GD0 to floating state + cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); + furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + + // RF switches + furi_hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); + + // Go to sleep + cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); + + furi_hal_subghz.state = SubGhzStateIdle; + } while(false); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); - FURI_LOG_I(TAG, "Init OK"); + + if(furi_hal_subghz.state == SubGhzStateIdle) { + FURI_LOG_I(TAG, "Init OK"); + } else { + FURI_LOG_E(TAG, "Init Fail"); + } } void furi_hal_subghz_sleep() {