~aleteoryx/muditaos

b6235923bfe77e4a1c2ec851c05e5658500c233d — Mateusz Piesta 2 years ago 67e8b1c
[BH-1595] USB charger detection issues

* Fixed issues with USB charging port detection
* Fixed memory leak in usb_stack/OS integration layer
* Fixed incorrect handling of software timer
* Minor cleaning/refactor.

[BH-1595] Turned off USB/PC charging

Charging enabled only for a dedicated charger. Users won't be able
to charger while connected to the PC.
M cmake/modules/AddPackage.cmake => cmake/modules/AddPackage.cmake +1 -1
@@ 39,7 39,7 @@ function(add_standalone_image SOURCE_TARGET)
        # please do not:
        # 1. change compression to -9 (or higher) as i will have detrimental effects on compression times with not much gain
        # 2. change -T parameter to explicit thread count - xz with T0 will adjust thread count to your machine capatibilies
        COMMAND tar -I 'xz -T0' -Scf ${STANDALONE_PKG} ${SOURCE_TARGET}.img
        COMMAND tar Scf - ${SOURCE_TARGET}.img | xz -T0 > ${STANDALONE_PKG}
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        DEPENDS ${BIN_FILE}
        DEPENDS json-common-target

M harmony_changelog.md => harmony_changelog.md +1 -0
@@ 16,6 16,7 @@
* Fixed problem that UI could be occasionally broken
* Fixed problem with displaying end of title when playing song in loop was selected.
* Fixed problem with an unresponding device after playing specific WAV files.
* Fixed USB charging port detection.

### Added


M module-bsp/board/rt1051/bellpx/hal/battery_charger/BatteryCharger.cpp => module-bsp/board/rt1051/bellpx/hal/battery_charger/BatteryCharger.cpp +60 -41
@@ 15,6 15,8 @@
#include <board/BoardDefinitions.hpp>
#include <log/log.hpp>

#include <variant>

namespace
{
    using namespace bsp::devices::power;


@@ 38,6 40,13 @@ namespace
    constexpr auto charger_irq_gpio_chgok =
        static_cast<drivers::GPIOInstances>(BoardDefinitions::BELL_BATTERY_CHARGER_CHGOK_GPIO);

    template <class... Ts>
    struct overloaded : Ts...
    {
        using Ts::operator()...;
    };
    template <class... Ts>
    overloaded(Ts...) -> overloaded<Ts...>;
} // namespace

namespace hal::battery


@@ 45,11 54,23 @@ namespace hal::battery
    class BellBatteryCharger : public AbstractBatteryCharger
    {
      public:
        enum class IrqEvents : std::uint8_t
        struct events
        {
            Charger,
            FuelGauge
            enum class DCD : std::uint8_t
            {
                Timeout = 0x00U,
                UnknownType,
                Error, /// VBUS is coming from a dedicated power supply
                SDP,   /// Standard downstream port, up to 500mA
                CDP,   /// Charging downstream port, up to 1.5A
                DCP,   /// Dedicated charging port(wall warts and auto adapters without enumeration), up to 1.5A
            };
            struct Charger
            {};
            struct FuelGauge
            {};
        };
        using IrqEvents          = std::variant<events::DCD, events::Charger, events::FuelGauge>;
        using BatteryWorkerQueue = WorkerQueue<IrqEvents>;

        explicit BellBatteryCharger(xQueueHandle irqQueueHandle);


@@ 68,7 89,9 @@ namespace hal::battery

        void sendNotification(Events event);
        void pollFuelGauge();
        bool tryEnableCharging();

        void handleIrqEvents(IrqEvents event);
        void handleChargerEvents(MP2639B::ChargingStatus status);

        xTimerHandle reinit_timer;
        xQueueHandle notification_channel;


@@ 93,17 116,8 @@ namespace hal::battery
                                                                               charger_irq_pin_acok,
                                                                               charger_gpio_chgok,
                                                                               charger_irq_pin_chgok,
                                                                               [this](const auto) {
                                                                                   /// Due to this layer performing
                                                                                   /// charging control automatically,
                                                                                   /// there is no need to notify higher
                                                                                   /// layers about \ref
                                                                                   /// MP2639B::ChargingStatus::PluggedNotCharging
                                                                                   /// event.
                                                                                   if (not tryEnableCharging()) {
                                                                                       sendNotification(
                                                                                           Events::Charger);
                                                                                   }
                                                                               [this](const auto event) {
                                                                                   handleChargerEvents(event);
                                                                               }}},

          fuel_gauge_gpio{drivers::DriverGPIO::Create(fuel_gauge_irq_gpio_instance, {})},


@@ 116,20 130,8 @@ namespace hal::battery
            inst->pollFuelGauge();
        });

        worker_queue = std::make_unique<BatteryWorkerQueue>("battery_charger", [this](const auto &msg) {
            switch (msg) {
            case IrqEvents::Charger: {
                charger.handle_irq();
            } break;

            case IrqEvents::FuelGauge: {
                fuel_gauge.irq_handler();
                sendNotification(Events::SOC);
            } break;
            }
        });

        tryEnableCharging();
        worker_queue = std::make_unique<BatteryWorkerQueue>(
            "battery_charger", [this](const auto &msg) { handleIrqEvents(msg); }, 1024);

        pollFuelGauge();



@@ 227,29 229,46 @@ namespace hal::battery
            LOG_INFO("Fuel gauge initialization success");
        }
    }

    bool BellBatteryCharger::tryEnableCharging()
    void BellBatteryCharger::handleIrqEvents(const IrqEvents event)
    {
        if (charger.get_charge_status() == MP2639B::ChargingStatus::PluggedNotCharging) {
            charger.enable_charging(true);
            return true;
        }

        return false;
        std::visit(overloaded{[this](const events::Charger) { charger.handle_irq(); },
                              [this](const events::FuelGauge) {
                                  fuel_gauge.irq_handler();
                                  sendNotification(Events::SOC);
                              },
                              [this](const events::DCD evt) {
                                  LOG_INFO("USB charging port discovery result: %s",
                                           std::string{magic_enum::enum_name(evt)}.c_str());
                                  switch (evt) {
                                  case events::DCD::DCP:
                                  case events::DCD::CDP:
                                  case events::DCD::Timeout:
                                      LOG_INFO("Valid charger detected, enabling charging");
                                      charger.enable_charging(true);
                                      break;
                                  default:
                                      charger.enable_charging(false);
                                  }
                              }},
                   event);
    }
    void BellBatteryCharger::handleChargerEvents(const MP2639B::ChargingStatus)
    {
        sendNotification(Events::Charger);
    }

    BaseType_t charger_irq()
    {
        return BellBatteryCharger::getWorkerQueueHandle().post(BellBatteryCharger::IrqEvents::Charger);
        return BellBatteryCharger::getWorkerQueueHandle().post({BellBatteryCharger::events::Charger{}});
    }
    BaseType_t fuel_gauge_irq()
    {
        return BellBatteryCharger::getWorkerQueueHandle().post(BellBatteryCharger::IrqEvents::FuelGauge);
        return BellBatteryCharger::getWorkerQueueHandle().post({BellBatteryCharger::events::FuelGauge{}});
    }

    extern "C" void USB_ChargerDetectedCB(std::uint8_t /*unused*/)
    extern "C" void USB_ChargerDetectedCB(std::uint8_t raw_type)
    {
        /// It needs to be defined even if it is not used.
        BellBatteryCharger::getWorkerQueueHandle().post({BellBatteryCharger::events::DCD{raw_type}});
    }

    std::unique_ptr<AbstractBatteryCharger> AbstractBatteryCharger::Factory::create(xQueueHandle irqQueueHandle)

D module-bsp/board/rt1051/eMMC/eMMC.cpp => module-bsp/board/rt1051/eMMC/eMMC.cpp +0 -109
@@ 1,109 0,0 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "eMMC.hpp"

#include "bsp/BoardDefinitions.hpp"

#if defined(TARGET_RT1051)
#include "board/rt1051/bsp/eMMC/fsl_mmc.h"
#elif defined(TARGET_Linux)

#else
#error "Unsupported target 1"
#endif

namespace bsp
{

    using namespace drivers;

    RetCode eMMC::Init()
    {
        driverUSDHC = drivers::DriverUSDHC::Create(
            "EMMC", static_cast<drivers::USDHCInstances>(BoardDefinitions::EMMC_USDHC_INSTANCE));
#if defined(TARGET_RT1051)

        // pll = DriverPLL::Create(static_cast<PLLInstances >(BoardDefinitions::EMMC_PLL),DriverPLLParams{});

        mmcCard.busWidth                   = kMMC_DataBusWidth8bit;
        mmcCard.busTiming                  = kMMC_HighSpeedTiming;
        mmcCard.enablePreDefinedBlockCount = true;
        mmcCard.host.base                  = USDHC2; // TODO:M.P move it to BoardDefinitions.hpp
        mmcCard.host.sourceClock_Hz        = GetPerphSourceClock(PerphClock_USDHC2);

        auto ret = MMC_Init(&mmcCard);
        if (ret != kStatus_Success) {
            return RetCode::Failure;
        }
        else {
            userPartitionBlocks = mmcCard.userPartitionBlocks;
            return RetCode::Success;
        }
#else
#error "Unsupported target"
#endif
    }

    RetCode eMMC::DeInit()
    {
#if defined(TARGET_RT1051)
        MMC_Deinit(&mmcCard);
        return RetCode::Success;
#else
#error "Unsupported target"
#endif
    }

    RetCode eMMC::ReadBlocks(uint8_t *buffer, uint32_t startBlock, uint32_t blockCount)
    {
#if defined(TARGET_RT1051)
        driverUSDHC->Enable();
        auto ret = MMC_ReadBlocks(&mmcCard, buffer, startBlock, blockCount);
        driverUSDHC->Disable();
        if (ret != kStatus_Success) {
            return RetCode::Failure;
        }
        else {
            return RetCode::Success;
        }
#else
#error "Unsupported target"
#endif
    }

    RetCode eMMC::WriteBlocks(const uint8_t *buffer, uint32_t startBlock, uint32_t blockCount)
    {
#if defined(TARGET_RT1051)
        driverUSDHC->Enable();
        auto ret = MMC_WriteBlocks(&mmcCard, buffer, startBlock, blockCount);
        driverUSDHC->Disable();
        if (ret != kStatus_Success) {
            return RetCode::Failure;
        }
        else {
            return RetCode::Success;
        }
#else
#error "Unsupported target"
#endif
    }

    RetCode eMMC::SwitchPartition(eMMC::Partition partition)
    {
#if defined(TARGET_RT1051)
        driverUSDHC->Enable();
        auto ret = MMC_SelectPartition(&mmcCard, static_cast<mmc_access_partition_t>(partition));
        driverUSDHC->Disable();
        if (ret != kStatus_Success) {
            return RetCode::Failure;
        }
        else {
            return RetCode::Success;
        }
#else
#error "Unsupported target"
#endif
    }

} // namespace bsp

D module-bsp/board/rt1051/eMMC/eMMC.hpp => module-bsp/board/rt1051/eMMC/eMMC.hpp +0 -64
@@ 1,64 0,0 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#ifndef MODULE_BSP_EMMC_HPP
#define MODULE_BSP_EMMC_HPP

#include <stdint.h>
#include <memory>

#if defined(TARGET_RT1051)
#include "board/rt1051/bsp/eMMC/fsl_mmc.h"
#include "drivers/pll/DriverPLL.hpp"
#else
#error "Unsupported target"
#endif

#include "bsp/common.hpp"
#include "drivers/usdhc/DriverUSDHC.hpp"

namespace bsp
{
    class eMMC
    {
      public:
        enum class Partition
        {
            UserArea        = 0U, /*!< No access to boot partition (default), normal partition */
            Boot1           = 1U, /*!< Read/Write boot partition 1 */
            Boot2           = 2U, /*!< Read/Write boot partition 2*/
            RPMB            = 3U, /*!< Replay protected mem block */
            GeneralPurpose1 = 4U, /*!< access to general purpose partition 1 */
            GeneralPurpose2 = 5U, /*!< access to general purpose partition 2 */
            GeneralPurpose3 = 6U, /*!< access to general purpose partition 3 */
            GeneralPurpose4 = 7U, /*!< access to general purpose partition 4 */

        };

        eMMC()
        {}
        ~eMMC()
        {}

        RetCode Init();
        RetCode DeInit();
        RetCode ReadBlocks(uint8_t *buffer, uint32_t startBlock, uint32_t blockCount);
        RetCode WriteBlocks(const uint8_t *buffer, uint32_t startBlock, uint32_t blockCount);
        RetCode SwitchPartition(Partition partition);

        uint32_t userPartitionBlocks;

      protected:
      private:
#if defined(TARGET_RT1051)
        std::shared_ptr<drivers::DriverPLL> pll;
        mmc_card_t mmcCard;
#else
#error "Unsupported target"
#endif
        std::shared_ptr<drivers::DriverUSDHC> driverUSDHC;
    };

} // namespace bsp

#endif // MODULE_BSP_EMMC_HPP

M module-bsp/board/rt1051/puretx/hal/battery_charger/BatteryCharger.cpp => module-bsp/board/rt1051/puretx/hal/battery_charger/BatteryCharger.cpp +4 -1
@@ 136,7 136,10 @@ namespace hal::battery
    void PureBatteryCharger::setChargingCurrentLimit(std::uint8_t usbType)
    {
        using namespace bsp::battery_charger;
        switch (static_cast<batteryChargerType>(usbType)) {
        const auto event = static_cast<batteryChargerType>(usbType);
        LOG_INFO("USB charging port discovery result: %s", std::string{magic_enum::enum_name(event)}.c_str());

        switch (event) {
        case batteryChargerType::DcdTimeOut:
        case batteryChargerType::DcdUnknownType:
        case batteryChargerType::DcdError:

M module-bsp/bsp/usb/usb.hpp => module-bsp/bsp/usb/usb.hpp +0 -1
@@ 45,7 45,6 @@ namespace bsp
    int usbCDCSend(std::string *sendMsg);
    int usbCDCSendRaw(const char *dataPtr, size_t dataLen);
    void usbDeinit();
    void usbReinit(const std::string &rootPath);
    void usbSuspend();
    void usbHandleDataReceived();


M module-bsp/devices/power/MP2639B.cpp => module-bsp/devices/power/MP2639B.cpp +4 -3
@@ 14,7 14,9 @@ namespace bsp::devices::power
                if (not inst->is_valid_voltage()) {
                    inst->enable_charging(false);
                }
                inst->configuration.notification(inst->get_charge_status());
                if (inst->configuration.notification) {
                    inst->configuration.notification(inst->get_charge_status());
                }
            });

        drivers::DriverGPIOPinParams mode_pin_params{};


@@ 54,7 56,6 @@ namespace bsp::devices::power
        else if (valid_voltage and not is_charging_enabled()) {
            status = ChargingStatus::PluggedNotCharging;
        }
        // TODO: add error condition, i.e when chgok blinks at 1Hz
        return status;
    }
    void MP2639B::enable_charging(bool ctrl)


@@ 89,7 90,7 @@ namespace bsp::devices::power
    void MP2639B::handle_irq()
    {
        if (xTimerIsTimerActive(irq_filter_timer) == pdFALSE) {
            xTimerStart(irq_filter_timer, pdMS_TO_TICKS(100));
            xTimerStart(irq_filter_timer, pdMS_TO_TICKS(500));
        }
    }
    bool MP2639B::is_charging_enabled() const

M module-bsp/hal/include/hal/battery_charger/AbstractBatteryCharger.hpp => module-bsp/hal/include/hal/battery_charger/AbstractBatteryCharger.hpp +4 -4
@@ 33,7 33,7 @@ namespace hal::battery
            Brownout
        };

        enum class ChargerPresence
        enum class ChargerPresence : std::uint8_t
        {
            Undefined,
            PluggedIn,


@@ 48,9 48,9 @@ namespace hal::battery
        virtual ~AbstractBatteryCharger() = default;

        virtual std::optional<Voltage> getBatteryVoltage() const = 0;
        virtual std::optional<SOC> getSOC() const          = 0;
        virtual ChargingStatus getChargingStatus() const   = 0;
        virtual ChargerPresence getChargerPresence() const = 0;
        virtual std::optional<SOC> getSOC() const                = 0;
        virtual ChargingStatus getChargingStatus() const         = 0;
        virtual ChargerPresence getChargerPresence() const       = 0;

        static_assert(sizeof(Events) == sizeof(std::uint8_t),
                      "All events processed by event manager ought to have size of std::uint8_t");

M module-services/service-desktop/WorkerDesktop.cpp => module-services/service-desktop/WorkerDesktop.cpp +0 -10
@@ 90,16 90,6 @@ void WorkerDesktop::closeWorker(void)
    LOG_DEBUG("deinit end");
}

bool WorkerDesktop::reinit(const std::filesystem::path &path)
{
    LOG_DEBUG("Reinit USB begin");

    bsp::usbReinit(path);

    LOG_DEBUG("Reinit USB end");
    return true;
}

void WorkerDesktop::reset()
{
    initialized = false;

M module-services/service-desktop/WorkerDesktop.hpp => module-services/service-desktop/WorkerDesktop.hpp +0 -1
@@ 28,7 28,6 @@ class WorkerDesktop : public sys::Worker

    virtual bool init(std::list<sys::WorkerQueueInfo> queues) override;
    void closeWorker();
    bool reinit(const std::filesystem::path &path);

    bool handleMessage(std::uint32_t queueID) override final;


M pure_changelog.md => pure_changelog.md +1 -0
@@ 37,6 37,7 @@
* Fixed slider-related crash on phone turn off
* Fixed problem with an unresponsive device after playing specific WAV files.
* Fixed unresponsive Templates window for user input after templates were changed via MC.
* Fixed USB charging port detection.

## [1.7.0 2023-03-23]
### Changed / Improved

M third-party/usb_stack => third-party/usb_stack +1 -1
@@ 1,1 1,1 @@
Subproject commit c04c7d528f37eed85a010437f96e46384b145e13
Subproject commit 4344e3eccc83ebee901a029de0e4ed8e793a47ed