LD.ехе:linker_script.ЛД:138 не может двигаться счетчика назад | ArduinoFFT об ошибке
Плате: Ардуино Нано 33 Бле смысле
Я потянув данные PCM из встроенного микрофона и запустить ее через библиотеку arduinoFFT (версия 1.5.6), чтобы получить спектрограмму. Поскольку библиотека arduinoFFT требует, чтобы данные были массивом двойников, я преобразовал данные из нескольких дважды, и начал процесс БПФ. БПФ.Многооконность() функция работает нормально, но я получаю ошибку в БПФ.Вычислить() вызов функции (строка 77). Ошибка исчезает, когда я удалить вызов функции. Ошибка:
Found 25 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <arduinoFFT> 1.5.6
|-- <PDM> 1.0
Building in release mode
Linking .pio\build\nano33ble\firmware.elf
c:/users/benlu/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-
eabi/8.2.1/../../../../arm-none-eabi/bin/ld.exe:linker_script.ld:138 cannot move location counter
backwards (from 000000002004a470 t
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\nano33ble\firmware.elf] Error 1
И код:
#include "Mic.h"
#include <arduinoFFT.h>
// FFT
arduinoFFT FFT = arduinoFFT(); /* Create FFT object */
/*
These values can be changed in order to evaluate the functions
*/
const uint16_t samples = 16128; //This value MUST ALWAYS be a power of 2
const double signalFrequency = 16000;
const double samplingFrequency = 16000;
const uint8_t amplitude = 100;
/*
These are the input and output vectors
Input vectors receive computed results from FFT
*/
double vImag[samples] = {0};
// buffer to read samples into, each sample is 16-bits
short* sample_buffer;
// number of samples read, read from Mic class on loop
volatile int samples_read;
// The length of the buffer to use. Currently set to 4 seconds.
int buffer_size = 16000;
double double_buffer[16384] = {};
// Instantiate
Mic mic;
// DO NOT PRINT INSIDE THIS FUNCTION - Causes it to hang.
void onPDMdata() {
mic.sample();
}
void setup() {
Serial.begin(115200);
while (!Serial);
PDM.onReceive(onPDMdata);
PDM.setBufferSize(16128);
Serial.println("3...");
delay(1000);
Serial.println("2...");
delay(1000);
Serial.println("1...");
delay(1000);
Serial.println("Listening!");
mic.begin();
}
void loop() {
// wait for samples to be read
samples_read = mic.samples_read();
// If desired buffer size is reached.
if (samples_read >= buffer_size) {
// Retrieves audio buffer
sample_buffer = mic.sample_buffer();
// print samples to the serial monitor or plotter
for (int i = 0; i < samples_read; i++) {
double_buffer[i] = (double)(sample_buffer[i]);
Serial.println(double_buffer[i]);
}
Serial.println("---------- SAMPLE BREAK ----------");
FFT.Windowing(double_buffer, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(double_buffer, vImag, samples, FFT_FORWARD); /* Compute FFT <--------------------- THIS LINE */
// FFT.ComplexToMagnitude(double_buffer, vImag, samples); /* Compute magnitudes */
// delay for data collection only, comment when not collecting
delay(1000);
Serial.println("Listening!");
// clear the read count and resume recording
mic.clear_buffer();
}
}
Где я могу начать устранять эту проблему? Мне раньше не приходилось сталкиваться с ошибками компоновщика, так что любые указатели будут очень ценны. Заранее спасибо!
@Ben L, 👍2
Обсуждение1 ответ
Лучший ответ:
Короткая Версия
Короткий ответ заключается в том, что вы исчерпали оперативную память.
Только эти два массива:
const uint16_t samples = 16128;
double vImag[samples] = {0};
double double_buffer[16384] = {};
...занимаете ли вы (16128 + 16384) * 8 == 260096 байты памяти. Всего в нем всего 262144 байта оперативной памяти.
Судя по тому, как настроен сценарий компоновщика, для стека зарезервировано не менее 1024 байт, и нет никаких сомнений в том, что где-то используется по крайней мере еще один кБайт. В файлах Mbed OS и Arduino core, если ничего больше.
Что касается того , почему он терпит неудачу только при вызове Compute
, то все сводится к тому, что оптимизатор компилятора обнаруживает, что один (а возможно, и оба) ваших массива на самом деле не используются, и поэтому не входит в микс при запуске компоновщика.
Подробности
Теоретически вы должны были бы получить несколько более приятное и понятное сообщение от УТВЕРЖДЕНИЯ
в скрипте компоновщика:
ASSERT(. <= (ORIGIN(RAM) + LENGTH(RAM) - 1024), "heap region overflowed into stack");
Таким образом, вместо этого вы должны были увидеть на своем экране ошибку "область кучи перетекла в стек", которую, возможно, не так просто расшифровать пользователю Arduino, но куча и стек-это термины, которые рано или поздно будут распознаны как связанные с памятью.
Однако исполняемый файл компоновщика, поставляемый вместе с текущей версией 1.3.2 ядра Arduino для Mbed, полностью игнорирует
операторы ASSERT; я проверил это (и проверил свое понимание моего теста с помощью компоновщика amd64). Предположительно, есть опция сборки для компоновщика или опция командной строки или конфигурационного файла, которая управляет этим, но я ее еще не нашел. В любом случае он игнорирует полезное УТВЕРЖДЕНИЕ
и вместо этого продолжает терпеть неудачу в строке 138, упомянутой в сообщении об ошибке:
. = ORIGIN(RAM) + LENGTH(RAM) - 1024;
Вы можете видеть, что он включает в себя то же самое выражение, просто без полезного сообщения, если что-то пойдет не так. "счетчик местоположений" в сообщении-это термин, связанный с компоновщиком, который примерно означает "где будет помещена следующая вещь в память", поскольку он собирает ваш окончательный исполняемый файл из отдельно скомпилированных фрагментов. Вы использовали так много оперативной памяти в своей программе, что счетчик местоположения был перенесен мимо того места, где сценарий компоновщика хочет поместить символ __HeapLimit
, на 1K от конца оперативной памяти MCU. Предполагается, что счетчик местоположения будет монотонно увеличиваться. Таким образом, вычисление этого выражения приводит к ошибочной попытке "переместить счетчик местоположения назад".
Ух ты, спасибо за исчерпывающий ответ! Я пытался поднять голос, но у меня недостаточно репутации, чтобы показать ха-ха, я хотел, чтобы вы знали, что я очень, очень ценю ваш ответ! Так что, похоже, я использовал слишком много памяти, и мне нужно найти новый подход. Спасибо!, @Ben L
Хорошая сделка. Я собирался просто сказать: "все в порядке" или что ты можешь вернуться, если вспомнишь. Я забыл, что для этого существует порог, но я также еще не поддержал ваш вопрос. Сделав это, вы должны иметь возможность озвучивать все, что вам нравится., @timemage
- GCC msg "note: in definition of macro 'max'" сообщение об ошибке
- Есть ли константа для максимального значения Unsigned Long в компиляторе Arduino?
- Необработанный строковый литерал Arduino IDE C++ 11 имеет проблемы с // в http://, компилятор считает, что // это комментарий
- Не могу использовать uint16_t в библиотеке
- Неопределенная ссылка на функцию в пользовательской библиотеке
- Использование Arduino в качестве автономного компилятора
- Существует ли компилятор с открытым исходным кодом для кодов Arduino Sketch?
- Разделение кода на несколько файлов приводит к ошибке "multiple definition" и "undefined reference".
`c:/users/benlu/.platformio-Из этого я заключаю, что вы используете platformio, что может иметь важное значение. Вы пробовали построить это с помощью официальных инструментов arduino-builder/arduino-cli (или, знаете, с помощью IDE)?, @timemage
samples = 16128; //Это значение ВСЕГДА должно быть степенью 2
- 16128 не является степенью двух. (вероятно, не имеет значения), @Mat@Мат-ха-ха, ты прав! У меня это было установлено правильно, но я пошел на перенумеровку, пытаясь решить еще одну проблему... спасибо за улов!, @Ben L
@timemage Я только что попробовал его в Arduino IDE и столкнулся с той же самой точной ошибкой., @Ben L