|
Функции требующие статической памяти |
|
|
|
Feb 24 2016, 05:01
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Доброго времени суток! Столкнулся с тем, что не хватает памяти на микроконтроллере. Начал копать и выяснил, что больше всего памяти потребляет вызов функции, которая у меня занимается вычислениями по калибровочным таблицам (кусочно-линейная аппроксимация). Поскольку мое устройство должно поддерживать большое количество датчиков, вызов этой функции осуществляется из разных мест программы. Добавления каждого нового вызова этой функции вызывает у меня увеличение потребления статической памяти. Я долго думал можно ли с этим что либо поделать, но так и не придумал. Ниже привожу примеры использования.\ Собственно сами функции: CODE 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 в каждом подобном классе приводит к резкому возрастанию выделения статической памяти. В итоге у меня ее просто не хватает. Что можно с этим поделать, есть идеи?
|
|
|
|
|
Feb 24 2016, 05:46
|

Профессионал
    
Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143

|
Цитата(yanvasiij @ Feb 24 2016, 08:01)  Начал копать и выяснил, что больше всего памяти потребляет вызов функции Добавления каждого нового вызова этой функции вызывает у меня увеличение потребления статической памяти б-р-р-р, вы путаете понятия. Каждый вызов функции увеличивает потребление стека. Но по выходу из функции размер стека возвращается к значению до вызова. Рекурсий у вас тут не видно Цитата(yanvasiij @ Feb 24 2016, 08:01)  Для каждого типа термопары у меня по два объекта соответствующего класса. попробовать typeSCalibrationTable сделать как static const
--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
|
|
|
|
|
Feb 24 2016, 05:59
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(megajohn @ Feb 24 2016, 10:46)  б-р-р-р, каждый вызов функции увеличивает потребление стека. Но по выходу из функции размер стека возвращается к значению до вызова. Рекурсий у вас тут не видно
попробовать typeSCalibrationTable сделать как static const Нет, в том то и дело, что работа со стеком это динамика, статически выделяемая память при компиляции тут не при чем (точнее она при чем только при указании размера стека). Я не спорю с тем фактом, что увеличением вызовов увеличит потребление стека, это я понимаю. Проблема в том, что у меня увеличивается объем выделенной статической памяти, на этапе компиляции (секция ZI-data), при увеличении точек входа в эту злосчастную функцию в программе. typeSCalibrationTable уже как static const, я забыл это упомянуть.
|
|
|
|
|
Feb 24 2016, 11:35
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(AHTOXA @ Feb 24 2016, 14:07)  Покажите определение. Скорее всего не хватает ещё одного 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, ... много много значений ... };
|
|
|
|
|
Feb 24 2016, 12:03
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(shreck @ Feb 24 2016, 16:59)  А проц какой? Не AVR ли часом. Для него одного const мало. Надо еще __flash добавлять. Вроде так раньше было. stm32f042
|
|
|
|
|
Feb 24 2016, 12:44
|

Профессионал
    
Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143

|
Цитата(AHTOXA @ Feb 24 2016, 15:30)  А компилятор какой? по слову ZI-data определяется что это Keil автор, попробуйте массив вынести из класса и подепить его через конструктор или Extern
--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
|
|
|
|
|
Feb 24 2016, 13:01
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(megajohn @ Feb 24 2016, 17:44)  по слову ZI-data определяется что это Keil автор, попробуйте массив вынести из класса и подепить его через конструктор или Extern Да компилятор keil. Моя вина - не сказал. Так и было с самого начала, в классе лишь указатель на этот массив.
|
|
|
|
|
Feb 24 2016, 17:54
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(yanvasiij @ Feb 24 2016, 18:35)  Код 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, такая константа будет глобальной в проекте.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Feb 25 2016, 05:04
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(SSerge @ Feb 24 2016, 22:54)  const в плюсах делает Ваш массив локальным в пределах единицы компиляции, так что static было писать не обязательно. В результате в каждом .с файле, где этот массив используется появляется ещё одна его копия.
Если нужны константные данные, но доступные из разных файлов, объявляйте их как extern const, такая константа будет глобальной в проекте. Спасибо, теперь буду знать. Но я использую указатель на этот массив, разве это должно приводить к такому значительному увеличению потребления статически выделенной оперативной памяти?
|
|
|
|
|
Feb 26 2016, 05:25
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(megajohn @ Feb 26 2016, 01:21)  как обход этой проблемы, могу предложить решение в лоб - сделать одну точку входа. При RTOS это делается через очередь Ну да, похоже придется так и сделать. Не очень красивый способ, как мне кажется, но когда я переделал таким образом потребление памяти уменьшилось в разы. У меня кстати нет ртос в этом проекте, слишком мало памяти у проца и слишком много всего надо впихнуть.
|
|
|
|
|
Feb 26 2016, 09:04
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(yanvasiij @ Feb 25 2016, 12:04)  Спасибо, теперь буду знать. Но я использую указатель на этот массив, разве это должно приводить к такому значительному увеличению потребления статически выделенной оперативной памяти? Если Вы используете в своей программе имя массива (которое является указателем на его первый элемент), то где-то должен существовать и сам массив, иначе получите ошибку при компиляции. Если массив определяется в этом-же файле, то всё хорошо. Если массив в другом файле, компилятору нужно сообщить о его существовании и о его типе: extern const float typeSCalibrationTable[]; чтобы компилятор знал что такой массив существует, но где-то высоко в горах, не в нашем файле. Судя по тому, что у Вас сообщений об ошибках при компиляции нет, тут ситуация такая: Вы скорее всего поместили объявление массива в .h файл и включаете его во все компилируемые .c файлы с помощью #include. Но тогда получается что в каждом компилируемом файле появляется свой массив по имени typeSCalibrationTable, но он локальный, виден только в пределах .c файла, в другом .с файле тоже будет такой-же массив, тоже локальный в пределах своего файла. Всё работает как надо, но массивы плодятся как кролики. Как исправить: Определите массив только в одном .c файле. Для С++ нужно писать extern const float typeSCalibrationTable[]={ .... }; Для просто С можно без extern, в С массив и так будет глобальным ( а static как раз сделает его локальным со всеми вышеописанными проблемами). Во всех остальных файлах помещаете описание, его можно поместить в подходящий .h или прямо в .с писать: extern const float typeSCalibrationTable[]; Но это С-стиль, а в С++ можно сделать этот массив статическим членом подходящего класса и обращаться к нему как имя_класса::typeSCalibrationTable.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|