yanvasilij 0 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба Доброго времени суток! Столкнулся с тем, что не хватает памяти на микроконтроллере. Начал копать и выяснил, что больше всего памяти потребляет вызов функции, которая у меня занимается вычислениями по калибровочным таблицам (кусочно-линейная аппроксимация). Поскольку мое устройство должно поддерживать большое количество датчиков, вызов этой функции осуществляется из разных мест программы. Добавления каждого нового вызова этой функции вызывает у меня увеличение потребления статической памяти. Я долго думал можно ли с этим что либо поделать, но так и не придумал. Ниже привожу примеры использования.\ Собственно сами функции: float plaStraight (const float *calibrationTable, float delta, float minValue, float maxValue, float inValue) { int i; float outValue = minValue; if (inValue > calibrationTable[i = 0]) while (maxValue >= outValue) { if (inValue < calibrationTable[++i]) return outValue + (inValue - calibrationTable[i-1]) * delta / (calibrationTable[i] - calibrationTable[i-1]); outValue += delta; }; return outValue; } float plaStraight (const float *calibrationTable, float delta, float minValue, float maxValue, float inValue) { int i; float outValue = minValue; if (inValue > calibrationTable[i = 0]) while (maxValue >= outValue) { if (inValue < calibrationTable[++i]) return outValue + (inValue - calibrationTable[i-1]) * delta / (calibrationTable[i] - calibrationTable[i-1]); outValue += delta; }; return outValue; } float plaRevers (const float *calibrationTable, u32 len, float reversDelta, float minValue, float inValue) { float outValue = calibrationTable[len - 1]; float inValue0 = minValue; float straightDelta; int i = 0; outValue = calibrationTable[len - 1]; inValue0 = minValue; if ( inValue > inValue0 ) { while ( calibrationTable[len-1] >= outValue ) { i++; if ( inValue < (inValue0 + reversDelta) ) { straightDelta = calibrationTable[i] - calibrationTable[i-1]; outValue = calibrationTable[i-1] + ((inValue - inValue0) * straightDelta / reversDelta); return outValue; } outValue = calibrationTable[i]; inValue += reversDelta; } outValue = calibrationTable[len-1]; } return outValue; } Пример класса, в котором используются эти функции class TermocoupleSProcessor: public TermocoupleProcessorBase { public: virtual float calcTemperature (float eds) { return plaStraight (typeSCalibrationTable, 10.0, -50.0f, 1760.0f, eds); //<<<Добавления этой строчки приводит к большому выделению памяти } virtual float calcEds (float t) { return plaRevers(typeSCalibrationTable, CALIBRATION_TABLE_LEN, 10.0f, -50.0f, t);//<<<Добавления этой строчки приводит к большому выделению памяти } virtual void init (void) { sensorType = TermocoupleS; conversationIsReady = 0; } }; Объекты я объявляю статически. Для каждого типа термопары у меня по два объекта соответствующего класса. Добавления вызова plaStraight и plaStraight в каждом подобном классе приводит к резкому возрастанию выделения статической памяти. В итоге у меня ее просто не хватает. Что можно с этим поделать, есть идеи? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 3 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба Начал копать и выяснил, что больше всего памяти потребляет вызов функции Добавления каждого нового вызова этой функции вызывает у меня увеличение потребления статической памяти б-р-р-р, вы путаете понятия. Каждый вызов функции увеличивает потребление стека. Но по выходу из функции размер стека возвращается к значению до вызова. Рекурсий у вас тут не видно Для каждого типа термопары у меня по два объекта соответствующего класса. попробовать typeSCalibrationTable сделать как static const Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба б-р-р-р, каждый вызов функции увеличивает потребление стека. Но по выходу из функции размер стека возвращается к значению до вызова. Рекурсий у вас тут не видно попробовать typeSCalibrationTable сделать как static const Нет, в том то и дело, что работа со стеком это динамика, статически выделяемая память при компиляции тут не при чем (точнее она при чем только при указании размера стека). Я не спорю с тем фактом, что увеличением вызовов увеличит потребление стека, это я понимаю. Проблема в том, что у меня увеличивается объем выделенной статической памяти, на этапе компиляции (секция ZI-data), при увеличении точек входа в эту злосчастную функцию в программе. typeSCalibrationTable уже как static const, я забыл это упомянуть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба typeSCalibrationTable уже как static const, я забыл это упомянуть. Покажите определение. Скорее всего не хватает ещё одного const. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба Покажите определение. Скорее всего не хватает ещё одного const. static const float typeSCalibrationTable[] = { -0.226, -0.188, -0.145, -0.1, -0.051, 0, 0.054, 0.111, 0.171, 0.232, 0.296, 0.363, ... много много значений ... }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ashr 0 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба А проц какой? Не AVR ли часом. Для него одного const мало. Надо еще __flash добавлять. Вроде так раньше было. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба А проц какой? Не AVR ли часом. Для него одного const мало. Надо еще __flash добавлять. Вроде так раньше было. stm32f042 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба А компилятор какой? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 3 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба А компилятор какой? по слову ZI-data определяется что это Keil автор, попробуйте массив вынести из класса и подепить его через конструктор или Extern Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба по слову ZI-data определяется что это Keil автор, попробуйте массив вынести из класса и подепить его через конструктор или Extern Да компилятор keil. Моя вина - не сказал. Так и было с самого начала, в классе лишь указатель на этот массив. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 4 24 февраля, 2016 Опубликовано 24 февраля, 2016 · Жалоба static const float typeSCalibrationTable[] = { -0.226, -0.188, -0.145, -0.1, -0.051, 0, 0.054, 0.111, 0.171, 0.232, 0.296, 0.363, ... много много значений ... }; const в плюсах делает Ваш массив локальным в пределах единицы компиляции, так что static было писать не обязательно. В результате в каждом .с файле, где этот массив используется появляется ещё одна его копия. Если нужны константные данные, но доступные из разных файлов, объявляйте их как extern const, такая константа будет глобальной в проекте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 25 февраля, 2016 Опубликовано 25 февраля, 2016 · Жалоба const в плюсах делает Ваш массив локальным в пределах единицы компиляции, так что static было писать не обязательно. В результате в каждом .с файле, где этот массив используется появляется ещё одна его копия. Если нужны константные данные, но доступные из разных файлов, объявляйте их как extern const, такая константа будет глобальной в проекте. Спасибо, теперь буду знать. Но я использую указатель на этот массив, разве это должно приводить к такому значительному увеличению потребления статически выделенной оперативной памяти? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 3 25 февраля, 2016 Опубликовано 25 февраля, 2016 · Жалоба при увеличении точек входа в эту злосчастную функцию в программе. как обход этой проблемы, могу предложить решение в лоб - сделать одну точку входа. При RTOS это делается через очередь Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 26 февраля, 2016 Опубликовано 26 февраля, 2016 · Жалоба как обход этой проблемы, могу предложить решение в лоб - сделать одну точку входа. При RTOS это делается через очередь Ну да, похоже придется так и сделать. Не очень красивый способ, как мне кажется, но когда я переделал таким образом потребление памяти уменьшилось в разы. У меня кстати нет ртос в этом проекте, слишком мало памяти у проца и слишком много всего надо впихнуть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 4 26 февраля, 2016 Опубликовано 26 февраля, 2016 · Жалоба Спасибо, теперь буду знать. Но я использую указатель на этот массив, разве это должно приводить к такому значительному увеличению потребления статически выделенной оперативной памяти? Если Вы используете в своей программе имя массива (которое является указателем на его первый элемент), то где-то должен существовать и сам массив, иначе получите ошибку при компиляции. Если массив определяется в этом-же файле, то всё хорошо. Если массив в другом файле, компилятору нужно сообщить о его существовании и о его типе: extern const float typeSCalibrationTable[]; чтобы компилятор знал что такой массив существует, но где-то высоко в горах, не в нашем файле. Судя по тому, что у Вас сообщений об ошибках при компиляции нет, тут ситуация такая: Вы скорее всего поместили объявление массива в .h файл и включаете его во все компилируемые .c файлы с помощью #include. Но тогда получается что в каждом компилируемом файле появляется свой массив по имени typeSCalibrationTable, но он локальный, виден только в пределах .c файла, в другом .с файле тоже будет такой-же массив, тоже локальный в пределах своего файла. Всё работает как надо, но массивы плодятся как кролики. Как исправить: Определите массив только в одном .c файле. Для С++ нужно писать extern const float typeSCalibrationTable[]={ .... }; Для просто С можно без extern, в С массив и так будет глобальным ( а static как раз сделает его локальным со всеми вышеописанными проблемами). Во всех остальных файлах помещаете описание, его можно поместить в подходящий .h или прямо в .с писать: extern const float typeSCalibrationTable[]; Но это С-стиль, а в С++ можно сделать этот массив статическим членом подходящего класса и обращаться к нему как имя_класса::typeSCalibrationTable. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться