Instruksi AVR SEI

13

Instruksi AVR SEI ( http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_SEI.html ) menunggu instruksi berikutnya selesai sebelum mengaktifkan interupsi.

Jika saya menggunakan instruksi lain untuk mengatur flag I di SREG, apakah ini juga akan menunggu 1 instruksi?

Dengan kata lain: Apakah tunggu fitur instruksi SEI atau register status?

Jika ini adalah fitur dari instruksi SEI, maka pada titik apakah flag benar-benar ditetapkan, dalam siklus yang mengeksekusi SEI atau dengan instruksi selanjutnya?

jayjay
sumber
Ini adalah pertanyaan yang bagus, tetapi seharusnya tidak terlalu sulit untuk diuji dan dipastikan.
Vorac
1
@Vorac Bisakah Anda memberi saya contoh bagaimana ini bisa diuji? Itu akan menjadi jawaban yang saya terima pasti.
jayjay
1
Ini mungkin fitur dari implementasi arsitektur AVR, dan di mana interupsi dapat ditangani. IIRC, arsitektur AVR menggunakan pipa 3-tahap. Jadi instruksi selanjutnya mungkin sudah 'dalam penerbangan' (yaitu dalam pipeline tahap satu, atau lebih jauh) sebelum perubahan flag I dapat digunakan untuk memeriksa interupsi. Saya sudah lama tidak mencari, tapi saya pikir para desainer arsitektur AVR tidak akan terlalu membatasi diri. Jadi, menguji interupsi untuk instruksi pada tahap 1 dari pipa, dan tidak sebelum instruksi berikutnya (pada tahap 2) memberi mereka beberapa fleksibilitas.
gbulmer

Jawaban:

8

Hasil empiris!

Sementara jawaban lainnya bijaksana dan beralasan, semuanya tidak lengkap atau hanya dugaan. Jika dokumentasinya ambigu, kita harus bereksperimen dan kita harus menguji setiap kasus.

Pertanyaan ini layak mendapatkan jawaban konklusif, jadi mari kita tarik AVR dan mulai mengatur beberapa bit!

Prosedur

Untuk menguji, saya membuat program Arduino (ATMEGA328P) kecil yang akan ...

  1. menyiapkan ISR yang tidak akan pernah kembali (while (1) )
  2. menetapkan ISR ke sumber yang dapat saya picu dalam perangkat lunak (INT0 semakin rendah)
  3. interupsi yang dinonaktifkan
  4. diaktifkan dan memicu interupsi sehingga akan tertunda

Saya menggunakan test bed yang akan menyalakan LED dalam instruksi tunggal setelah interupsi diaktifkan. Dengan mencoba berbagai cara untuk mengaktifkan interupsi di test bed dan memeriksa LED, saya dapat mengetahui apakah instruksi setelah instruksi yang diaktifkan dijalankan atau tidak.

Jika LED tidak menyala, maka saya tahu bahwa ISR dieksekusi (dan dikunci) segera setelah interupsi diaktifkan.

Jika LED menyala, maka saya tahu bahwa instruksi selanjutnya diizinkan untuk dieksekusi sebelum ISR dipanggil.

Hasil

SEI instruksi (kasus dasar)

Kode:

sei

Hasil: LED menyala. Instruksi berikut dijalankan.

OUT petunjuk

Kode:

in  r16,0x3f   // Get SREG
ori r16,128    // Set I bit 
out 0x3f,r16   // Save back to SREG

Hasil:

Memimpin. Instruksi berikut dijalankan.

ST petunjuk

Kode:

   clr r29        // Clear Y high byte
   ldi r28,0x5f   // Set Y low byte to point to SREG
   ld r16, Y      // Get SREG
   ori r16,128    // Set I bit 
   st Y,r16       // Put SREG

Hasil:

Memimpin. Instruksi berikut dijalankan.

Kesimpulan!

T: Apakah tunggu fitur instruksi SEI atau register status?

A: Tampaknya mengubah Ibit dalam SREGadalah dari 0a1 akan memungkinkan instruksi berikut untuk dieksekusi berikutnya bahkan jika ada interupsi yang tertunda, terlepas dari instruksi apa yang digunakan untuk mengatur bit.

Catatan

Ini sebenarnya berubah menjadi pertanyaan yang sangat menarik dengan banyak komplikasi. Jika Anda tertarik dengan perinciannya, lihat ...

http://wp.josh.com/2016/01/05/different-ways-to-set-i-bit-in-avr-sreg-besides-sei/

bigjosh
sumber
2
Ketika spesifikasi tidak jelas, ada masalah dengan "hasil empiris". Hanya karena perangkat keras tertentu yang Anda uji berfungsi dengan cara tertentu, tidak berarti bagian lain akan berfungsi seperti itu. Atmel bebas untuk mengubah implementasi asalkan tidak mengubah spesifikasi. Jadi, "Dimana dokumentasinya ambigu, ..." tetap seperti itu, setelah percobaan dan pengujian, masih ambigu.
gbulmer
@bulb Saya setuju 100%. Dia yang menggunakan fitur tidak berdokumen dalam produksi pasti akan sedih. Masih merupakan pertanyaan empiris yang menarik (dan jawaban), dan mungkin tidak masalah untuk bergantung pada proyek pribadi satu kali.
bigjosh
Ya, Anda melakukan penyelidikan yang menarik.
gbulmer
4

Ini adalah pemahaman saya dari dokumentasi bahwa melakukan seiinstruksi tidak berbeda dari langsung menulis 1 ke bit I SREG. Keuntungan dari instruksi ini adalah Anda tidak perlu memuat nilai terlebih dahulu 1<<Ike register yang berfungsi untuk mengubah SREG, sehingga menghemat waktu.

Untuk menguraikan, gunakan sei:

sei ; One cycle

Mengatur bit menggunakan sbi(hanya akan bekerja jika SREG berada di bawah 32 byte dari register register, tetapi tampaknya pada sebagian besar jika tidak semua tidak.)

sbi SREG,7 ; Two cycles

Menulis untuk saya bit langsung di SREG:

in  r24,SREG ;
ori r24,0x80 ;
out SREG,r24 ; Three cycles

The Ibit harus ditetapkan di sreg segera setelah seiinstruksi (atau sbiatau out) selesai. Namun, setiap interupsi yang tertunda tidak akan ditangani sampai setelah instruksi berikutnya selesai - bit akan ditetapkan, tetapi dibutuhkan siklus tambahan untuk interupsi yang akan diaktifkan. Karena interupsi tidak dapat ditangani di tengah instruksi, dan beberapa instruksi membutuhkan lebih dari satu siklus untuk dieksekusi, mereka menentukan waktu yang diperlukan untuk diaktifkan sebagai satu instruksi. Ini harus menjadi kasus untuk semua versi kode - yaitu masing-masing di atas akan menyebabkan keterlambatan instruksi.


Setelah sedikit mencari, saya menemukan utas ini di forum Arduino di mana beberapa tes berbeda dilakukan untuk memverifikasi perilaku. Tampaknya setuju dengan apa yang saya katakan di atas.

Selanjutnya, menurut utas itu, jika Ibendera sudah diatur, maka tidak ada respons tertunda dari interupsi yang disebabkan oleh seiyang menyiratkan bahwa respons tertunda bukan disebabkan oleh instruksi itu sendiri, melainkan pada perangkat keras internal yang dikendalikan oleh Ibendera - jadi setiap operasi yang mengubah bendera di SREG, baik itu seiatau outatau stsakan memiliki perilaku yang persis sama.

Tom Carpenter
sumber
Jadi tidak ada aspek menunda operasi, khusus untuk SEI tetapi tidak KELUAR, yang memungkinkan instruksi berikut untuk menyelesaikan?
Brian Drummond
Dalam kasus contoh kedua Anda, kapan interupsi yang tertunda ditangani? Apakah ada penundaan siklus seperti yang pertama?
jayjay
@jayjay lihat pembaruan saya.
Tom Carpenter
1
Catatan yang SBItidak dapat digunakan untuk mengatur Ibit SREGsehingga kode apa pun yang melakukan ini kemungkinan tidak benar-benar diuji dalam kehidupan nyata karena bahkan tidak akan berkumpul. SBIhanya dapat beroperasi pada 32 register yang lebih rendah dan SREG ada di slot 63.
bigjosh
@ Bigjosh contoh SBI adalah salah satu yang saya pikirkan kemudian - outadalah yang saya gunakan pada awalnya. Saya pikir saya akan menemukan AVR (mungkin ATTiny) yang memiliki SREG di 32 register yang lebih rendah, tetapi saya mungkin membayangkannya.
Tom Carpenter
1

IMHO apakah menulis ke SREG masih menunda 1 instruksi dapat diuji seperti ini (pseudocode):

ISR() { PORTA = 0; while(1); }
main() 
{
    cli();
    DDRA = 0xff;
    configure_isr_for_level_interrupt_that_will_trigger_immediately();
    SREG = 0xff;
    cli();
    PORTA = 0xff;
    while(1);
}

Sayangnya saya tidak punya waktu untuk melakukannya :(

Vorac
sumber
0

Bukan itu yang dikatakan. Dokumentasi mengatakan

Instruksi SEI berikut akan dieksekusi sebelum interupsi yang tertunda.

bukannya menunggu instruksi selanjutnya. Saya membaca ini karena flag diset segera tetapi meskipun diaktifkan, tidak ada interupsi yang akan ditangani sampai instruksi berikutnya dijalankan.

patthoyts
sumber
Ini semua benar, tetapi pertanyaan saya adalah: Apakah perilaku ini khusus untuk SEI?
jayjay
@ jayjay Saya curiga ini disebabkan oleh panjang pipa instruksi
crasic