Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: как в winavr сделать так чтоб в прерывании вместо push/pop было st/ld
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Kibi
есть проблема с компилятором WinAVR-20071221 в прерываниях он ставит push/pop, в результате стека не хватает, хочу заменить на st/ld, кто знает как это зделать, перейти на iar нет возможности.
Kuzmi4
Цитата(Kibi @ May 20 2008, 10:06) *
есть проблема с компилятором WinAVR-20071221 в прерываниях он ставит push/pop, в результате стека не хватает, хочу заменить на st/ld, кто знает как это зделать, перейти на iar нет возможности.


Не хотелось бы вас огорчать , но насколько я знаю в иаре тоже в прерываниях push/pop... НУ вот так они организованы....
А что за камень что стэк не помесчается ?
MrYuran
Цитата(Kibi @ May 20 2008, 10:06) *
есть проблема с компилятором WinAVR-20071221 в прерываниях он ставит push/pop, в результате стека не хватает, хочу заменить на st/ld, кто знает как это зделать, перейти на iar нет возможности.

При вызове функций и заходе в прерывания в любом случае адрес возврата сохраняется в стеке.
Также компилятор размещает на стеке локальные переменные и копии регистров, которые портятся во время обработки прерываний.
Так что не используйте в прерывании функций, не определяйте в функциях локальных переменных - и потребление стека уменьшится.
Крайний вариант - писать обработчики прерываний на асме, тогда можно сделать всё что угодно.
singlskv
Цитата(Kibi @ May 20 2008, 11:06) *
есть проблема с компилятором WinAVR-20071221 в прерываниях он ставит push/pop, в результате стека не хватает, хочу заменить на st/ld, кто знает как это зделать, перейти на iar нет возможности.
Прямо, никак...
Обходными путями можно, только весь контекст придется ручками сохранять, типа:
Код
void TIMER2_COMP_vect(void) __attribute__((signal)) __attribute__((naked));
void TIMER2_COMP_vect()
{
  {сохраняем контекст}

  {восстанавливаем контекст}
  __asm__ __volatile__("reti"); // выходим
}


Только вот непонятен до конца вопрос, как использование st/ld поможет сократить размер
необходимой памяти ?
Kibi
Цитата(singlskv @ May 20 2008, 12:08) *
Прямо, никак...
Обходными путями можно, только весь контекст придется ручками сохранять, типа:
Код
void TIMER2_COMP_vect(void) __attribute__((signal)) __attribute__((naked));
void TIMER2_COMP_vect()
{
  {сохраняем контекст}

  {восстанавливаем контекст}
  __asm__ __volatile__("reti"); // выходим
}


Только вот непонятен до конца вопрос, как использование st/ld поможет сократить размер
необходимой памяти ?


когда сохраняем регистры с помощью st они сохраняются не в стеке, а в памяти выделенной под временные переменные, а вот когда идет push то переменные сохраняются в стек, стек растет и перекрывает собой адресное пространство временных переменных, которые в свою очередь используются в прерывании, в результате стек слетаетsad.gif чуть расширю вопрос, есть ли какие нибудь дериктивы чтоб локальные переменные ни при каких условиях не занимали область памяти стека???
VladimirYU
Цитата(Kibi @ May 20 2008, 13:50) *
когда сохраняем регистры с помощью st они сохраняются не в стеке, а в памяти выделенной под временные переменные, а вот когда идет push то переменные сохраняются в стек, стек растет и перекрывает собой адресное пространство временных переменных, которые в свою очередь используются в прерывании, в результате стек слетаетsad.gif чуть расширю вопрос, есть ли какие нибудь дериктивы чтоб локальные переменные ни при каких условиях не занимали область памяти стека???


может быть static поможет?

Цитата(VladimirYU @ May 20 2008, 13:58) *
может быть static поможет?


или через heap. Сначала new потом обязательно delete.
defunct
Цитата(Kibi @ May 20 2008, 12:50) *
когда сохраняем регистры с помощью st они сохраняются не в стеке, а в памяти выделенной под временные переменные, а вот когда идет push то переменные сохраняются в стек, стек растет и перекрывает собой адресное пространство временных переменных,

Вы заблуждаетесь. Временные (локальные) переменные располагаются также в стеке, а вот глобальные лежат по строго фиксированным адресам. Обращаться к стеку можно как с помощью PUSH/POP так и с помощью LD/ST. Судя по всему у Вас просто не хватает стека для нормальной работы программы. Менять PUSH/POP на LD/ST ничего не даст если памяти не хватает. Выход здесь такой - просто увеличить объем стека (сократить количество глобальных переменных, за счет замены их локальными переменными).
Kibi
Цитата(defunct @ May 20 2008, 14:04) *
Вы заблуждаетесь. Временные (локальные) переменные располагаются также в стеке, а вот глобальные лежат по строго фиксированным адресам. Обращаться к стеку можно как с помощью PUSH/POP так и с помощью LD/ST. Судя по всему у Вас просто не хватает стека для нормальной работы программы. Менять PUSH/POP на LD/ST ничего не даст если памяти не хватает. Выход здесь такой - просто увеличить объем стека (сократить количество глобальных переменных, за счет замены их локальными переменными).


нет, локальные распологаются не в области стека, проверял, проблема то возникает из-за небольшой рекурсии, но если push/pop заменить на st/ld, как было в iar, то все работает, но на iar вернуться нельзя, в том то и проблема, если кто знает директивы компилятору, чтоб push/pop заменить на st/ld то они мне впринципе и нужны, памяти используется 96%, но опятьже из-за небольшой рекурсии есть залезание в стек локальными переменными, к сожаленю логику программы переделывать мне месяц не дадут, сократить объем памяти тоже нет возможности:(
Непомнящий Евгений
Цитата(Kibi @ May 20 2008, 14:29) *
нет, локальные распологаются не в области стека, проверял

А где по вашему они располагаются???
777777
Цитата(Kibi @ May 20 2008, 14:29) *
нет, локальные распологаются не в области стека, проверял, проблема то возникает из-за небольшой рекурсии, но если push/pop заменить на st/ld, как было в iar, то все работает

Не понимаю как такое может быть. Если есть рекурсия, то локальные переменные обязательно должны быть в стеке, иначе у тебя будет один комплект переменных на все вызовы. Либо - ты рекурсией называешь что-то не то.
Qwertty
Цитата(Непомнящий Евгений @ May 20 2008, 14:47) *
А где по вашему они располагаются???

Обычно в регистрах. Если их не очень много.
А вот предыдущее содержимое регистров идет в стек.
Kibi
Цитата(Непомнящий Евгений @ May 20 2008, 14:47) *
А где по вашему они располагаются???


если считать что стек распологается в sram и локальные и глобальные тамже, то да, спорить не буду, вопрос как ограничить компилятору залезание в область стека, iar это делает, может я тупой, да я привык работать на асме, и там таких проблем нет, ладно вопрос остается открытым, полезу заново перечитывать документацию по компилятору, мож если более внимательнее перечитаю то найду решение, просьба не флудить в теме, если есть решение как заменить push/pop на st/ld при компиляции, то прошу поделиться опытом.
aesok
Цитата(Kibi @ May 20 2008, 14:59) *
просьба не флудить в теме, если есть решение как заменить push/pop на st/ld при компиляции, то прошу поделиться опытом.


Если не флудить - то никак нельзя.

А если немного пофлудить, то:
С каким уровнем оптимизации Вы компилируете проэкт?
В какой памяти Вы распологаете строковые переменные и/или таблицы констант?

Анатолий.
VladimirYU
Все дело IMHO в разных способах организации стека. В ИАР он рганизован программно без использования регистра указателя стека, поэтому там St/Ld, а у вас фактически аппаратно с использованием регистра указателя стека, такова реализация компилятора. Боюсь, что никак эту особенность вам не обойти.
Qwertty
Цитата(Kibi @ May 20 2008, 14:59) *
если есть решение как заменить push/pop на st/ld при компиляции, то прошу поделиться опытом.

Решение привел выше singlskv.
А в начале обработчика ассемблерной вставкой сохраняйте регистры куда угодно. Только чем это поможет непонятно.
И еще непонятно, как связаны обработчик прерывания и рекурсия. Вы в обработчике используете рекурсивную функцию? Или речь про вложенные прерывания?

Цитата(aesok @ May 20 2008, 15:04) *
В какой памяти Вы распологаете строковые переменные

А что, есть варианты? 07.gif
Kibi
Цитата(VladimirYU @ May 20 2008, 15:25) *
Все дело IMHO в разных способах организации стека. В ИАР он рганизован программно без использования регистра указателя стека, поэтому там St/Ld, а у вас фактически аппаратно с использованием регистра указателя стека, такова реализация компилятора. Боюсь, что никак эту особенность вам не обойти.


думаю что да, но вопрос остается открытым, как сказать компилятору не ставить push/pop
VladimirYU
Цитата(Qwertty @ May 20 2008, 15:33) *
Решение привел выше singlskv.
А в начале обработчика ассемблерной вставкой сохраняйте регистры куда угодно. Только чем это поможет непонятно.

Реализуемый, но жостаточно рискованный способ, можно задеть, например, глобальные переменные или static. Данный подход это первый шаг к откату на asm. Искать выход нужно в организации программы в целом.
galjoen
Мне кажется, что первопричина тут в том, что один и тот-же регистр в случае PUSH сохраняется в стеке несколько раз, а в случае ST тоже несколько раз, но на одно и то же место. И вот эту проблемму нужно решать (лишние сохранения регистров). Например не вызывать в прерывании функции и т.п. А замена PUSH на ST это симптоматическое лечение, которое может привести к тяжёлым глюкам.
Непомнящий Евгений
Цитата(VladimirYU @ May 20 2008, 15:47) *
Реализуемый, но жостаточно рискованный способ, можно задеть, например, глобальные переменные или static.

Дык эти переменные будут также отжирать оперативку, единственное - что не на стеке. Чем это поможет? Если есть лишняя оперативка - можно просто размер стека увеличить...
aesok
Цитата(Qwertty @ May 20 2008, 15:33) *
Цитата
В какой памяти Вы распологаете строковые переменные

А что, есть варианты? 07.gif


Неправильно выразился... стороковые константы?

Анатолий.
singlskv
Цитата(Kibi @ May 20 2008, 15:44) *
думаю что да, но вопрос остается открытым, как сказать компилятору не ставить push/pop
Думаю что искать это Вы будете очень долго...
Вам вроде уже сказали что нет такой возможности, хотя повторое чтение мануалов
конечно еще никому не мешало smile.gif

Ну а если хотите конкретной помощи, тады код в студию....
defunct
Цитата(Kibi @ May 20 2008, 13:29) *
нет, локальные распологаются не в области стека, проверял, проблема то возникает из-за небольшой рекурсии, но если push/pop заменить на st/ld, как было в iar, то все работает, но на iar вернуться нельзя, в том то и проблема, если кто знает директивы компилятору, чтоб push/pop заменить на st/ld то они мне впринципе и нужны, памяти используется 96%, но опятьже из-за небольшой рекурсии есть залезание в стек локальными переменными, к сожаленю логику программы переделывать мне месяц не дадут, сократить объем памяти тоже нет возможностиsad.gif

Плохо проверяли.
1. Локальные переменные всегда располагаются в стеке если не помещаются в регистрах.
2. В IAR два стека, стек данных CSTACK, и стек возвратов RSTACK. И в IAR можно вручную задать их объем, т.о. память под стек заданного объема будет жестко резервирована и будет учитываться при подсчете занимаемой памяти.

3. В WinAVR есть один общий стек ничинающийся с RAMEND ничем не ограниченный снизу (память не резервируется и соответственно стек не учитывается при подсчете занятой памяти).

Вы должны сами заботиться о том чтобы стека хватало. Если у вас используется 96% памяти, то значит под стек у вас осталось всего 4%. Умножте количество памяти вашего МК на 0.04 и будет вам число в байтах отведенное под стек в вашей программе. Учтите что для входа в прерывание нужно хотя бы 35 байт RAM + память на вызовы функций + память под локальные переменные. Меньше 256 байт стека, я считаю кощунством.
SasaVitebsk
Совершенно согласен defunct. с Я бы добавил ещё следующее. В IAR сумма стеков примерно будет равна с той же программе (С учётом эффективности компиляторов).

Таким образом нельзя говорить о вариантах реализации стека PUSH/STD, а можно говорить лишь о недостаточности памяти в целом. Либо о вашем непонимании. Вы поймите если переменная должна оказаться в стеке, то не имеет значения каким образом и в какой именно стек она будет положена! Главное, что она займёт место в памяти.

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

Я бы вообще попытался бы отказаться от рекурсии. Например в пользу бинарного перебора либо дерева. Очень неэффективна рекурсия в большенстве своём.
Qwertty
Цитата(SasaVitebsk @ Aug 17 2008, 14:16) *
Если в рекурсивной ф-ции вы объявите локальную переменную, то она будет размещена на стеке, а если вы её объявите static, то будет создан лишь один экземпляр переменной в памяти (Правда надо осмыслить логику работы).

А чего осмысливать - рекурсивная функция должна быть реентерабельной, т.е. никаких static-ов в ней быть не должно.
SasaVitebsk
Цитата(Qwertty @ Aug 17 2008, 22:09) *
А чего осмысливать - рекурсивная функция должна быть реентерабельной, т.е. никаких static-ов в ней быть не должно.

smile.gif Просто пытаюсь осторожно высказываться. Ну если к примеру временная переменная возникает и уничтожается до рекурсивного вызова... smile.gif Ну чисто теоретически...

Но мне кажется что любая рекурсивная ф-ция памяти жрёт как сволочь. Зачем её применять? Особенно в условиях нехватки ресурсов Например памяти.

Возьмём простейший случай - один параметр. Таким образом ф-ция минимум съест 3 байта памяти за каждый вызов. Думаю что на самом деле будет не менее 8-10 с учётом сохранения каких-нибудь регистров. Таким образом при уровне вложенности 150 - получится 1200-1500 байт! Это же немыслимо для контроллера!

Опишите задачу, которую вы пытаетесь рекурсией решать. Мы тут коллегиально попытаемся её в обход пустить. smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.