Various Fixes for 0.95 (#3215)
* FuriHal: retry gauge/charger initialization * FuriHal: lower logging level for flash known errata * FuriHal: graceful fail if subghz chip is not working * Furi: issue stop command even if timer is not active, document timer behavior
This commit is contained in:
		
							parent
							
								
									a61b5d4b4c
								
							
						
					
					
						commit
						457aa5331f
					
				| @ -122,17 +122,10 @@ FuriStatus furi_timer_stop(FuriTimer* instance) { | |||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
| 
 | 
 | ||||||
|     TimerHandle_t hTimer = (TimerHandle_t)instance; |     TimerHandle_t hTimer = (TimerHandle_t)instance; | ||||||
|     FuriStatus stat; |  | ||||||
| 
 | 
 | ||||||
|     if(xTimerIsTimerActive(hTimer) == pdFALSE) { |  | ||||||
|         stat = FuriStatusErrorResource; |  | ||||||
|     } else { |  | ||||||
|     furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS); |     furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS); | ||||||
|         stat = FuriStatusOk; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     /* Return execution status */ |     return FuriStatusOk; | ||||||
|     return (stat); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t furi_timer_is_running(FuriTimer* instance) { | uint32_t furi_timer_is_running(FuriTimer* instance) { | ||||||
|  | |||||||
| @ -32,6 +32,9 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co | |||||||
| void furi_timer_free(FuriTimer* instance); | void furi_timer_free(FuriTimer* instance); | ||||||
| 
 | 
 | ||||||
| /** Start timer
 | /** 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      instance  The pointer to FuriTimer instance | ||||||
|  * @param[in]  ticks     The interval in ticks |  * @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); | FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks); | ||||||
| 
 | 
 | ||||||
| /** Restart timer with previous timeout value
 | /** 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      instance  The pointer to FuriTimer instance | ||||||
|  * @param[in]  ticks     The interval in ticks |  * @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); | FuriStatus furi_timer_restart(FuriTimer* instance, uint32_t ticks); | ||||||
| 
 | 
 | ||||||
| /** Stop timer
 | /** 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 |  * @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); | FuriStatus furi_timer_stop(FuriTimer* instance); | ||||||
| 
 | 
 | ||||||
| /** Is timer running
 | /** 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 |  * @param      instance  The pointer to FuriTimer instance | ||||||
|  * |  * | ||||||
|  | |||||||
| @ -101,7 +101,7 @@ void furi_hal_flash_init() { | |||||||
|     // WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR);
 |     // WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR);
 | ||||||
|     /* Actually, reset all error flags on start */ |     /* Actually, reset all error flags on start */ | ||||||
|     if(READ_BIT(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS)) { |     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); |         WRITE_REG(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -71,12 +71,37 @@ void furi_hal_power_init() { | |||||||
| 
 | 
 | ||||||
|     furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); |     furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); | ||||||
|     // Find and init gauge
 |     // Find and init gauge
 | ||||||
|     if(bq27220_init(&furi_hal_i2c_handle_power)) { |     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_power.gauge_ok = bq27220_apply_data_memory( | ||||||
|                 &furi_hal_i2c_handle_power, furi_hal_power_gauge_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
 |     // Find and init charger
 | ||||||
|  |     retry = 2; | ||||||
|  |     while(retry > 0) { | ||||||
|         furi_hal_power.charger_ok = bq25896_init(&furi_hal_i2c_handle_power); |         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_hal_i2c_release(&furi_hal_i2c_handle_power); | ||||||
| 
 | 
 | ||||||
|     FURI_LOG_I(TAG, "Init OK"); |     FURI_LOG_I(TAG, "Init OK"); | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ | |||||||
| #include <furi_hal_version.h> | #include <furi_hal_version.h> | ||||||
| #include <furi_hal_rtc.h> | #include <furi_hal_rtc.h> | ||||||
| #include <furi_hal_spi.h> | #include <furi_hal_spi.h> | ||||||
|  | #include <furi_hal_cortex.h> | ||||||
| #include <furi_hal_interrupt.h> | #include <furi_hal_interrupt.h> | ||||||
| #include <furi_hal_resources.h> | #include <furi_hal_resources.h> | ||||||
| #include <furi_hal_bus.h> | #include <furi_hal_bus.h> | ||||||
| @ -29,7 +30,7 @@ static uint32_t furi_hal_subghz_debug_gpio_buff[2]; | |||||||
| /** SubGhz state */ | /** SubGhz state */ | ||||||
| typedef enum { | typedef enum { | ||||||
|     SubGhzStateInit, /**< Init pending */ |     SubGhzStateInit, /**< Init pending */ | ||||||
| 
 |     SubGhzStateBroken, /**< Chip power-on self test failed */ | ||||||
|     SubGhzStateIdle, /**< Idle, energy save mode */ |     SubGhzStateIdle, /**< Idle, energy save mode */ | ||||||
| 
 | 
 | ||||||
|     SubGhzStateAsyncRx, /**< Async RX started */ |     SubGhzStateAsyncRx, /**< Async RX started */ | ||||||
| @ -69,12 +70,13 @@ const GpioPin* furi_hal_subghz_get_data_gpio() { | |||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_init() { | void furi_hal_subghz_init() { | ||||||
|     furi_assert(furi_hal_subghz.state == SubGhzStateInit); |     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); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 |     do { | ||||||
| #ifdef FURI_HAL_SUBGHZ_TX_GPIO | #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 | #endif | ||||||
| 
 | 
 | ||||||
|         // Reset
 |         // Reset
 | ||||||
| @ -86,16 +88,28 @@ void furi_hal_subghz_init() { | |||||||
|         furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |         furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|         // GD0 low
 |         // GD0 low
 | ||||||
|  |         FuriHalCortexTimer timeout = furi_hal_cortex_timer_get(10000); | ||||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW); | ||||||
|     while(furi_hal_gpio_read(&gpio_cc1101_g0) != false) |         while(furi_hal_gpio_read(&gpio_cc1101_g0) != false && | ||||||
|  |               !furi_hal_cortex_timer_is_expired(timeout)) | ||||||
|             ; |             ; | ||||||
| 
 | 
 | ||||||
|  |         if(furi_hal_gpio_read(&gpio_cc1101_g0) != false) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         // GD0 high
 |         // GD0 high
 | ||||||
|  |         timeout = furi_hal_cortex_timer_get(10000); | ||||||
|         cc1101_write_reg( |         cc1101_write_reg( | ||||||
|             &furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); |             &furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||||
|     while(furi_hal_gpio_read(&gpio_cc1101_g0) != true) |         while(furi_hal_gpio_read(&gpio_cc1101_g0) != true && | ||||||
|  |               !furi_hal_cortex_timer_is_expired(timeout)) | ||||||
|             ; |             ; | ||||||
| 
 | 
 | ||||||
|  |         if(furi_hal_gpio_read(&gpio_cc1101_g0) != true) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         // Reset GD0 to floating state
 |         // Reset GD0 to floating state
 | ||||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|         furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |         furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
| @ -107,8 +121,16 @@ void furi_hal_subghz_init() { | |||||||
|         // Go to sleep
 |         // Go to sleep
 | ||||||
|         cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); |         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_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|  | 
 | ||||||
|  |     if(furi_hal_subghz.state == SubGhzStateIdle) { | ||||||
|         FURI_LOG_I(TAG, "Init OK"); |         FURI_LOG_I(TAG, "Init OK"); | ||||||
|  |     } else { | ||||||
|  |         FURI_LOG_E(TAG, "Init Fail"); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_sleep() { | void furi_hal_subghz_sleep() { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく