@@ -65,7 +65,6 @@ bool can_stringify_token(uintptr_t token)
65
65
return true ;
66
66
}
67
67
68
-
69
68
void HardwarePWM::DebugOutput (Stream& logger)
70
69
{
71
70
const size_t count = arrcount (HwPWMx);
@@ -98,22 +97,61 @@ void HardwarePWM::DebugOutput(Stream& logger)
98
97
// returns true ONLY when (1) no PWM channel has a pin, and (2) the owner token is nullptr
99
98
bool HardwarePWM::takeOwnership (uintptr_t token)
100
99
{
101
- if (token == 0 ) return false ; // cannot take ownership with nullptr
102
- if (this ->_owner_token != 0 ) return false ; // doesn't matter if it's actually a match ... it's not legal to take ownership twice
103
- if (this ->usedChannelCount () != 0 ) return false ; // at least one channel is already in use
104
- if (this ->enabled () ) return false ; // if it's enabled, do not allow new ownership, even with no pins in use
100
+ if (token == 0 ) {
101
+ LOG_LV1 (" HwPWM" , " zero / nullptr is not a valid ownership token (attempted use in takeOwnership)" );
102
+ return false ; // cannot take ownership with nullptr
103
+ }
104
+ if (token == this ->_owner_token ) {
105
+ LOG_LV1 (" HwPWM" , " failing to acquire ownership because already owned by requesting token (cannot take ownership twice)" );
106
+ }
107
+ if (this ->_owner_token != 0 ) {
108
+ LOG_LV3 (" HwPWM" , " failing to acquire ownership because already owned by other token" );
109
+ return false ;
110
+ }
111
+ if (this ->usedChannelCount () != 0 ) {
112
+ LOG_LV3 (" HwPWM" , " failing to acquire ownership because at least one channel connected" );
113
+ return false ;
114
+ }
115
+ if (this ->enabled ()) {
116
+ LOG_LV3 (" HwPWM" , " failing to acquire ownership because peripheral is already enabled" );
117
+ return false ;
118
+ }
119
+ // TODO: warn, but do not fail, if taking ownership with IRQs already enabled
120
+ // NVIC_GetActive
121
+
105
122
// use gcc built-in intrinsic to ensure atomicity
106
123
// See https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
107
124
return __sync_bool_compare_and_swap (&(this ->_owner_token ), 0 , token);
108
125
}
109
126
// returns true ONLY when (1) no PWM channel has a pin attached, and (2) the owner token matches
110
127
bool HardwarePWM::releaseOwnership (uintptr_t token)
111
128
{
112
- if (! releaseOwnershipFromISR ( token) ) {
113
- LOG_LV1 (" HwPWM" , " Failed to release ownership of PWM %p using token %x " , _pwm, token );
129
+ if (token == 0 ) {
130
+ LOG_LV1 (" HwPWM" , " zero / nullptr is not a valid ownership token (attempted use in releaseOwnership) " );
114
131
return false ;
115
132
}
116
- return true ;
133
+ if (!this ->isOwner (token)) {
134
+ LOG_LV1 (" HwPWM" , " attempt to release ownership when not the current owner" );
135
+ return false ;
136
+ }
137
+ if (this ->usedChannelCount () != 0 ) {
138
+ LOG_LV1 (" HwPWM" , " attempt to release ownership when at least on channel is still connected" );
139
+ return false ;
140
+ }
141
+ if (this ->enabled ()) {
142
+ LOG_LV1 (" HwPWM" , " attempt to release ownership when PWM peripheral is still enabled" );
143
+ return false ; // if it's enabled, do not allow ownership to be released, even with no pins in use
144
+ }
145
+ // TODO: warn, but do not fail, if releasing ownership with IRQs enabled
146
+ // NVIC_GetActive
147
+
148
+ // use gcc built-in intrinsic to ensure atomicity
149
+ // See https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
150
+ bool result = __sync_bool_compare_and_swap (&(this ->_owner_token ), token, 0 );
151
+ if (!result) {
152
+ LOG_LV1 (" HwPWM" , " race condition resulted in failure to acquire ownership" );
153
+ }
154
+ return result;
117
155
}
118
156
bool HardwarePWM::releaseOwnershipFromISR (uintptr_t token) {
119
157
// Do not do any logging if called from ISR ...
0 commit comments