Возможная причина - переполнение памяти, неверная инициализация стека.
Стек инициализируется в самом начале программы, для этого компилятор avr-gcc компилирует обычно такой код (можно посмотреть во время отладки, если выбрать в меню View -> Disassembler и перейти в самое начало листинга). Например, для микроконтроллера ATmega16:
+00000000: 940C002A JMP 0x0000002A прыжок на начало программы
..
+0000002A: 2411 CLR R1 R1 == 0
+0000002B: BE1F OUT 0x3F,R1 очистка SREG
+0000002C: E5CF LDI R28,0x5F загрузка адреса 0x045F
+0000002D: E0D4 LDI R29,0x04 загрузка адреса 0x045F
+0000002E: BFDE OUT 0x3E,R29 загрузка стека адресом 0x045F
+0000002F: BFCD OUT 0x3D,R28 загрузка стека адресом 0x045F
..
В этом примере в стек загружается значение 0x045F (адрес, равный макросу RAMEND из хедера, определяющего ресурсы процессора).
Напомню, что стек у AVR должен начинаться от максимального адреса RAM, и по мере заполнения стека его граница смещается к младшим адресам (стек растет вверх, адрес в указателе стека уменьшается). Предельное минимальное значение указателя стека для микроконтроллера ATmega16 - 0x60, поскольку дальше начинается область SFR (Special Function Registers, регистры специального назначения).
В системе WinAVR адрес начала стека присваивается символу __stack.
Если в Вашей системе символ __stack не задан, то возможна неправильная установка стека. Символ __stack можно задать вручную и передать линкеру через командную строку компилятора, например так (в этом примере устанавливается стек для ATmega16, у которого размер RAM равен 1024 байт):
## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS += -Wl,-Map=$(PROJECT).map -Wl,--cref -Wl,--defsym=__stack=0x045F
Адрес начала стека можно посмотреть с помощью программы avr-nm.exe (входит в пакет WinAVR вместе с компилятором avr-gcc). Например, для выходного файла формата ELF это можно сделать так (кроме адреса, будет также выведен тип и размер символов, в списке нужно искать символ __stack):
avr-nm -S rs422.elf
..
0000268c 000001aa T __pack_f
00002f7e T __prologue_saves__
0000045f W __stack
00002fee t __stop_program
00001f02 00000062 T __subsf3
00800075 00000008 D __thenan_sf
00000000 a __tmp_reg__
..
Можно также использовать утилиту avr-objdump.exe (также входит в пакет WinAVR):
c:\asm\rs422\default>avr-objdump -x rs422.elf | grep __stack
0000045f w *ABS* 00000000 __stack
Общую статистику по использованию памяти может показать утилита avr-size.exe (также входит в пакет WinAVR), например:
c:\asm\rs422\default>avr-size rs422.elf
text data bss dec hex filename
12272 286 591 13149 335d rs422.elf
Или из Makefile:
@avr-size -C --mcu=${MCU} ${TARGET}
avr-objdump -h -S rs422.elf > rs422.lss
AVR Memory Usage
----------------
Device: atmega16
Program: 12558 bytes (76.6% Full)
(.text + .data + .bootloader)
Data: 877 bytes (85.6% Full)
(.data + .bss + .noinit)
Build succeeded with 1 Warnings...
|