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) {
|
furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS);
|
||||||
stat = FuriStatusErrorResource;
|
|
||||||
} else {
|
|
||||||
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;
|
||||||
furi_hal_power.gauge_ok = bq27220_apply_data_memory(
|
while(retry > 0) {
|
||||||
&furi_hal_i2c_handle_power, furi_hal_power_gauge_data_memory);
|
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
|
// 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_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,46 +70,67 @@ 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
|
||||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
cc1101_reset(&furi_hal_spi_bus_handle_subghz);
|
cc1101_reset(&furi_hal_spi_bus_handle_subghz);
|
||||||
cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
||||||
|
|
||||||
// Prepare GD0 for power on self test
|
// Prepare GD0 for power on self test
|
||||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||||
|
|
||||||
// GD0 low
|
// GD0 low
|
||||||
cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW);
|
FuriHalCortexTimer timeout = furi_hal_cortex_timer_get(10000);
|
||||||
while(furi_hal_gpio_read(&gpio_cc1101_g0) != false)
|
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
|
if(furi_hal_gpio_read(&gpio_cc1101_g0) != false) {
|
||||||
cc1101_write_reg(
|
break;
|
||||||
&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
|
}
|
||||||
while(furi_hal_gpio_read(&gpio_cc1101_g0) != true)
|
|
||||||
;
|
|
||||||
|
|
||||||
// Reset GD0 to floating state
|
// GD0 high
|
||||||
cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
timeout = furi_hal_cortex_timer_get(10000);
|
||||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
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
|
if(furi_hal_gpio_read(&gpio_cc1101_g0) != true) {
|
||||||
furi_hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
break;
|
||||||
cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW);
|
}
|
||||||
|
|
||||||
// Go to sleep
|
// Reset GD0 to floating state
|
||||||
cc1101_shutdown(&furi_hal_spi_bus_handle_subghz);
|
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_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() {
|
void furi_hal_subghz_sleep() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user