Skip to content

Commit fcce4da

Browse files
committed
opt-in ownership of PWM peripheral
1 parent 2de0066 commit fcce4da

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

cores/nRF5/HardwarePWM.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,25 @@ HardwarePWM* HwPWMx[] =
5353
#endif
5454
};
5555

56+
// returns true ONLY when (1) no PWM channel has a pin, and (2) the owner token is nullptr
57+
bool HardwarePWM::takeOwnership(uintptr_t token)
58+
{
59+
if (this->_owner_token != 0) return false; // doesn't matter if it's actually a match ... it's not legal to take ownership twice
60+
if (this->usedChannelCount() != 0) return false; // at least one channel is already in use
61+
// use gcc built-in intrinsic to ensure atomicity
62+
// See https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
63+
return __sync_bool_compare_and_swap(&(this->_owner_token), 0, token);
64+
}
65+
// returns true ONLY when (1) no PWM channel has a pin attached, and (2) the owner token matches
66+
bool HardwarePWM::releaseOwnership(uintptr_t token)
67+
{
68+
if (!this->isOwner(token) ) return false; // don't even look at peripheral
69+
if ( this->usedChannelCount() != 0) return false; // fail if any channels still have pins
70+
// use gcc built-in intrinsic to ensure atomicity
71+
// See https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
72+
return __sync_bool_compare_and_swap(&(this->_owner_token), token, 0);
73+
}
74+
5675
HardwarePWM::HardwarePWM(NRF_PWM_Type* pwm)
5776
{
5877
_pwm = pwm;

cores/nRF5/HardwarePWM.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class HardwarePWM
5050
private:
5151
enum { MAX_CHANNELS = 4 }; // Max channel per group
5252
NRF_PWM_Type* _pwm;
53+
uintptr_t _owner_token = 0;
5354

5455
uint16_t _seq0[MAX_CHANNELS];
5556

@@ -67,6 +68,18 @@ class HardwarePWM
6768

6869
void setClockDiv(uint8_t div); // value is PWM_PRESCALER_PRESCALER_DIV_x, DIV1 is 16Mhz
6970

71+
// Cooperative ownership sharing
72+
73+
// returns true ONLY when (1) no PWM channel has a pin, and (2) the owner token is nullptr
74+
bool takeOwnership(uintptr_t token);
75+
// returns true ONLY when (1) no PWM channel has a pin attached, and (2) the owner token matches
76+
bool releaseOwnership(uintptr_t token);
77+
// allows caller to verify that they own the peripheral
78+
__INLINE bool isOwner(uintptr_t token) __attribute__((__always_inline__))
79+
{
80+
return this->_owner_token == token;
81+
}
82+
7083
bool addPin (uint8_t pin);
7184
bool removePin (uint8_t pin);
7285

0 commit comments

Comments
 (0)