#c #arduino #interrupt
Вопрос:
У меня есть следующий код, который ведет себя странно, когда я вызываю метод
#include <TimerOne.h>
#include <cppQueue.h>
#include <Arduino.h>
typedef struct Diagnostic {
String entityName;
uint16_t pin;
} Diag;
// Global setup
cppQueue q(sizeof(Diag *), 10, FIFO, false);
int ctr = 0;
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
}
// Add to queue
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(2000); // wait for a second
Serial.println("After high");
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
// Critical Section
Diag d;
Serial.println("String assignment");
d.entityName = "Front Door";
d.pin = LED_BUILTIN;
d_ptr = amp;d;
Serial.println("Enqueuing one");
q.push(amp;d);
Serial.println("Enqueued one");
Serial.println(freeMemory());
//q.pop(amp;d);
//Serial.println("Dequeued one" d.entityName);
DequeueIsr();
//Serial.println("Atomic block");
//Serial.println(q.getCount());
//Serial.println("Loop end");
}
void DequeueIsr() {
Diag di;
if (!q.isEmpty())
{
Serial.println("Queue not empty");
q.pop(amp;di);
Serial.println("Dequeued one" di.entityName);
Serial.println(freeMemory());
}
}
Всякий раз, когда я пытаюсь вставить свой объект в функцию DequeueIsr, код зависает после 2 или 3 итераций, после этого на последовательном мониторе нет вывода. Если я просто скопирую код в методе удаления из очереди и запущу его в основном цикле, он будет работать, он не застрянет. Также это происходит, когда я работаю со строками, если я удаляю поле EntityName из Diag, оно работает внутри метода.
Я упускаю что-то важное ?
Что я действительно хотел сделать, так это освободить очередь с помощью метода прерывания с использованием библиотеки часовых поясов. Я удалил весь код, связанный с таймером, и даже простой вызов метода не работает.
Комментарии:
1. Сколько отладок вы провели и какие выводы это дало? ericlippert.com/2014/03/05/how-to-debug-small-programs
2. Serial.printlns-единственное, что мне здесь помогает, у вас есть какой-нибудь другой способ отладки ? Также, когда вы говорите insights, я уже упоминал выше, как работает код, когда я удаляю код из метода Dequeue и вставляю его в функцию loop (). Я не выделяю никакой памяти, также я проверил память стека, она сообщает 1684 на второй итерации, прежде чем застрять.
3. Я бы предположил, что оптимизатор разрушает
d
перед вызовомDequeueIsr
, что приводит к зависанию указателя в вашей очереди4. Не знаю много о cppQueue, но в обычном C
q.push(amp;d)
было бы довольно странно —d
не выделяется динамически и выйдет за рамки в концеloop()
— если вам повезетd
, всегда будет одинаковым (что, вероятно, не то, что вы хотите в любом случае).5. Вот официальный пример github.com/SMFSW/Queue/blob/master/examples/SimpleQueue/…
Ответ №1:
Похоже cppQueue
, что он копирует объекты с помощью memcpy
, поэтому он работает только с тривиально копируемыми объектами, String
не является тривиально копируемым, поэтому ваш код имеет неопределенное поведение
Комментарии:
1. github.com/SMFSW/Queue/blob/master/examples/PointersQueue/… Приведенным здесь примером из официального репо является пример со строкой*, также взяв пример кода, если я помещу его в отдельную функцию, он будет работать. Почему это так ?
2. В этом примере хранятся указатели на элементы в массиве
strings
, а не на локальные объекты (обратите внимание, чтоq.push(amp;pStr)
это передача указателя на указатель).3. Спасибо, теперь это имеет смысл