Работа с GPIO Atmega128a в MicrochipStudio
Начинаю работать с микроконтроллерами Atmega, пробую просто зажечь светодиод и столкнулся со странным поведением. Вот код:
void GPIO_init(void)
{
DDRE |= BIT7; // red LED
DDRD |= BIT6; // yellow LED
//PORTE |= BIT7;
}
int main(void)
{
GPIO_init();
PORTE |= BIT7;
while (1);
}
Светодиод на пине 7 порта Е. Если PORTE |= BIT7 делать в main - светодиод не зажигается, а если в функции GPIO_init() - нормально светится, как и должен. В симуляторе одинаково работает в обоих случаях, а в железе нет. В чём может быть причина?
Вот ассемблерные листинги для случая когда код не работает в железе:
00000046 CLR R1 Clear Register
00000047 OUT 0x3F,R1 Out to I/O location
00000048 SER R28 Set Register
00000049 LDI R29,0x10 Load immediate
0000004A OUT 0x3E,R29 Out to I/O location
0000004B OUT 0x3D,R28 Out to I/O location
0000004C RCALL PC+0x0014 Relative call subroutine
0000004D RJMP PC+0x0022 Relative jump
0000004E RJMP PC-0x004E Relative jump
0000004F PUSH R28 Push register on stack
00000050 PUSH R29 Push register on stack
00000051 IN R28,0x3D In from I/O location
00000052 IN R29,0x3E In from I/O location
DDRE |= 0x80; // red LED
00000053 LDI R24,0x22 Load immediate
00000054 LDI R25,0x00 Load immediate
00000055 LDI R18,0x22 Load immediate
00000056 LDI R19,0x00 Load immediate
00000057 MOVW R30,R18 Copy register pair
00000058 LDD R18,Z+0 Load indirect with displacement
00000059 ORI R18,0x80 Logical OR with immediate
0000005A MOVW R30,R24 Copy register pair
0000005B STD Z+0,R18 Store indirect with displacement
0000005C NOP No operation
0000005D POP R29 Pop register from stack
0000005E POP R28 Pop register from stack
0000005F RET Subroutine return
00000060 PUSH R28 Push register on stack
00000061 PUSH R29 Push register on stack
00000062 IN R28,0x3D In from I/O location
00000063 IN R29,0x3E In from I/O location
GPIO_init();
00000064 RCALL PC-0x0015 Relative call subroutine
PORTE |= 0x80;
00000065 LDI R24,0x23 Load immediate
00000066 LDI R25,0x00 Load immediate
00000067 LDI R18,0x23 Load immediate
00000068 LDI R19,0x00 Load immediate
00000069 MOVW R30,R18 Copy register pair
0000006A LDD R18,Z+0 Load indirect with displacement
0000006B ORI R18,0x80 Logical OR with immediate
0000006C MOVW R30,R24 Copy register pair
0000006D STD Z+0,R18 Store indirect with displacement
while (1);
0000006E RJMP PC-0x0000 Relative jump
А вот когда работает:
00000046 CLR R1 Clear Register
00000047 OUT 0x3F,R1 Out to I/O location
00000048 SER R28 Set Register
00000049 LDI R29,0x10 Load immediate
0000004A OUT 0x3E,R29 Out to I/O location
0000004B OUT 0x3D,R28 Out to I/O location
0000004C RCALL PC+0x001D Relative call subroutine
0000004D RJMP PC+0x0022 Relative jump
0000004E RJMP PC-0x004E Relative jump
0000004F PUSH R28 Push register on stack
00000050 PUSH R29 Push register on stack
00000051 IN R28,0x3D In from I/O location
00000052 IN R29,0x3E In from I/O location
DDRE |= 0x80; // red LED
00000053 LDI R24,0x22 Load immediate
00000054 LDI R25,0x00 Load immediate
00000055 LDI R18,0x22 Load immediate
00000056 LDI R19,0x00 Load immediate
00000057 MOVW R30,R18 Copy register pair
00000058 LDD R18,Z+0 Load indirect with displacement
00000059 ORI R18,0x80 Logical OR with immediate
0000005A MOVW R30,R24 Copy register pair
0000005B STD Z+0,R18 Store indirect with displacement
PORTE |= 0x80;
0000005C LDI R24,0x23 Load immediate
0000005D LDI R25,0x00 Load immediate
0000005E LDI R18,0x23 Load immediate
0000005F LDI R19,0x00 Load immediate
00000060 MOVW R30,R18 Copy register pair
00000061 LDD R18,Z+0 Load indirect with displacement
00000062 ORI R18,0x80 Logical OR with immediate
00000063 MOVW R30,R24 Copy register pair
00000064 STD Z+0,R18 Store indirect with displacement
00000065 NOP No operation
00000066 POP R29 Pop register from stack
00000067 POP R28 Pop register from stack
00000068 RET Subroutine return
00000069 PUSH R28 Push register on stack
0000006A PUSH R29 Push register on stack
0000006B IN R28,0x3D In from I/O location
0000006C IN R29,0x3E In from I/O location
GPIO_init();
0000006D RCALL PC-0x001E Relative call subroutine
while (1);
0000006E RJMP PC-0x0000 Relative jump
Ответы (1 шт):
Проблема была аппаратная: перепаял микроконтроллер и всё заработало как надо
UPD: Замена чипа не помогла, просто забыл выключить оптимизацию, а с оптимизацией компилятор инлайнил функцию. А проблема возникала именно при возврате из функции. Так что новый чип вёл себя точно так же. В итоге я подпаялся JTAGом, посмотрел как меняются регистры. Оказалось, что по умолчанию указатель на стек указывает на пределы оперативной памяти, процессор не мог сохранить туда адрес возврата, а потому каждый раз из функции возвращался в участок памяти, где ничего нет. В настройках проекта есть пункт "начальный адрес стека". Я вписал туда адрес конца оперативной памяти (минус 2 байта), скомпилировал проект - и всё заработало