реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Принудительное размещение локальной переменной в стеке, Компилятор IAR EW3.30A (MSP430F449)
Petrooo
сообщение Feb 12 2007, 17:31
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 21-10-05
Пользователь №: 9 922



Добрый день, уважаемые коллеги!
Компилятор размещает локальные переменные, определенные в теле функции либо в регистрах, либо в стеке.
Код
void Func(char Var1) {
char Var2;
...
Var2 = Var1;
...
}

Если переменная 1 или 2-х байтная, то скорее всего компилятор ее разместит в регистрах.
А мне нужно, чтобы он принудительно разместил ее (Var2) в сегменте стека.
А еще лучше, если сразу Var1 будет размещаться в стеке.
Как мне его это заставить сделать?
Go to the top of the page
 
+Quote Post
vmp
сообщение Feb 12 2007, 18:13
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070



Цитата(Petrooo @ Feb 12 2007, 17:31) *
А мне нужно, чтобы он принудительно разместил ее (Var2) в сегменте стека.


Вызвать подпрограмму, которой передать в качестве аргумента адрес Var2.


void dummy(int *p)
{
}

void func(void)
{
int Var2;
dummy(&var2);
}
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Feb 12 2007, 18:55
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(vmp @ Feb 12 2007, 19:13) *
Вызвать подпрограмму, которой передать в качестве аргумента адрес Var2.

Компилятор может точно так же поместить в регистры указатель.
Поэтому встает вопрос о целях автора. Какая разница, где переменная, указатель и прочее?
По большому счету задай оптимизацию - по коду или быстродействию и отдайся компилятору, закрыв глаза. wink.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
vmp
сообщение Feb 12 2007, 19:21
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070



Цитата(Dog Pawlowa @ Feb 12 2007, 18:55) *
Цитата(vmp @ Feb 12 2007, 19:13) *

Вызвать подпрограмму, которой передать в качестве аргумента адрес Var2.

Компилятор может точно так же поместить в регистры указатель.

В вызываемой подпрограмме - да. А в вызывающей переменная будет создана на стеке, ибо регистры (по крайней мере в данной архитектуре) адреса не имеют.
Go to the top of the page
 
+Quote Post
rezident
сообщение Feb 12 2007, 20:50
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(vmp @ Feb 12 2007, 21:21) *
Цитата(Dog Pawlowa @ Feb 12 2007, 18:55) *

Цитата(vmp @ Feb 12 2007, 19:13) *

Вызвать подпрограмму, которой передать в качестве аргумента адрес Var2.

Компилятор может точно так же поместить в регистры указатель.

В вызываемой подпрограмме - да. А в вызывающей переменная будет создана на стеке, ибо регистры (по крайней мере в данной архитектуре) адреса не имеют.

Это зависит от компилятора. В IAR, например, передача параметров функции производится через регистры R15-R12. Если же размер параметров функции превышает совокупный размер этих регистров то тогда да, параметры передаются через стек.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 12 2007, 21:06
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(rezident @ Feb 12 2007, 19:50) *
Если же размер параметров функции превышает совокупный размер этих регистров то тогда да, параметры передаются через стек.
Для того, чтобы передать адрес переменной, эта переменная должна иметь адрес, т.е. находиться в памяти а не в регистрах. Что и требовалось.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
rezident
сообщение Feb 12 2007, 22:31
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Сергей Борщ @ Feb 12 2007, 23:06) *
Цитата(rezident @ Feb 12 2007, 19:50) *

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

Извиняюсь, невнимательно прочитал сообщения топика.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 12 2007, 23:07
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(rezident @ Feb 12 2007, 21:31) *
Извиняюсь, невнимательно прочитал сообщения топика.
Похоже я тоже невнимательно читал. Если передавать Var1 прямо в стеке, можно попробовать что-то вроде
Код
typedef struct
{
   char Value;
} char_struct_t;

void Func(char_struct_t Var1)
По идее структура должна передаваться через стек, но никто не гарантирует, что оптимизатор не окажется слишком умным и не решит, что такая структура влезет и в регистр.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Feb 13 2007, 10:37
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Сергей Борщ @ Feb 13 2007, 00:07) *
но никто не гарантирует, что оптимизатор не окажется слишком умным и не решит, что такая структура влезет и в регистр.

Ребят, ну давайте не пытаться быть умнее компилятора! :-)
Я вот прикинул.... Я пишу программы для микропроцессоров и микроконтроллеров 22 года, из них 16 последних на ЯВУ, и ни разу не задумывался, как передаются параметры в функцию.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Petrooo
сообщение Feb 13 2007, 15:15
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 21-10-05
Пользователь №: 9 922



ссори за долгое отсутствие
Цитата(Dog Pawlowa @ Feb 13 2007, 10:37) *
Ребят, ну давайте не пытаться быть умнее компилятора! :-)
Я вот прикинул.... Я пишу программы для микропроцессоров и микроконтроллеров 22 года, из них 16 последних на ЯВУ, и ни разу не задумывался, как передаются параметры в функцию.

Пишу для микропроцессоров менее 22 лет, но вот пришлось задуматься где передаются параметры smile.gif
Есть девайс (ККМ), в котором пользователь иногда запускает "критический" процесс с "критическими" секциями исполнения программы. Например печать журнала чеков. Если при печати вырубается питание, то по включении ККМ должна продолжить печать с того чека, на котором прервалась печать. Причем все накопления по предыдущим чекам не должны пропасть.
Что я делаю:
1. при выключении питания по прерыванию сохраняю адрес критической секции (печать одного чека)
2. ее параметры - номер чека и прочее
3 и стек в котором лежат локальные переменные

По включению девайс:
1. проходит все начальные тесты и прочее
2. смотрит была ли "свертка"
3. если была, восстанавливаю адрес верхушки стека
Код
asm ("MOV.W  &SVERTKA+2, SP");

и его содержимое
4. перехожу по адресу
Код
asm ("BR     &SVERTKA+4");


Теперь, полагаю, уважаемой публике стало понятно, почему собственно встал вопрос топика.
Локальные переменные, которые в стеке свои значения "сохранили" от старого сеанса,
а которые в регистрах - похерились!
Можно, конечно, при свертке еще и регисты сохранять, но думал, что можно забороть умный копмилятор еще более умной директивой или ключевым словом, которые я не нарыл smile.gif
Пока решил проблему так:
чтобы меньше переделывать код тупо "умыл" компилятор, объявив Var2 8-ым байтным long long'ом (в регистры запухнуть это копмилятору оказалось слабо)!

Кстати, если мне не изменяет память, я уже как то поднимал эту тему на форуме, было бы интересно узнать, кто как сворачивается-разворачивается по выкл/вкл в аналогичных ситуациях.
Go to the top of the page
 
+Quote Post
rezident
сообщение Feb 13 2007, 15:30
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Petrooo @ Feb 13 2007, 17:15) *
Кстати, если мне не изменяет память, я уже как то поднимал эту тему на форуме, было бы интересно узнать, кто как сворачивается-разворачивается по выкл/вкл в аналогичных ситуациях.

ИМХО проще иметь глобальную структуру глобальных переменных. Тогда критические данные можно разместить последовательно (рядом) в такой структуре. Сохранять их в таком случае проще - всегда известно где они лежат и каков размер критической секции данных.
"Рубанули питание" для случая применения MSP430 звучит несколько странно. Если есть детектор "вырубания", то конденсатора на две-три сотни мкФ или ионистора (или литиевой батарейки на худой конец) вполне хватит чтобы завершить сохранение критически важных данных.
Go to the top of the page
 
+Quote Post
АДИКМ
сообщение Feb 13 2007, 16:08
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 630
Регистрация: 2-08-05
Пользователь №: 7 294



Цитата(Petrooo @ Feb 13 2007, 16:15) *
ссори за долгое отсутствие
Цитата(Dog Pawlowa @ Feb 13 2007, 10:37) *

Ребят, ну давайте не пытаться быть умнее компилятора! :-)
Я вот прикинул.... Я пишу программы для микропроцессоров и микроконтроллеров 22 года, из них 16 последних на ЯВУ, и ни разу не задумывался, как передаются параметры в функцию.

Пишу для микропроцессоров менее 22 лет, но вот пришлось задуматься где передаются параметры smile.gif
Есть девайс (ККМ), в котором пользователь иногда запускает "критический" процесс с "критическими" секциями исполнения программы. Например печать журнала чеков. Если при печати вырубается питание, то по включении ККМ должна продолжить печать с того чека, на котором прервалась печать. Причем все накопления по предыдущим чекам не должны пропасть.
Что я делаю:
1. при выключении питания по прерыванию сохраняю адрес критической секции (печать одного чека)
2. ее параметры - номер чека и прочее
3 и стек в котором лежат локальные переменные

По включению девайс:
1. проходит все начальные тесты и прочее
2. смотрит была ли "свертка"
3. если была, восстанавливаю адрес верхушки стека
Код
asm ("MOV.W  &SVERTKA+2, SP");

и его содержимое
4. перехожу по адресу
Код
asm ("BR     &SVERTKA+4");


Теперь, полагаю, уважаемой публике стало понятно, почему собственно встал вопрос топика.
Локальные переменные, которые в стеке свои значения "сохранили" от старого сеанса,
а которые в регистрах - похерились!
Можно, конечно, при свертке еще и регисты сохранять, но думал, что можно забороть умный копмилятор еще более умной директивой или ключевым словом, которые я не нарыл smile.gif
Пока решил проблему так:
чтобы меньше переделывать код тупо "умыл" компилятор, объявив Var2 8-ым байтным long long'ом (в регистры запухнуть это копмилятору оказалось слабо)!

Кстати, если мне не изменяет память, я уже как то поднимал эту тему на форуме, было бы интересно узнать, кто как сворачивается-разворачивается по выкл/вкл в аналогичных ситуациях.



Скажите, а как Вы успеваете сохранится? Ведь у вас термопринтер потребляет немало...
Вы уверены, что Z или X отчет надо продолжать печатать с того же места, а не заново?

А для того чтобы данные передавались как вам надо, может проще эти процедуры на ассемблере написать?


--------------------
летаю на пепелаце...
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Feb 13 2007, 16:34
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Petrooo @ Feb 13 2007, 16:15) *
Кстати, если мне не изменяет память, я уже как то поднимал эту тему на форуме, было бы интересно узнать, кто как сворачивается-разворачивается по выкл/вкл в аналогичных ситуациях.


Ну, теперь понятно smile.gif

1. Использую измерение напряжения до стабилизатора, чтобы вовремя отключить все энергопотребляющие узлы, чтобы контроллер насладился сохранением статистики в ЕЕПРОМ.
2. Чтобы статистика не попортилась, делаю это только только в критических местах.
3. Реализую алгоритм прибора в виде массива функций, а текущим индексом массива является глобальная переменная "статус".
4. Не использую стек для таких функций, но, чтобы памяти хватило, использую одни и те же глобальные переменные в каждой функции, переопределяя их каждый раз в целях соответствия имени физическому смыслу (комментарии не пишу, компенсируя это именами).

Собственно, все... После сброса контроллер инициализируется и сразу выходит на ту функцию, где он был.

Были мысли про стек, но больше риск влететь куда-то не туда, и возникает зависимость от платформы, а я это не люблю - контроллеры приходят и уходят, а люди остаются smile.gif

Да, еще... (прочитал, что написал ув. Rezident) - пп 3 и 4 нужны , если нужно быстро перезапуститься (например, помехи жуткие и проч.) Если обычный процесс выключения, пусть нештатного - можно ведь сохраниться в EEPROM без проблем - т.е. пп. 1 и 2 достаточно.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
_Bill
сообщение Feb 13 2007, 17:08
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(Petrooo @ Feb 12 2007, 17:31) *
Добрый день, уважаемые коллеги!
Компилятор размещает локальные переменные, определенные в теле функции либо в регистрах, либо в стеке.
Код
void Func(char Var1) {
char Var2;
...
Var2 = Var1;
...
}

Если переменная 1 или 2-х байтная, то скорее всего компилятор ее разместит в регистрах.
А мне нужно, чтобы он принудительно разместил ее (Var2) в сегменте стека.
А еще лучше, если сразу Var1 будет размещаться в стеке.
Как мне его это заставить сделать?

Попробуйте объявить ее как auto. А вообще, компилятор достаточно "умный". Он должен "увидеть" ссылку на адрес переменной и разместить ее в стеке.
Go to the top of the page
 
+Quote Post
Petrooo
сообщение Feb 13 2007, 17:32
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 21-10-05
Пользователь №: 9 922



Цитата(rezident @ Feb 13 2007, 15:30) *
ИМХО проще иметь глобальную структуру глобальных переменных. Тогда критические данные можно разместить последовательно (рядом) в такой структуре. Сохранять их в таком случае проще - всегда известно где они лежат и каков размер критической секции данных.
"Рубанули питание" для случая применения MSP430 звучит несколько странно. Если есть детектор "вырубания", то конденсатора на две-три сотни мкФ или ионистора (или литиевой батарейки на худой конец) вполне хватит чтобы завершить сохранение критически важных данных.

Как говориться, кто в лес, а кто по дрова! smile.gif
Хм, разве была речь о том, что чего там не хватит для сохранения чего то???
Агрументы самой свертки разумеется универсальны и лежат в глобальной структуре.
Но вот после того как куда-то вернулись и продолжаем рабуту дальше в "штатном режиме" по функционалу, тут уже в разных функциях по разному и универсальными глобальными структурами не опишешь. Не универсальный механизм получается, бестолково.

Цитата
"Рубанули питание" для случая применения MSP430 звучит несколько странно.

Абсолютно верно, но это только мы знаем, что проц полюбому на батарейке и что тумблером аппаратно вырубается только принтер и подсветка индикатора, а проц ушел в LPM3 smile.gif

Цитата(АДИКМ @ Feb 13 2007, 16:08) *
Скажите, а как Вы успеваете сохранится? Ведь у вас термопринтер потребляет немало...
Вы уверены, что Z или X отчет надо продолжать печатать с того же места, а не заново?

Термопринтер, индикатор разумеется вырубается сразу по тумблеру.
Коллега, не путайте: X/Z-отчет - это одно, а КЛ (контрольная лента) - это другое.
Отчеты по свертке перепечатываются заново, а печать КЛ продолжается с того чека, где зарубились (чек перепечетывается заново). Но это уже заморочки ТУ на девайс smile.gif
Цитата
А для того чтобы данные передавались как вам надо, может проще эти процедуры на ассемблере написать?

Эк, Вы куда, коллега, хватили!
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 5th July 2025 - 20:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01542 секунд с 7
ELECTRONIX ©2004-2016