~aleteoryx/muditaos

9279e9ac0624fc2655f01c2cb60157f6e31613ee — Dawid Wojtas 3 years ago 8c2b5aa
[BH-1628] Reinit I2C after bus error

A lack of timeout in I2C could cause
the worker could get stuck in a loop
if the communication has been broken somehow.
The Harmony is unresponsive in this case.
The only solution is just to perform a hardware
reset using Frontlight and Back buttons simultaneously.

There are also additional 5 attempts to read and write
transactions if the bus error occurs in the Fuel Gauge driver.
It should be sufficient but if it would still persists
the system just will read 0% SOC and shutdown system.
M module-bsp/board/rt1051/common/fsl_drivers/CMakeLists.txt => module-bsp/board/rt1051/common/fsl_drivers/CMakeLists.txt +7 -0
@@ 67,6 67,13 @@ target_sources(fsl
        fsl_wdog.h    
)

# define a timeout for fsl_lpi2c driver
# it needs to be here if the fsl library will be replaced by a newer version
target_compile_definitions(fsl 
    PRIVATE 
    LPI2C_WAIT_TIMEOUT=500000
)

target_include_directories(fsl
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>

M module-bsp/board/rt1051/common/fsl_drivers/fsl_lpi2c.h => module-bsp/board/rt1051/common/fsl_drivers/fsl_lpi2c.h +1 -0
@@ 54,6 54,7 @@
/*@}*/

/*! @brief Timeout times for waiting flag. */
/*! Timeout is defined in CMakeLists.txt in the fsl_drivers directory */
#ifndef LPI2C_WAIT_TIMEOUT
#define LPI2C_WAIT_TIMEOUT 0U /* Define to zero means keep waiting until the flag is assert/deassert. */
#endif

M module-bsp/board/rt1051/drivers/RT1051DriverI2C.cpp => module-bsp/board/rt1051/drivers/RT1051DriverI2C.cpp +11 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RT1051DriverI2C.hpp"


@@ 102,6 102,16 @@ namespace drivers
        LPI2C_MasterDeinit(base);
    }

    void RT1051DriverI2C::ReInit(void)
    {
        lpi2c_master_config_t lpi2cConfig = {};

        LPI2C_MasterDeinit(base);

        LPI2C_MasterGetDefaultConfig(&lpi2cConfig);
        LPI2C_MasterInit(base, &lpi2cConfig, GetPerphSourceClock(PerphClock_I2C));
    }

    ssize_t RT1051DriverI2C::Write(const drivers::I2CAddress &addr, const uint8_t *txBuff, const size_t size)
    {
        cpp_freertos::LockGuard lock(mutex);

M module-bsp/board/rt1051/drivers/RT1051DriverI2C.hpp => module-bsp/board/rt1051/drivers/RT1051DriverI2C.hpp +3 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#ifndef PUREPHONE_RT1051DRIVERI2C_HPP


@@ 22,6 22,8 @@ namespace drivers

        ~RT1051DriverI2C();

        void ReInit(void) override final;

        ssize_t Write(const I2CAddress &addr, const uint8_t *txBuff, const size_t size) override final;

        ssize_t Read(const I2CAddress &addr, uint8_t *rxBuff, const size_t size) override final;

M module-bsp/devices/power/CW2015.cpp => module-bsp/devices/power/CW2015.cpp +24 -7
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "CW2015.hpp"


@@ 317,19 317,36 @@ namespace bsp::devices::power

    std::optional<std::uint8_t> CW2015::read(const std::uint8_t reg)
    {
        constexpr std::uint8_t maxAttemps          = 5;
        const drivers::I2CAddress fuelGaugeAddress = {ADDRESS, reg, i2c_subaddr_size};
        std::uint8_t ret_val{};
        if (const auto result = i2c.Read(fuelGaugeAddress, &ret_val, i2c_subaddr_size); result == i2c_subaddr_size) {
            return ret_val;
        }
        else {
            return std::nullopt;

        for (std::uint8_t i = 0; i < maxAttemps; ++i) {
            if (const auto result = i2c.Read(fuelGaugeAddress, &ret_val, i2c_subaddr_size);
                result == i2c_subaddr_size) {
                return ret_val;
            }
            i2c.ReInit();
            LOG_INFO("Attempting to read I2C data: %d", i);
            vTaskDelay(pdMS_TO_TICKS(i * 10));
        }
        return std::nullopt;
    }

    bool CW2015::write(const std::uint8_t reg, const std::uint8_t value)
    {
        constexpr std::uint8_t maxAttemps          = 5;
        const drivers::I2CAddress fuelGaugeAddress = {ADDRESS, reg, i2c_subaddr_size};
        return i2c.Write(fuelGaugeAddress, &value, i2c_subaddr_size) == i2c_subaddr_size;

        for (std::uint8_t i = 0; i < maxAttemps; ++i) {
            if (const auto result = i2c.Write(fuelGaugeAddress, &value, i2c_subaddr_size); result == i2c_subaddr_size) {
                return true;
            }
            i2c.ReInit();
            LOG_INFO("Attempting to write I2C data: %d", i);
            vTaskDelay(pdMS_TO_TICKS(i * 10));
        }
        return false;
    }
    CW2015::operator bool() const
    {

M module-bsp/drivers/i2c/DriverI2C.cpp => module-bsp/drivers/i2c/DriverI2C.cpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "DriverI2C.hpp"


@@ 9,7 9,6 @@
#include "board/rt1051/drivers/RT1051DriverI2C.hpp"
#elif defined(TARGET_Linux)

//#include ""
#else
#error "Unsupported target"
#endif

M module-bsp/drivers/i2c/DriverI2C.hpp => module-bsp/drivers/i2c/DriverI2C.hpp +3 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#ifndef PUREPHONE_DRIVERI2C_HPP


@@ 57,6 57,8 @@ namespace drivers
        virtual ~DriverI2C()
        {}

        virtual void ReInit(void) = 0;

        virtual ssize_t Write(const I2CAddress &addr, const uint8_t *txBuff, const size_t size) = 0;

        virtual ssize_t Read(const I2CAddress &addr, uint8_t *rxBuff, const size_t size) = 0;