Arduino, код странным образом зависает при вызове функции

#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. Спасибо, теперь это имеет смысл