Перейти к содержанию
    

Функции требующие статической памяти

Доброго времени суток!

 

Столкнулся с тем, что не хватает памяти на микроконтроллере. Начал копать и выяснил, что больше всего памяти потребляет вызов функции, которая у меня занимается вычислениями по калибровочным таблицам (кусочно-линейная аппроксимация). Поскольку мое устройство должно поддерживать большое количество датчиков, вызов этой функции осуществляется из разных мест программы. Добавления каждого нового вызова этой функции вызывает у меня увеличение потребления статической памяти. Я долго думал можно ли с этим что либо поделать, но так и не придумал. Ниже привожу примеры использования.\

 

Собственно сами функции:

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 в каждом подобном классе приводит к резкому возрастанию выделения статической памяти. В итоге у меня ее просто не хватает. Что можно с этим поделать, есть идеи?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Начал копать и выяснил, что больше всего памяти потребляет вызов функции

Добавления каждого нового вызова этой функции вызывает у меня увеличение потребления статической памяти

 

б-р-р-р, вы путаете понятия.

Каждый вызов функции увеличивает потребление стека. Но по выходу из функции размер стека возвращается к значению до вызова. Рекурсий у вас тут не видно

 

Для каждого типа термопары у меня по два объекта соответствующего класса.

 

попробовать typeSCalibrationTable сделать как static const

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

б-р-р-р, каждый вызов функции увеличивает потребление стека. Но по выходу из функции размер стека возвращается к значению до вызова. Рекурсий у вас тут не видно

 

 

 

попробовать typeSCalibrationTable сделать как static const

 

Нет, в том то и дело, что работа со стеком это динамика, статически выделяемая память при компиляции тут не при чем (точнее она при чем только при указании размера стека). Я не спорю с тем фактом, что увеличением вызовов увеличит потребление стека, это я понимаю. Проблема в том, что у меня увеличивается объем выделенной статической памяти, на этапе компиляции (секция ZI-data), при увеличении точек входа в эту злосчастную функцию в программе.

 

typeSCalibrationTable уже как static const, я забыл это упомянуть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

typeSCalibrationTable уже как static const, я забыл это упомянуть.

Покажите определение. Скорее всего не хватает ещё одного const.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Покажите определение. Скорее всего не хватает ещё одного 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,
... много много значений ...
};

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А проц какой? Не AVR ли часом. Для него одного const мало. Надо еще __flash добавлять. Вроде так раньше было.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А проц какой? Не AVR ли часом. Для него одного const мало. Надо еще __flash добавлять. Вроде так раньше было.

 

stm32f042

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А компилятор какой?

 

по слову ZI-data определяется что это Keil

автор, попробуйте массив вынести из класса и подепить его через конструктор или Extern

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

по слову ZI-data определяется что это Keil

автор, попробуйте массив вынести из класса и подепить его через конструктор или Extern

 

Да компилятор keil.

Моя вина - не сказал. Так и было с самого начала, в классе лишь указатель на этот массив.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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, такая константа будет глобальной в проекте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

const в плюсах делает Ваш массив локальным в пределах единицы компиляции, так что static было писать не обязательно.

В результате в каждом .с файле, где этот массив используется появляется ещё одна его копия.

 

Если нужны константные данные, но доступные из разных файлов, объявляйте их как extern const, такая константа будет глобальной в проекте.

 

Спасибо, теперь буду знать. Но я использую указатель на этот массив, разве это должно приводить к такому значительному увеличению потребления статически выделенной оперативной памяти?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

при увеличении точек входа в эту злосчастную функцию в программе.

 

как обход этой проблемы, могу предложить решение в лоб - сделать одну точку входа.

При RTOS это делается через очередь

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

как обход этой проблемы, могу предложить решение в лоб - сделать одну точку входа.

При RTOS это делается через очередь

 

Ну да, похоже придется так и сделать. Не очень красивый способ, как мне кажется, но когда я переделал таким образом потребление памяти уменьшилось в разы. У меня кстати нет ртос в этом проекте, слишком мало памяти у проца и слишком много всего надо впихнуть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, теперь буду знать. Но я использую указатель на этот массив, разве это должно приводить к такому значительному увеличению потребления статически выделенной оперативной памяти?

Если Вы используете в своей программе имя массива (которое является указателем на его первый элемент), то где-то должен существовать и сам массив, иначе получите ошибку при компиляции.

Если массив определяется в этом-же файле, то всё хорошо. Если массив в другом файле, компилятору нужно сообщить о его существовании и о его типе:

extern const float typeSCalibrationTable[];

чтобы компилятор знал что такой массив существует, но где-то высоко в горах, не в нашем файле.

 

Судя по тому, что у Вас сообщений об ошибках при компиляции нет, тут ситуация такая:

Вы скорее всего поместили объявление массива в .h файл и включаете его во все компилируемые .c файлы с помощью #include.

Но тогда получается что в каждом компилируемом файле появляется свой массив по имени typeSCalibrationTable, но он локальный, виден только в пределах .c файла, в другом .с файле тоже будет такой-же массив, тоже локальный в пределах своего файла.

Всё работает как надо, но массивы плодятся как кролики.

 

Как исправить:

Определите массив только в одном .c файле. Для С++ нужно писать

extern const float typeSCalibrationTable[]={ .... };

Для просто С можно без extern, в С массив и так будет глобальным ( а static как раз сделает его локальным со всеми вышеописанными проблемами).

 

Во всех остальных файлах помещаете описание, его можно поместить в подходящий .h или прямо в .с писать:

extern const float typeSCalibrationTable[];

 

Но это С-стиль, а в С++ можно сделать этот массив статическим членом подходящего класса и обращаться к нему как имя_класса::typeSCalibrationTable.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...