Bagaimana cara tumpukan panggilan beroperasi selama interupsi pada AVR?

8

(Khusus untuk Uno Arduino ...)

Apa yang terjadi pada stack ketika interupsi terjadi pada mikrokontroler AVR dan saya memanggil suatu fungsi? Apakah kompiler memasukkan kode? Apakah itu menumpuk tumpukan di suatu tempat dan kemudian mengatur ulang penunjuk tumpukan? Apakah ada tumpukan sekunder hanya untuk interupsi?

Seperti yang saya mengerti, vektor untuk interupsi adalah perintah GOTO langsung dalam perakitan. Juga, saya tidak berpikir bahwa mikrokontroler akan secara otomatis mengacaukan tumpukan, jadi mungkin dibiarkan sendiri. Namun, itu masih belum menjelaskan bagaimana fungsi bekerja selama ISR.

Penguin Anonim
sumber
Jawaban di bawah ini luar biasa, harap dicatat bahwa kompiler tidak dapat inline panggilan interupsi karena ... Mereka panggilan interupsi: D
Vladimir Cravero
1
@VladimirCravero yang saya maksudkan adalah sebaris fungsi yang dipanggil dalam interrupt (jika saya panggil foo () di ISR ​​apakah inline itu jadi itu sebenarnya bukan panggilan fungsi?)
Anonymous Penguin
Jadi jawaban di bawah ini tidak menjawab pertanyaan Anda, atau bukan? manusia gua menjelaskan apa yang terjadi ketika interupsi terjadi, tetapi tidak apa yang terjadi ketika suatu fungsi dipanggil dalam konteks yang terganggu. jawaban untuk yang terakhir adalah: tidak ada yang istimewa, fungsi dipanggil dan hanya itu. keajaiban terjadi ketika interupsi dipicu, apa yang terjadi setelah (sebelum iret) hanya kode normal, biasanya tidak terputus.
Vladimir Cravero
@VladimirCravero ya ya (secara tidak langsung). Saya sedang berbicara tentang bagaimana stack dimodifikasi untuk ISR, berpikir bahwa itu harus dimodifikasi untuk menggunakan fungsi. Saya akan menebak bahwa fungsi bekerja dengan cara yang persis sama setelah ISR diatur.
Penguin Anonim
yah, kamu mengerti kemudian. setelah lompat ke vektor interupsi semuanya baik-baik saja dan Anda dapat pergi ke mana pun Anda inginkan.
Vladimir Cravero

Jawaban:

16

AVR adalah arsitektur RISC, sehingga memiliki penanganan hardware yang cukup mendasar dari interupsi. Sebagian besar prosesor mengacaukan tumpukan selama interupsi, meskipun ada beberapa, terutama ARM dan PowerPC, yang menggunakan metode berbeda.

Bagaimanapun, inilah yang AVR lakukan untuk interupsi:

Ketika interupsi terjadi, perangkat keras prosesor melakukan langkah-langkah ini, yang bukan hanya GOTO sederhana:

  1. Selesaikan instruksi saat ini.
  2. Nonaktifkan bendera interupsi global.
  3. Dorong alamat instruksi berikutnya pada tumpukan.
  4. Salin alamat dalam vektor interupsi yang benar (sesuai dengan interupsi yang terjadi) ke penghitung program.

Sekarang pada titik ini, perangkat keras telah melakukan semua yang harus dilakukan. Perangkat lunak harus ditulis dengan benar untuk tidak merusak barang-barang. Biasanya, langkah selanjutnya adalah di sepanjang garis ini.

  1. Dorong register status ke tumpukan. (Ini harus dilakukan terlebih dahulu sebelum diubah).

  2. Dorong register CPU apa pun yang akan (atau mungkin) diubah ke tumpukan. Register mana yang perlu disimpan dengan cara ini ditentukan oleh model pemrograman. Model pemrograman didefinisikan oleh kompiler.

Sekarang kode interupsi yang berfungsi dapat dijalankan. Untuk menjawab kasus dalam pertanyaan memanggil fungsi, ia hanya melakukan apa yang selalu dilakukannya, mendorong nilai kembali pada tumpukan, lalu mengembalikannya setelah selesai. Ini tidak memengaruhi semua nilai sebelumnya yang kami simpan di tumpukan hingga sekarang.

  1. Jalankan kode kerja ISR.

Sekarang kita sudah selesai dan ingin kembali dari interupsi. Pertama-tama kita harus melakukan pembersihan perangkat lunak.

  1. Pop register CPU yang kami dorong di langkah 6.
  2. Pop nilai status yang disimpan kembali ke register status. Setelah ini, kita harus berhati-hati untuk tidak menjalankan instruksi yang dapat mengubah register status.
  3. Jalankan instruksi RTI. Perangkat keras melakukan langkah-langkah ini untuk instruksi ini:

    Sebuah. Aktifkan bendera interupsi global. (Perhatikan bahwa setidaknya satu instruksi harus dijalankan sebelum interupsi berikutnya dihormati. Ini mencegah interupsi berat dari sepenuhnya memblokir pekerjaan latar belakang.)

    b. Pop alamat kembali yang disimpan ke dalam PC.

Sekarang kita kembali ke kode normal.

Perhatikan bahwa ada beberapa poin di mana kita harus sangat berhati-hati, terutama di sekitar register status dan register simpanan yang bisa diubah. Untungnya jika Anda menggunakan kompiler C, semua ini ditangani di bawah selimut.

Anda juga harus memperhatikan kedalaman tumpukan Anda. Kapan saja interupsi diaktifkan, ISR dapat menggunakan lebih banyak stack daripada yang terlihat jelas dengan melihat kode lokal. Tentu saja, ini benar-benar tidak muncul banyak kecuali Anda mendorong ingatan Anda hingga batasnya.

Berikut ini tautan yang menjelaskan proses ini jika Anda menginginkan referensi.

manusia gua
sumber
Apa tujuan dari langkah 5/6? Rasanya konyol bagi saya untuk tidak secara langsung memodifikasi register, walaupun saya kira mengacaukan beberapa register selama interupsi dapat menciptakan beberapa hasil yang buruk.
Penguin Anonim
1
Langkah 5 dan 6 menyimpan status sistem (sebelum interupsi) saat ini, sehingga dapat dipulihkan (langkah 8 dan 9) setelah interupsi selesai, untuk memungkinkan program utama untuk melanjutkan seolah-olah tidak terganggu.
Peter Bennett
1
Ini adalah ringkasan yang bagus.
Connor Wolf
3
Perlu juga dicatat, bahwa jika Anda benar- benar tahu apa yang Anda lakukan, Anda dapat menonaktifkan penyimpanan otomatis dari status dan register lainnya, dengan bendera GCC ( ISR_NAKED). Ini bisa membuat Anda melewatkan langkah 5,6,8,9, dalam konteks di mana Anda benar - benar membutuhkan siklus itu. Kelemahannya adalah Anda harus benar - benar yakin Anda akan mempertahankan register yang relevan, atau dapat menimpa mereka tanpa membahayakan.
Connor Wolf
2
Itu menarik untuk diketahui, tetapi saya akan melakukan pemrograman perakitan sebelum menggunakan bendera itu. Sangat berbahaya ...
manusia gua