Це запитання, яке мій тато завжди задавав мені. " Чому він просто не проходить усі інструкції і не зупиняється в кінці? "
Давайте розглянемо патологічний приклад. Наступний код був складений у компіляторі 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 () викликається, а в кінці містить зворотній вислів, хоча ми його прямо там не вказали. Коли основна віддача, процесор виконує наступну інструкцію, яка просто GOTO, щоб повернутися до початку коду. main () просто викликається знову і знову.
Тепер, сказавши це, це не такий спосіб, як зазвичай люди роблять. Я ніколи не писав жодного вбудованого коду, який би дозволяв main () вийти таким чином. Здебільшого мій код виглядатиме приблизно так:
void main(void)
{
while(1)
{
wait_timer();
do_some_task();
}
}
Тому я ніколи не дозволяв головному () вийти.
"Гаразд добре" ви говорите. Все це дуже цікаво, що компілятор гарантує, що ніколи не буде останнього твердження про повернення. Але що станеться, якщо ми змусимо проблему? Що робити, якщо я зашифрував моєму асемблеру і не став стрибнути назад до початку?
Ну, очевидно, процесор просто продовжував би виконувати наступні інструкції. Вони виглядали б приблизно так:
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 () порожня. На мікроконтролері з пам'яттю FLASH порожня інструкція містить значення 0xFFFF. Принаймні, на PIC цей код коду трактується як "nop", або "no operation". Він просто нічого не робить. Центральний процесор продовжував би виконувати ці носочки до кінця пам'яті.
Що після цього?
В останній інструкції покажчик інструкції процесора становить 0x7FFe. Коли ЦП додає 2 до свого вказівника інструкції, він отримує 0x8000, що вважається переповненням на ПОС із лише 32k FLASH, і тому він обертається назад до 0x0000, і процесор із задоволенням продовжує виконувати інструкції ще на початку коду , так, як ніби він був скинутий.
Ви також запитували про необхідність відключення живлення. В основному ви можете робити все, що завгодно, і це залежить від вашої заявки.
Якщо у вас був додаток, який потребував лише однієї справи після ввімкнення живлення, а потім нічого не робити, ви могли просто покласти час (1); наприкінці main (), щоб процесор перестав робити щось помітне.
Якщо програма вимагала від центрального процесора живлення, тоді, залежно від процесора, ймовірно, будуть доступні різні режими сну. Однак процесори мають звичку прокидатися знову, тому вам доведеться переконатися, що не існує обмеження часу уві сні, а також немає активного таймера для сторожових собак тощо.
Ви навіть можете організувати якусь зовнішню схему, яка дозволила б процесору повністю скоротити власну потужність після її закінчення. Дивіться це запитання: Використання миттєвої кнопки як перемикача тумблера для вимкнення .