From f4424367410ba566fcd015f9483b6945221b5832 Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Wed, 19 Jun 2024 11:55:51 -0700 Subject: [PATCH] Fix PwmOut::resume() for static pinmap usage (#281) * Fix PwmOut::resume() for static pinmap usage * Use function pointers, like SPI does * Fix style * Remove "static" * Revert "Remove "static"" This reverts commit c00929788e5ccfbc8f716cbb32e8079dc0a5fb33. --- drivers/include/drivers/PwmOut.h | 19 +++++++++++++++++-- drivers/source/PwmOut.cpp | 30 +++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/drivers/include/drivers/PwmOut.h b/drivers/include/drivers/PwmOut.h index 9a901c4b75..b187a965e7 100644 --- a/drivers/include/drivers/PwmOut.h +++ b/drivers/include/drivers/PwmOut.h @@ -63,7 +63,8 @@ public: /** Create a PwmOut connected to the specified pin * - * @param pinmap reference to structure which holds static pinmap. + * @param pinmap reference to structure which holds static pinmap. + * This reference is stored in the PwmOut, so the pinmap needs to live as long as this object does. */ PwmOut(const PinMap &pinmap); PwmOut(const PinMap &&) = delete; // prevent passing of temporary objects @@ -199,6 +200,14 @@ protected: /** Unlock deep sleep in case it is locked */ void unlock_deep_sleep(); + // Functions which call the underlying HAL init function. The direct one calls the static + // pinmap version (pwmout_init_direct()) and the normal one calls the PinName-accepting one (pwmout_init()). + // A pointer to one of these two functions is stored in the _init_func member. + // It's done this way so that references to pwmout_init(), and therefore to the pinmap tables, + // can be removed by the linker if only the static pinmap version is used. + static void _call_pwmout_init_direct(PwmOut *thisPtr); + static void _call_pwmout_init(PwmOut *thisPtr); + /** Initialize this instance */ void init(); @@ -206,7 +215,13 @@ protected: void deinit(); pwmout_t _pwm; - PinName _pin; + + const PinName _pin; // Pin, NC if using static pinmap + PinMap const *const _pinmap; // Static pinmap, nullptr if not used + + /* Pointer to HAL init function */ + void (*_init_func)(PwmOut *); + bool _deep_sleep_locked; bool _initialized; float _duty_cycle; diff --git a/drivers/source/PwmOut.cpp b/drivers/source/PwmOut.cpp index 53e6f84f10..a956f22f7e 100644 --- a/drivers/source/PwmOut.cpp +++ b/drivers/source/PwmOut.cpp @@ -28,6 +28,8 @@ namespace mbed { PwmOut::PwmOut(PinName pin) : _pin(pin), + _pinmap(nullptr), + _init_func(_call_pwmout_init), _deep_sleep_locked(false), _initialized(false), _duty_cycle(0), @@ -36,11 +38,16 @@ PwmOut::PwmOut(PinName pin) : PwmOut::init(); } -PwmOut::PwmOut(const PinMap &pinmap) : _deep_sleep_locked(false) +PwmOut::PwmOut(const PinMap &pinmap) : + _pin(NC), + _pinmap(&pinmap), + _init_func(_call_pwmout_init_direct), + _deep_sleep_locked(false), + _initialized(false), + _duty_cycle(0), + _period_us(0) { - core_util_critical_section_enter(); - pwmout_init_direct(&_pwm, &pinmap); - core_util_critical_section_exit(); + PwmOut::init(); } PwmOut::~PwmOut() @@ -164,12 +171,25 @@ void PwmOut::unlock_deep_sleep() } } +void PwmOut::_call_pwmout_init_direct(PwmOut *thisPtr) +{ + pwmout_init_direct(&thisPtr->_pwm, thisPtr->_pinmap); +} + +void PwmOut::_call_pwmout_init(PwmOut *thisPtr) +{ + pwmout_init(&thisPtr->_pwm, thisPtr->_pin); +} + void PwmOut::init() { core_util_critical_section_enter(); if (!_initialized) { - pwmout_init(&_pwm, _pin); + + // Call either pwmout_init() or pwmout_init_direct(), depending on whether we have a PinName or a static pinmap + _init_func(this); + lock_deep_sleep(); _initialized = true; }