77#include < Arduino.h>
88#include " zephyrInternal.h"
99
10+ #include < zephyr/kernel.h>
11+ #include < zephyr/spinlock.h>
12+
1013static const struct gpio_dt_spec arduino_pins[] = {
1114 DT_FOREACH_PROP_ELEM_SEP (
1215 DT_PATH (zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))};
@@ -230,53 +233,120 @@ PinStatus digitalRead(pin_size_t pinNumber) {
230233 return (gpio_pin_get_dt (&arduino_pins[pinNumber]) == 1 ) ? HIGH : LOW;
231234}
232235
233- #ifndef MAX_TONE_PINS
236+ #if CONFIG_ARDUINO_MAX_TONES < 0
234237#define MAX_TONE_PINS DT_PROP_LEN (DT_PATH(zephyr_user), digital_pin_gpios)
238+ #else
239+ #define MAX_TONE_PINS CONFIG_ARDUINO_MAX_TONES
235240#endif
236241
237242#define TOGGLES_PER_CYCLE 2ULL
238243
239244static struct pin_timer {
240245 struct k_timer timer;
241- uint32_t count;
242- pin_size_t pin;
243- bool infinity;
246+ uint32_t count{0 };
247+ pin_size_t pin{pin_size_t (-1 )};
248+ bool infinity{false };
249+ bool timer_initialized{false };
250+ struct k_spinlock lock;
244251} arduino_pin_timers[MAX_TONE_PINS];
245252
253+ K_MUTEX_DEFINE (timer_cfg_lock);
254+
255+ void tone_expiry_cb (struct k_timer *timer);
256+
257+ static struct pin_timer *find_pin_timer (pin_size_t pinNumber, bool active_only) {
258+ for (size_t i = 0 ; i < ARRAY_SIZE (arduino_pin_timers); i++) {
259+ k_spinlock_key_t key = k_spin_lock (&arduino_pin_timers[i].lock );
260+
261+ if (arduino_pin_timers[i].pin == pinNumber) {
262+ k_spin_unlock (&arduino_pin_timers[i].lock , key);
263+ return &arduino_pin_timers[i];
264+ }
265+
266+ k_spin_unlock (&arduino_pin_timers[i].lock , key);
267+ }
268+
269+ if (active_only) {
270+ return nullptr ;
271+ }
272+
273+ for (size_t i = 0 ; i < ARRAY_SIZE (arduino_pin_timers); i++) {
274+ k_spinlock_key_t key = k_spin_lock (&arduino_pin_timers[i].lock );
275+
276+ if (arduino_pin_timers[i].pin == pin_size_t (-1 )) {
277+ arduino_pin_timers[i].pin = pinNumber;
278+
279+ if (!arduino_pin_timers[i].timer_initialized ) {
280+ k_timer_init (&arduino_pin_timers[i].timer , tone_expiry_cb, NULL );
281+ arduino_pin_timers[i].timer_initialized = true ;
282+ }
283+
284+ k_spin_unlock (&arduino_pin_timers[i].lock , key);
285+ return &arduino_pin_timers[i];
286+ }
287+
288+ k_spin_unlock (&arduino_pin_timers[i].lock , key);
289+ }
290+
291+ return nullptr ;
292+ }
293+
246294void tone_expiry_cb (struct k_timer *timer) {
247295 struct pin_timer *pt = CONTAINER_OF (timer, struct pin_timer , timer);
248- const struct gpio_dt_spec *spec = &arduino_pins[pt->pin ];
296+ k_spinlock_key_t key = k_spin_lock (&pt->lock );
297+ pin_size_t pin = pt->pin ;
249298
250299 if (pt->count == 0 && !pt->infinity ) {
300+ if (pin != pin_size_t (-1 )) {
301+ gpio_pin_set_dt (&arduino_pins[pin], 0 );
302+ }
303+
251304 k_timer_stop (timer);
252- gpio_pin_set_dt (spec, 0 );
305+ pt->count = 0 ;
306+ pt->infinity = false ;
307+ pt->pin = pin_size_t (-1 );
253308 } else {
254- gpio_pin_toggle_dt (spec);
309+ if (pin != pin_size_t (-1 )) {
310+ gpio_pin_toggle_dt (&arduino_pins[pin]);
311+ }
312+
255313 pt->count --;
256314 }
257- }
258315
259- void tone_timeout_cb (struct k_timer *timer) {
260- pin_size_t pinNumber = (pin_size_t )(uintptr_t )k_timer_user_data_get (timer);
261- noTone (pinNumber);
316+ k_spin_unlock (&pt->lock , key);
262317}
263318
264319void tone (pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
265- const struct gpio_dt_spec *spec = &arduino_pins[pinNumber] ;
266- struct k_timer *timer ;
320+ k_spinlock_key_t key ;
321+ struct pin_timer *pt ;
267322 k_timeout_t timeout;
268323
269- if (pinNumber >= MAX_TONE_PINS ) {
324+ if (k_is_in_isr () ) {
270325 return ;
271326 }
272327
273- timer = &arduino_pin_timers[pinNumber].timer ;
328+ k_mutex_lock (&timer_cfg_lock, K_FOREVER);
329+
330+ pt = find_pin_timer (pinNumber, false );
331+
332+ if (pt == nullptr ) {
333+ k_mutex_unlock (&timer_cfg_lock);
334+ return ;
335+ }
274336
275337 pinMode (pinNumber, OUTPUT);
276- k_timer_stop (&arduino_pin_timers[pinNumber]. timer );
338+ k_timer_stop (&pt-> timer );
277339
278340 if (frequency == 0 ) {
279- gpio_pin_set_dt (spec, 0 );
341+ key = k_spin_lock (&pt->lock );
342+ pt->count = 0 ;
343+ pt->infinity = false ;
344+ pt->pin = pin_size_t (-1 );
345+ k_spin_unlock (&pt->lock , key);
346+
347+ gpio_pin_set_dt (&arduino_pins[pinNumber], 0 );
348+
349+ k_mutex_unlock (&timer_cfg_lock);
280350 return ;
281351 }
282352
@@ -285,21 +355,45 @@ void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration)
285355 timeout.ticks = 1 ;
286356 }
287357
288- arduino_pin_timers[pinNumber].infinity = (duration == 0 );
289- arduino_pin_timers[pinNumber].count = (uint64_t )duration * frequency *
290- (MSEC_PER_SEC / TOGGLES_PER_CYCLE);
291- arduino_pin_timers[pinNumber].pin = pinNumber;
292- k_timer_init (timer, tone_expiry_cb, NULL );
358+ key = k_spin_lock (&pt->lock );
359+ pt->infinity = (duration == 0 );
360+ pt->count = min ((uint64_t )duration * frequency * TOGGLES_PER_CYCLE / MSEC_PER_SEC, UINT32_MAX);
361+ pt->pin = pinNumber;
362+ k_spin_unlock (&pt->lock , key);
363+
364+ gpio_pin_set_dt (&arduino_pins[pinNumber], 0 );
365+ k_timer_start (&pt->timer , timeout, timeout);
293366
294- gpio_pin_set_dt (spec, 0 );
295- k_timer_start (timer, timeout, timeout);
367+ k_mutex_unlock (&timer_cfg_lock);
296368}
297369
298370void noTone (pin_size_t pinNumber) {
299- const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
371+ struct pin_timer *pt;
372+ k_spinlock_key_t key;
373+
374+ if (k_is_in_isr ()) {
375+ return ;
376+ }
377+
378+ k_mutex_lock (&timer_cfg_lock, K_FOREVER);
379+
380+ pt = find_pin_timer (pinNumber, true );
381+
382+ if (pt == nullptr ) {
383+ k_mutex_unlock (&timer_cfg_lock);
384+ return ;
385+ }
386+
387+ key = k_spin_lock (&pt->lock );
388+ k_timer_stop (&pt->timer );
389+ pt->count = 0 ;
390+ pt->infinity = false ;
391+ pt->pin = pin_size_t (-1 );
392+ k_spin_unlock (&pt->lock , key);
393+
394+ gpio_pin_set_dt (&arduino_pins[pinNumber], 0 );
300395
301- k_timer_stop (&arduino_pin_timers[pinNumber].timer );
302- gpio_pin_set_dt (spec, 0 );
396+ k_mutex_unlock (&timer_cfg_lock);
303397}
304398
305399__attribute__ ((always_inline)) void delay(unsigned long ms) {
0 commit comments