Skip to content

Commit 256868e

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 78bcf6a commit 256868e

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
@@ -223,9 +223,15 @@ static struct pin_timer {
223223
uint32_t count{0};
224224
pin_size_t pin{pin_size_t(-1)};
225225
bool infinity{false};
226-
struct k_spinlock lock;
226+
bool timer_initialized{false};
227+
struct k_spinlock lock{};
227228
} arduino_pin_timers[MAX_TONE_PINS];
228229

230+
K_MUTEX_DEFINE(timer_cfg_lock);
231+
232+
void tone_expiry_cb(struct k_timer *timer);
233+
234+
/* Callers must hold timer_cfg_lock while using this helper. */
229235
static struct pin_timer *find_pin_timer(pin_size_t pinNumber, bool active_only) {
230236
for (size_t i = 0; i < ARRAY_SIZE(arduino_pin_timers); i++) {
231237
k_spinlock_key_t key = k_spin_lock(&arduino_pin_timers[i].lock);
@@ -268,12 +274,13 @@ void tone_expiry_cb(struct k_timer *timer) {
268274
}
269275

270276
k_timer_stop(timer);
277+
pt->count = 0;
278+
pt->infinity = false;
271279
pt->pin = pin_size_t(-1);
272280
} else {
273281
if (pin != pin_size_t(-1)) {
274282
gpio_pin_toggle_dt(&arduino_pins[pin]);
275283
}
276-
277284
pt->count--;
278285
}
279286

@@ -282,24 +289,42 @@ void tone_expiry_cb(struct k_timer *timer) {
282289

283290
void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
284291
k_spinlock_key_t key;
292+
uint64_t toggles_count;
285293
struct pin_timer *pt;
286294
k_timeout_t timeout;
287295

296+
if (k_is_in_isr()) {
297+
return;
298+
}
299+
300+
k_mutex_lock(&timer_cfg_lock, K_FOREVER);
301+
288302
pt = find_pin_timer(pinNumber, false);
289303

290304
if (pt == nullptr) {
305+
k_mutex_unlock(&timer_cfg_lock);
291306
return;
292307
}
293308

309+
if (!pt->timer_initialized) {
310+
k_timer_init(&pt->timer, tone_expiry_cb, NULL);
311+
pt->timer_initialized = true;
312+
}
313+
294314
pinMode(pinNumber, OUTPUT);
295315
k_timer_stop(&pt->timer);
296316

297-
if (frequency == 0) {
317+
toggles_count = ((uint64_t)duration * frequency / (MSEC_PER_SEC / TOGGLES_PER_CYCLE));
318+
if (frequency == 0 || (toggles_count == 0 && duration != 0)) {
298319
key = k_spin_lock(&pt->lock);
320+
pt->count = 0;
321+
pt->infinity = false;
299322
pt->pin = pin_size_t(-1);
300323
k_spin_unlock(&pt->lock, key);
301324

302325
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
326+
327+
k_mutex_unlock(&timer_cfg_lock);
303328
return;
304329
}
305330

@@ -310,32 +335,43 @@ void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration)
310335

311336
key = k_spin_lock(&pt->lock);
312337
pt->infinity = (duration == 0);
313-
pt->count = min((uint64_t)duration * frequency * TOGGLES_PER_CYCLE / MSEC_PER_SEC, UINT32_MAX);
338+
pt->count = min(toggles_count, UINT32_MAX);
314339
pt->pin = pinNumber;
315340
k_spin_unlock(&pt->lock, key);
316341

317-
k_timer_init(&pt->timer, tone_expiry_cb, NULL);
318-
319-
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
342+
gpio_pin_set_dt(&arduino_pins[pinNumber], 1);
320343
k_timer_start(&pt->timer, timeout, timeout);
344+
345+
k_mutex_unlock(&timer_cfg_lock);
321346
}
322347

323348
void noTone(pin_size_t pinNumber) {
324349
struct pin_timer *pt;
325350
k_spinlock_key_t key;
326351

352+
if (k_is_in_isr()) {
353+
return;
354+
}
355+
356+
k_mutex_lock(&timer_cfg_lock, K_FOREVER);
357+
327358
pt = find_pin_timer(pinNumber, true);
328359

329360
if (pt == nullptr) {
361+
k_mutex_unlock(&timer_cfg_lock);
330362
return;
331363
}
332364

333365
key = k_spin_lock(&pt->lock);
334366
k_timer_stop(&pt->timer);
367+
pt->count = 0;
368+
pt->infinity = false;
335369
pt->pin = pin_size_t(-1);
336370
k_spin_unlock(&pt->lock, key);
337371

338372
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
373+
374+
k_mutex_unlock(&timer_cfg_lock);
339375
}
340376

341377
void delay(unsigned long ms) {

0 commit comments

Comments
 (0)