Cortex M3 mendukung pasangan operasi operasi yang berguna (umum di banyak mesin lain juga) yang disebut "Load-Exclusive" (LDREX) dan "Store-Exclusive" (STREX). Secara konseptual, operasi LDREX melakukan beban, juga menetapkan beberapa perangkat keras khusus untuk mengamati apakah lokasi yang dimuat mungkin ditulis oleh sesuatu yang lain. Melakukan STREX ke alamat yang digunakan oleh LDREX terakhir akan menyebabkan alamat itu ditulis hanya jika tidak ada yang menulisnya terlebih dahulu . Instruksi STREX akan memuat register dengan 0 jika toko berlangsung, atau 1 jika dibatalkan.
Perhatikan bahwa STREX sering pesimistis. Ada berbagai situasi di mana mungkin memutuskan untuk tidak melakukan toko bahkan jika lokasi yang dimaksud sebenarnya belum tersentuh. Misalnya, interupsi antara LDREX dan STREX akan menyebabkan STREX menganggap lokasi yang sedang ditonton mungkin terkena. Untuk alasan ini, biasanya ide yang baik untuk meminimalkan jumlah kode antara LDREX dan STREX. Misalnya, pertimbangkan sesuatu seperti berikut:
inline void safe_increment (uint32_t * addr)
{
uint32_t new_value;
melakukan
{
new_value = __ldrex (addr) + 1;
} while (__ strex (new_value, addr));
}
yang mengkompilasi ke sesuatu seperti:
; Asumsikan R0 menyimpan alamat yang dimaksud; r1 dibuang
lp:
ldrex r1, [r0]
tambahkan r1, r1, # 1
strex r1, r1, [r0]
cmp r1, # 0; Tes jika tidak nol
bp l
.. kode berlanjut
Sebagian besar waktu kode dijalankan, tidak ada yang akan terjadi antara LDREX dan STREX untuk "mengganggu" mereka, sehingga STREX akan berhasil tanpa basa-basi lagi. Namun, jika interupsi terjadi segera mengikuti instruksi LDREX atau ADD, STREX tidak akan melakukan store, tetapi kode akan kembali untuk membaca nilai (mungkin diperbarui) dari [r0] dan menghitung nilai tambahan baru. berdasarkan itu.
Menggunakan LDREX / STREX untuk membentuk operasi seperti safe_increment memungkinkan untuk tidak hanya mengelola bagian kritis, tetapi juga dalam banyak kasus untuk menghindari kebutuhan mereka.
while(STREXW(new_value, addr);
Bagaimana kami dapat meyakini apa yang Anda katakan benar jika kode Anda bahkan tidak dapat dikompilasi?Sepertinya Anda memerlukan beberapa buffer bundar atau FIFO di perangkat lunak MCU Anda. Dengan melacak dua indeks atau petunjuk ke dalam array untuk membaca dan menulis, Anda dapat memiliki latar depan dan latar belakang mengakses buffer yang sama tanpa gangguan.
Kode latar depan bebas untuk menulis ke buffer lingkaran kapan saja. Ini memasukkan data pada pointer tulis, kemudian menambahkan pointer tulis.
Kode latar belakang (penanganan interupsi) mengkonsumsi data dari pointer baca dan menambah pointer baca.
Ketika pointer baca dan tulis sama, buffer kosong dan proses latar belakang tidak mengirim data. Ketika buffer penuh, proses latar depan menolak untuk menulis lagi (atau dapat menimpa data lama, tergantung pada kebutuhan Anda).
Menggunakan buffer bundar untuk memisahkan pembaca dan penulis harus menghilangkan kebutuhan untuk menonaktifkan interupsi.
sumber
Saya tidak ingat lokasi tepatnya tetapi di perpustakaan yang berasal dari ARM (Bukan TI, ARM, itu harus di bawah CMSIS atau sesuatu seperti itu, saya menggunakan ST tapi saya ingat membaca di suatu tempat bahwa file ini berasal dari ARM sehingga Anda harus memilikinya juga ) ada opsi menonaktifkan interupsi global. Ini adalah panggilan fungsi. (Saya tidak di tempat kerja tapi besok saya akan mencari fungsi yang tepat). Saya akan membungkusnya dengan nama yang bagus di sistem Anda dan menonaktifkan interupsi, lakukan hal Anda dan aktifkan lagi. Karena itu, opsi yang lebih baik akan menerapkan semaphore atau struktur antrian daripada global interrupt disable.
sumber