Это вопрос, который мой папа всегда задавал мне. « Почему он не проходит через все инструкции и не останавливается в конце? »
Давайте посмотрим на патологический пример. Следующий код был скомпилирован в компиляторе C18 Microchip для PIC18:
void main(void)
{
}
Он производит следующий вывод ассемблера:
addr opco instruction
---- ---- -----------
0000 EF63 GOTO 0xc6
0002 F000 NOP
0004 0012 RETURN 0
.
. some instructions removed for brevity
.
00C6 EE15 LFSR 0x1, 0x500
00C8 F000 NOP
00CA EE25 LFSR 0x2, 0x500
00CC F000 NOP
.
. some instructions removed for brevity
.
00D6 EC72 CALL 0xe4, 0 // Call the initialisation code
00D8 F000 NOP //
00DA EC71 CALL 0xe2, 0 // Here we call main()
00DC F000 NOP //
00DE D7FB BRA 0xd6 // Jump back to address 00D6
.
. some instructions removed for brevity
.
00E2 0012 RETURN 0 // This is main()
00E4 0012 RETURN 0 // This is the initialisation code
Как вы можете видеть, main () вызывается и в конце содержит оператор return, хотя мы сами его явно не помещали туда. Когда main возвращается, CPU выполняет следующую инструкцию, которая является просто GOTO, чтобы вернуться к началу кода. main () просто вызывается снова и снова.
Сказав это, люди обычно так не поступают. Я никогда не писал ни одного встроенного кода, который позволял бы main () завершать работу таким образом. В основном мой код будет выглядеть примерно так:
void main(void)
{
while(1)
{
wait_timer();
do_some_task();
}
}
Поэтому я бы никогда не позволил main () выйти.
«Хорошо, хорошо», - говорите вы. Все это очень интересно, что компилятор гарантирует, что никогда не будет последнего оператора return. Но что произойдет, если мы заставим проблему? Что, если я вручную закодирую свой ассемблер и не вернусь к началу?
Ну, очевидно, процессор просто продолжит выполнять следующие инструкции. Это будет выглядеть примерно так:
addr opco instruction
---- ---- -----------
00E6 FFFF NOP
00E8 FFFF NOP
00EA FFFF NOP
00EB FFFF NOP
.
. some instructions removed for brevity
.
7EE8 FFFF NOP
7FFA FFFF NOP
7FFC FFFF NOP
7FFE FFFF NOP
Следующий адрес памяти после последней инструкции в main () пуст. На микроконтроллере с флэш-памятью пустая инструкция содержит значение 0xFFFF. По крайней мере, на PIC этот код операции интерпретируется как 'nop' или 'no operation'. Это просто ничего не делает. Процессор продолжит выполнение этих nops до конца памяти.
Что после этого?
В последней инструкции указатель команды процессора равен 0x7FFe. Когда ЦП добавляет 2 к своему указателю инструкций, он получает 0x8000, что считается переполнением PIC только с 32k FLASH, и поэтому он возвращается обратно к 0x0000, и ЦП с радостью продолжает выполнять инструкции в начале кода так же, как если бы он был сброшен.
Вы также спросили о необходимости выключения. По сути, вы можете делать все, что захотите, и это зависит от вашего приложения.
Если у вас есть приложение, которое должно было выполнить только одно действие после включения, а затем ничего не делать, вы можете просто добавить время (1); в конце main (), так что процессор перестает делать что-либо заметное.
Если приложению требуется отключение ЦП, то, в зависимости от ЦП, возможно, будут доступны различные спящие режимы. Тем не менее, процессоры имеют привычку снова просыпаться, поэтому вам нужно убедиться, что для сна не было ограничений по времени, таймера сторожевого пса и т. Д.
Вы могли бы даже организовать некоторые внешние схемы, которые позволили бы процессору полностью отключить свою собственную мощность, когда он закончил. См. Этот вопрос: Использование кратковременной кнопки в качестве защелкивающегося выключателя .