@@ -75,10 +75,8 @@ void HardwarePWM::DebugOutput(Stream& logger)
7575 logger.printf (" || %d:" , i);
7676 if (can_stringify_token (token)) {
7777 uint8_t * t = (uint8_t *)(&token);
78- static_assert (sizeof (uintptr_t ) == 4 );
7978 logger.printf (" \" %c%c%c%c\" " , t[0 ], t[1 ], t[2 ], t[3 ] );
8079 } else {
81- static_assert (sizeof (uintptr_t ) == 4 );
8280 logger.printf (" %08x" , token);
8381 }
8482 for (size_t j = 0 ; j < MAX_CHANNELS; j++) {
@@ -96,76 +94,6 @@ void HardwarePWM::DebugOutput(Stream& logger)
9694void HardwarePWM::DebugOutput (Stream& logger) {}
9795#endif // CFG_DEBUG
9896
99- // returns true ONLY when (1) no PWM channel has a pin, and (2) the owner token is nullptr
100- bool HardwarePWM::takeOwnership (uintptr_t token)
101- {
102- bool notInIsr = !isInISR ();
103- if (token == 0 ) {
104- if (notInIsr) {
105- LOG_LV1 (" HwPWM" , " zero / nullptr is not a valid ownership token (attempted use in takeOwnership)" );
106- }
107- return false ; // cannot take ownership with nullptr
108- }
109- if (token == this ->_owner_token ) {
110- if (notInIsr) {
111- LOG_LV1 (" HwPWM" , " failing to acquire ownership because already owned by requesting token (cannot take ownership twice)" );
112- }
113- }
114- if (this ->_owner_token != 0 ) {
115- return false ;
116- }
117- if (this ->usedChannelCount () != 0 ) {
118- return false ;
119- }
120- if (this ->enabled ()) {
121- return false ;
122- }
123- // TODO: warn, but do not fail, if taking ownership with IRQs already enabled
124- // NVIC_GetActive
125-
126- // Use C++11 atomic CAS operation
127- uintptr_t newValue = 0U ;
128- return this ->_owner_token .compare_exchange_strong (newValue, token);
129- }
130- // returns true ONLY when (1) no PWM channel has a pin attached, and (2) the owner token matches
131- bool HardwarePWM::releaseOwnership (uintptr_t token)
132- {
133- bool notInIsr = !isInISR ();
134- if (token == 0 ) {
135- if (notInIsr) {
136- LOG_LV1 (" HwPWM" , " zero / nullptr is not a valid ownership token (attempted use in releaseOwnership)" );
137- }
138- return false ;
139- }
140- if (!this ->isOwner (token)) {
141- if (notInIsr) {
142- LOG_LV1 (" HwPWM" , " attempt to release ownership when not the current owner" );
143- }
144- return false ;
145- }
146- if (this ->usedChannelCount () != 0 ) {
147- if (notInIsr) {
148- LOG_LV1 (" HwPWM" , " attempt to release ownership when at least on channel is still connected" );
149- }
150- return false ;
151- }
152- if (this ->enabled ()) {
153- if (notInIsr) {
154- LOG_LV1 (" HwPWM" , " attempt to release ownership when PWM peripheral is still enabled" );
155- }
156- return false ; // if it's enabled, do not allow ownership to be released, even with no pins in use
157- }
158- // TODO: warn, but do not fail, if releasing ownership with IRQs enabled
159- // NVIC_GetActive
160-
161- // Use C++11 atomic CAS operation
162- bool result = this ->_owner_token .compare_exchange_strong (token, 0U );
163- if (!result) {
164- LOG_LV1 (" HwPWM" , " race condition resulted in failure to acquire ownership" );
165- }
166- return result;
167- }
168-
16997HardwarePWM::HardwarePWM (NRF_PWM_Type* pwm) :
17098 _pwm(pwm)
17199{
@@ -350,3 +278,72 @@ uint8_t HardwarePWM::freeChannelCount(void) const
350278 return MAX_CHANNELS - usedChannelCount ();
351279}
352280
281+ // returns true ONLY when (1) no PWM channel has a pin, and (2) the owner token is nullptr
282+ bool HardwarePWM::takeOwnership (uintptr_t token)
283+ {
284+ if (token == 0 ) {
285+ LOG_LV1 (" HwPWM" , " zero / nullptr is not a valid ownership token (attempted use in takeOwnership)" );
286+ return false ;
287+ }
288+
289+ if (token == this ->_owner_token ) {
290+ LOG_LV1 (" HwPWM" , " failing to acquire ownership because already owned by requesting token (cannot take ownership twice)" );
291+ return false ;
292+ }
293+
294+ if (this ->_owner_token != 0 ) return false ;
295+ if (this ->usedChannelCount () != 0 ) return false ;
296+ if (this ->enabled ()) return false ;
297+
298+ if (isInISR ())
299+ {
300+ UBaseType_t intr_status = taskENTER_CRITICAL_FROM_ISR ();
301+ _owner_token = token;
302+ taskEXIT_CRITICAL_FROM_ISR (intr_status);
303+ }else
304+ {
305+ taskENTER_CRITICAL ();
306+ _owner_token = token;
307+ taskEXIT_CRITICAL ();
308+ }
309+
310+ return true ;
311+ }
312+
313+ // returns true ONLY when (1) no PWM channel has a pin attached, and (2) the owner token matches
314+ bool HardwarePWM::releaseOwnership (uintptr_t token)
315+ {
316+ if (token == 0 ) {
317+ LOG_LV1 (" HwPWM" , " zero / nullptr is not a valid ownership token (attempted use in releaseOwnership)" );
318+ return false ;
319+ }
320+
321+ if (!this ->isOwner (token)) {
322+ LOG_LV1 (" HwPWM" , " attempt to release ownership when not the current owner" );
323+ return false ;
324+ }
325+
326+ if (this ->usedChannelCount () != 0 ) {
327+ LOG_LV1 (" HwPWM" , " attempt to release ownership when at least on channel is still connected" );
328+ return false ;
329+ }
330+
331+ if (this ->enabled ()) {
332+ LOG_LV1 (" HwPWM" , " attempt to release ownership when PWM peripheral is still enabled" );
333+ return false ; // if it's enabled, do not allow ownership to be released, even with no pins in use
334+ }
335+
336+ if (isInISR ())
337+ {
338+ UBaseType_t intr_status = taskENTER_CRITICAL_FROM_ISR ();
339+ _owner_token = 0 ;
340+ taskEXIT_CRITICAL_FROM_ISR (intr_status);
341+ }else
342+ {
343+ taskENTER_CRITICAL ();
344+ _owner_token = 0 ;
345+ taskEXIT_CRITICAL ();
346+ }
347+
348+ return true ;
349+ }
0 commit comments