Skip to content

Commit 1316b52

Browse files
committed
cores: arduino: zephyrCommon: rework tone slot handling and timer lifecycle
Rework tone/noTone internals to better match Arduino behavior while making concurrent tone usage configurable and safer. - Add CONFIG_ARDUINO_MAX_TONES (default: -1). - Negative values fall back to the digital pin count from devicetree. - Replace per-pin tone timer arrays with slot-based pin_timer entries. - Remove the timeout companion timer and finish finite tones by counting remaining toggles in tone_expiry_cb(). Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
1 parent 5146532 commit 1316b52

2 files changed

Lines changed: 45 additions & 9 deletions

File tree

Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ config ARDUINO_MAX_TONES
3939
default -1
4040
help
4141
Specify the maximum number of tones that can be played simultaneously with tone().
42-
If set to a negative value, the maximum number will be determined from the
43-
system's digital pin configuration.
42+
If set to -1 (or any other negative value), the maximum number will be
43+
determined from the system's digital pin configuration.
4444

4545
module = ARDUINO_API
4646
module-str = arduino_api

cores/arduino/zephyrCommon.cpp

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,15 @@ static struct pin_timer {
249249
uint32_t count{0};
250250
pin_size_t pin{pin_size_t(-1)};
251251
bool infinity{false};
252-
struct k_spinlock lock;
252+
bool timer_initialized{false};
253+
struct k_spinlock lock{};
253254
} arduino_pin_timers[MAX_TONE_PINS];
254255

256+
K_MUTEX_DEFINE(timer_cfg_lock);
257+
258+
void tone_expiry_cb(struct k_timer *timer);
259+
260+
/* Callers must hold timer_cfg_lock while using this helper. */
255261
static struct pin_timer *find_pin_timer(pin_size_t pinNumber, bool active_only) {
256262
for (size_t i = 0; i < ARRAY_SIZE(arduino_pin_timers); i++) {
257263
k_spinlock_key_t key = k_spin_lock(&arduino_pin_timers[i].lock);
@@ -294,12 +300,13 @@ void tone_expiry_cb(struct k_timer *timer) {
294300
}
295301

296302
k_timer_stop(timer);
303+
pt->count = 0;
304+
pt->infinity = false;
297305
pt->pin = pin_size_t(-1);
298306
} else {
299307
if (pin != pin_size_t(-1)) {
300308
gpio_pin_toggle_dt(&arduino_pins[pin]);
301309
}
302-
303310
pt->count--;
304311
}
305312

@@ -308,24 +315,42 @@ void tone_expiry_cb(struct k_timer *timer) {
308315

309316
void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
310317
k_spinlock_key_t key;
318+
uint64_t toggles_count;
311319
struct pin_timer *pt;
312320
k_timeout_t timeout;
313321

322+
if (k_is_in_isr()) {
323+
return;
324+
}
325+
326+
k_mutex_lock(&timer_cfg_lock, K_FOREVER);
327+
314328
pt = find_pin_timer(pinNumber, false);
315329

316330
if (pt == nullptr) {
331+
k_mutex_unlock(&timer_cfg_lock);
317332
return;
318333
}
319334

335+
if (!pt->timer_initialized) {
336+
k_timer_init(&pt->timer, tone_expiry_cb, NULL);
337+
pt->timer_initialized = true;
338+
}
339+
320340
pinMode(pinNumber, OUTPUT);
321341
k_timer_stop(&pt->timer);
322342

323-
if (frequency == 0) {
343+
toggles_count = ((uint64_t)duration * frequency / (MSEC_PER_SEC / TOGGLES_PER_CYCLE));
344+
if (frequency == 0 || (toggles_count == 0 && duration != 0)) {
324345
key = k_spin_lock(&pt->lock);
346+
pt->count = 0;
347+
pt->infinity = false;
325348
pt->pin = pin_size_t(-1);
326349
k_spin_unlock(&pt->lock, key);
327350

328351
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
352+
353+
k_mutex_unlock(&timer_cfg_lock);
329354
return;
330355
}
331356

@@ -336,32 +361,43 @@ void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration)
336361

337362
key = k_spin_lock(&pt->lock);
338363
pt->infinity = (duration == 0);
339-
pt->count = min((uint64_t)duration * frequency * TOGGLES_PER_CYCLE / MSEC_PER_SEC, UINT32_MAX);
364+
pt->count = min(toggles_count, UINT32_MAX);
340365
pt->pin = pinNumber;
341366
k_spin_unlock(&pt->lock, key);
342367

343-
k_timer_init(&pt->timer, tone_expiry_cb, NULL);
344-
345-
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
368+
gpio_pin_set_dt(&arduino_pins[pinNumber], 1);
346369
k_timer_start(&pt->timer, timeout, timeout);
370+
371+
k_mutex_unlock(&timer_cfg_lock);
347372
}
348373

349374
void noTone(pin_size_t pinNumber) {
350375
struct pin_timer *pt;
351376
k_spinlock_key_t key;
352377

378+
if (k_is_in_isr()) {
379+
return;
380+
}
381+
382+
k_mutex_lock(&timer_cfg_lock, K_FOREVER);
383+
353384
pt = find_pin_timer(pinNumber, true);
354385

355386
if (pt == nullptr) {
387+
k_mutex_unlock(&timer_cfg_lock);
356388
return;
357389
}
358390

359391
key = k_spin_lock(&pt->lock);
360392
k_timer_stop(&pt->timer);
393+
pt->count = 0;
394+
pt->infinity = false;
361395
pt->pin = pin_size_t(-1);
362396
k_spin_unlock(&pt->lock, key);
363397

364398
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
399+
400+
k_mutex_unlock(&timer_cfg_lock);
365401
}
366402

367403
unsigned long micros(void) {

0 commit comments

Comments
 (0)