Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по WinAVR
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Freeze Anti
Собственно, сабж... У меня в программе используется достаточно много вложенных if, из которых еще и вызываются функции, плюс еще прерывания используются... Короче, есть предположение, что стека не хватает... Хочу попробовать увеличить, но что-то не нашел в манах, как это сделать...
ReAl
Цитата(Freeze Anti @ Sep 17 2008, 08:57) *
Хочу попробовать увеличить, но что-то не нашел в манах, как это сделать...
В avr-gcc стек один (в отличие от IAR) и указатель стека всегда настраивается на верхушку памяти, тогда как место под неавтоматические переменные выделяется снизу.
Таким образом, размер стека автоматически устанавливается на максимально возможный.
Убедитесь, что оптимизация включена, просмотрите код, может где-то забыт массив, который уже не нужен.
Старайтесь не вызывать функции из обработчиков прерываний (за исключением inline-функций), так как это увеличивает расход стека. Если есть вложенные прерывания - попробуйте обойтись без них.
Не используйте оптимизацию -O3, при этом в коде инлайнится всё, до чего компилятор может дотянуться и это тоже может привести к росту использования стека (ненужные inline проскакивают и при -Os - для static-функций, на то есть __attribute__((__noinline__)) )
777777
Цитата(Freeze Anti @ Sep 17 2008, 09:57) *
Собственно, сабж... У меня в программе используется достаточно много вложенных if, из которых еще и вызываются функции, плюс еще прерывания используются... Короче, есть предположение, что стека не хватает... Хочу попробовать увеличить, но что-то не нашел в манах, как это сделать...

Вложенные if-ы не влияют на увеличение стека. Увеличить его не получится, так как от и так устанавливается на максимум. А вообще, если программа не работает, надо искать причину целенаправленно, а не выдумывать причины самому.

Цитата(ReAl @ Sep 17 2008, 10:13) *
Старайтесь не вызывать функции из обработчиков прерываний (за исключением inline-функций), так как это увеличивает расход стека.

Насколько я знаю, в avr-gcc этого нельзя делать потому, что подпрограмма обработки прерываний сохраняет только те регистры, которые использует сама, а какие регистры использует вызванная функция - она не знает и потому не сохраняет.
ReAl
Цитата(777777 @ Sep 17 2008, 09:20) *
Насколько я знаю, в avr-gcc этого нельзя делать потому, что подпрограмма обработки прерываний сохраняет только те регистры, которые использует сама, а какие регистры использует вызванная функция - она не знает и потому не сохраняет.

Она не знает - поэтому сохраняет все, которые не сохранит вызываемая функция (т.е. все, кроме calee-saved). Это и приводит к перерасходу стека:

Код
extern void foo(void);

ISR(INT1_vect)
{
    foo();
}



Код
.global    __vector_2
    .type    __vector_2, @function
__vector_2:
/* prologue: frame size=0 */
    push __zero_reg__
    push __tmp_reg__
    in __tmp_reg__,__SREG__
    push __tmp_reg__
    clr __zero_reg__
     ; а вот регистры с R2 по R17 вызываемая функция обязана по соглашению сохранять сама
    push r18
    push r19
    push r20
    push r21
    push r22
    push r23
    push r24
    push r25
    push r26
    push r27
    push r30
    push r31
/* prologue end (size=17) */
    rcall foo
/* epilogue: frame size=0 */
    pop r31
    pop r30
    pop r27
    pop r26
    pop r25
    pop r24
    pop r23
    pop r22
    pop r21
    pop r20
    pop r19
    pop r18
    pop __tmp_reg__
    out __SREG__,__tmp_reg__
    pop __tmp_reg__
    pop __zero_reg__
    reti

Теперь даже если foo() и использует-то только r25:r24, но сохраняется целая толпа и расход стека растёт.

p.s. возможно, в какой-то из версий баг был в этом месте, но меня обошло.
Kuzmi4
По теме - на сколько я помню изменить значение стэка в WinAVR можно так:
Код
__stack=0x123

Теперь стэк начинается с 0x123.
Это надо писать по моему в make-файле, поправте если не прав.
По умолчанию __stack равен RAMEND.
ReAl
Цитата(Kuzmi4 @ Sep 17 2008, 12:06) *
По теме - на сколько я помню изменить значение стэка в WinAVR можно так:
Код
__stack=0x123
По умолчанию __stack равен RAMEND.
Таким образом стек можно только уменьшить.
Ну разве что поцеплено внешнее ОЗУ и таким образом направить стек туда, но тогда уж лучше туда вытолкать глобальные массивы типа коммуникационных буферов, а стек оставить в более быстрой внутренней памяти.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.