• STM8'de iç içe kesmeler işlenirken hata oluştu (errata'da açıklanmadı). Kesinti yönetimi, kesinti vektörleri, yazılım kesintileri, IRQ'lar

    İç içe kesintiler

    Bu mekanizma, QNX Neutrino işletim sisteminde tamamen desteklenir. Önceki senaryolar, yalnızca bir kesintinin meydana geldiği en basit ve en yaygın durumu tanımlamıştır. Ancak, almak maksimum değer maskelenemez kesintilerin yokluğundaki gecikmeler, bir kerede tüm geçerli kesintiler dikkate alınarak zaman olarak kabul edilmelidir, çünkü daha yüksek önceliğe sahip maskelenemez bir kesinti mevcut kesintiyi önleyecektir.

    Şek. Şekil 2-25, İş Parçacığı A'nın çalıştığını gösterir.IRQx kesmesi, IRQy kesmesi ve lnty kesme işleyicisi tarafından önlenen Intx kesme işleyicisini başlatır. Inty kesme işleyicisi, İş Parçacığı B'yi başlatan bir olay döndürür ve Intx kesme işleyicisi, İş Parçacığı C'yi başlatan bir olay döndürür.

    Aramaları yarıda kes

    Kesinti işleme API'si aşağıdaki çekirdek çağrılarını içerir.

    Bu sayede yazılım arayüzü uygun kullanıcı ayrıcalıklarına sahip bir iş parçacığı, kesme gerçekleştiğinde çağrılacak iş parçacığının adres alanındaki donanım kesme numarasını ve işlevin adresini ileterek InterruptAttach() veya Interrupt Attach Event() işlevini çağırabilir. QNX Neutrino, birden çok kesme işleyicisinin (ISR'ler) her bir donanım kesme numarasıyla ilişkilendirilmesine izin verir. Maskelenemeyen kesmeler, zaten çalışan kesme işleyicileri yürütülürken işlenebilir.

    Aşağıdaki bir örnektir program kodu zamanlayıcı donanım kesintisine (işletim sisteminin sistem saati olarak da kullandığı) bir kesme işleyicisinin (ISR) eklendiği. Çekirdekteki zamanlayıcı kesme işleyicisi, kesme kaynaklarını kendisi temizler, böylece yalnızca iş parçacığının veri alanındaki sayacı artırır ve ardından kontrolü çekirdeğe aktarır.

    Sonuç olarak, uygun ayrıcalıklara sahip kullanıcı iş parçacıkları, yürütülürken donanım kesme vektörlerine (bu vektörlerden) kesme işleyicilerini dinamik olarak ekleyebilir (ve ayırabilir). Bu iş parçacıkları, olağan hata ayıklama araçları kullanılarak kaynak düzeyinde hata ayıklanabilir ve kesme işleyicisinin kendisinde, bu işleyici iş parçacığı düzeyinde çağrılarak hata ayıklanabilir ve adım adım yürütme kaynak düzeyinde veya InterruptAttachEvent() işlevini çağırarak.

    Bir donanım kesintisi meydana geldiğinde, işlemci mikro çekirdeğin kesme yeniden yönlendiricisini çağırır. Bu modül, yürütülmekte olan iş parçacığının kayıt bağlamını uygun iş parçacığı tablosu girişindeki yığına iter ve ardından bağlamı, kesme işleyicisinin kesme işleyicisini içeren iş parçacığının koduna ve verilerine erişimi olacak şekilde ayarlar. Böylece, kesme işleyicisi, kesmenin kaynağını belirlemek için kullanıcı iş parçacığındaki arabellekleri ve kodu kullanabilir ve iş parçacığının yapılması gereken daha fazla iş olması durumunda. yüksek seviye, bu kesme işleyicisini içeren iş parçacığı için bir olay oluşturun; bundan sonra bu iş parçacığı, kesme işleyicisinin kendi arabelleğine yerleştirdiği verileri işleyebilir.

    Kesme işleyicisi, içerdiği iş parçacığının içeriğine eşlendiğinden, doğrudan iş parçacığının adres alanına eşlenen cihazlarda çalışabilir veya kendi başına G/Ç yönergelerini yürütebilir. Sonuç olarak, bu, aygıt sürücülerini çekirdeğe bağlama ihtiyacını ortadan kaldırır.

    Mikro çekirdekte bulunan birincil kesme işleme modülü, belirli bir donanım kesmesiyle ilişkili tüm işleyicileri çağırır. Dönen değer, sürece bir olayın iletilmesi gerektiğini gösteriyorsa, çekirdek bu olayı kuyruğa alır. Belirli bir kesme vektörünü işlemek için son kesme işleyicisi çağrıldıktan sonra, çekirdek kesme işleyicisi kesme işleyicisinden çıkar ve "kesmeden geri döner".

    Bu kesme dönüşü, kesintiye uğrayan iş parçacığının bağlamında sonuçlanmak zorunda değildir. Kuyruğa alınan bir olay, daha yüksek öncelikli bir iş parçacığının HAZIR durumuna girmesine neden olduysa, mikro çekirdek, kesmeden o anda etkin olan iş parçacığının bağlamına geri dönecektir.

    Bu, bir kesmenin meydana gelmesi ile kesme işleyicisinin ilk komutunun yürütülmesi arasındaki süreyi (kesme işleme gecikmesi olarak adlandırılır) ve ayrıca kesme işlemi arasındaki süreyi (programlama gecikmesi olarak adlandırılır) ayarlar. son talimat kesme işleyicisi ve iş parçacığının ilk talimatı kesme işleyicisi tarafından hazır duruma getirilir.

    Maksimum kesinti işleme gecikmesi süresi, işletim sisteminin kesintileri yalnızca program kodunun birkaç kritik bölümündeki birkaç talimatın yürütülmesi süresince devre dışı bırakması nedeniyle kesin olarak tanımlanmıştır. Kesintilerin yasak olduğu süreler katı bir şekilde devam eder. kesin zaman ve verilere bağlı değildir.

    Mikro çekirdeğin birincil kesme işleyicisi, kesme işleyicisini çağırmadan önce birkaç talimatı yürütür. Sonuç olarak, işlemler, donanım kesintileri veya çekirdek çağrıları tarafından eşit derecede hızlı ve aynı talimat zinciri aracılığıyla önlenir.

    Çalışması sırasında, kesme işleyicisi tam erişim donanıma (ayrıcalıklı bir iş parçacığının parçası olduğu için), ancak başka çekirdek çağrıları yapamaz. Kesme işleyicisi, bir donanım kesmesine mümkün olduğu kadar hızlı yanıt vermeli, kesmeye hizmet vermek için minimum miktarda iş yapmalı (evrensel eşzamansız alıcı-vericiden (UART) bir bayt okuma vb.) daha fazla iş yap. .

    Belirli bir donanım önceliği için maksimum kesme gecikmesi, doğrudan çekirdek tarafından sunulan kesme gecikmesinden ve verilen kesme işleyicisinden daha yüksek donanım önceliğine sahip her kesme için maksimum kesme işleyici süresinden doğrudan hesaplanabilir. Donanım kesme öncelikleri yeniden atanabileceğinden, sistemdeki en önemli kesmeye en yüksek öncelik verilebilir.

    InterruptAttachEvent() işlevinin çağrılmasının kesme işleyicisini başlatmadığına dikkat edin. Bunun yerine, her kesinti için kullanıcı tanımlı bir olay oluşturulur. Tipik olarak, bu olay, ana işi yapabilmesi için bekleyen bir iş parçacığının programlanmasına neden olur. Kesme, olay oluşturulduktan sonra otomatik olarak maskelenir ve cihaza doğru zamanda hizmet veren iş parçacığı tarafından açıkça maskesinin kaldırılması gerekir.

    Böylece, donanım kesintilerinde gerçekleştirilen işin önceliği, donanım tarafından değil, işletim sisteminin kendisi tarafından kontrol edilebilir. Kesinti kaynağı, mevcut kesintiye hizmet verilinceye kadar yeni bir kesinti oluşturmaz; bu, kesintilerin program kodunun kritik bölümleri üzerindeki etkisini kontrol etmenize ve yüksek hassasiyetli zamanlama kontrolü gerçekleştirmenize olanak tanır.

    Kullanıcı işlemleri ve iş parçacıkları, yalnızca donanım kesintilerini değil, aynı zamanda mikro çekirdek içindeki çeşitli "olayları" da "yakalayabilir". Bu olaylardan herhangi biri gerçekleştiğinde, çekirdek, işlemek için kullanıcı iş parçacığında belirtilen harici işlevi (upcall) çağırabilir. bu olay. Örneğin, boştaki bir iş parçacığı her çağrıldığında, bir kullanıcı iş parçacığı, çekirdeğe özel donanım güç tasarrufu modlarını uygulamak için harici bir arama yapması talimatını verebilir.

    Parametre adı Anlam
    Makale konusu: kesintiler.
    Değerlendirme listesi (tematik kategori) Programlama

    bekçi zamanlayıcıları.

    Çoğu zaman, çevredeki ekipman tarafından üretilen elektriksel gürültü, mikrodenetleyicinin yanlış adres, bundan sonra davranışı tahmin edilemez hale gelir (mikrodenetleyici ʼʼ aşırı hıza geçer ʼʼ). Bu tür durumları izlemek için, genellikle mikrodenetleyiciye bekçi köpeği zamanlayıcıları dahil edilir.

    Bu cihaz, içeriği belirli bir süre içinde (genellikle onlarca milisaniyeden birkaç saniyeye kadar) güncellenmezse mikrodenetleyicinin sıfırlanmasına neden olur. Program sayacının içeriğindeki değişiklik karşılık gelmiyorsa verilen program, ardından watchdog güncelleme komutu yürütülmez. Bu durumda, bekçi uygulaması zamanlayıcısı, mikrodenetleyiciyi başlangıç ​​durumuna ayarlayarak sıfırlar.

    Pek çok geliştirici uygulamalarında bekçi uygulaması zamanlayıcıları kullanmazlar, çünkü örneğin elektrik parazitinin etkileriyle mücadele etmek için bunları kullanmanın kritik önemini görmezler; geri ışın veya araba ateşleme bobinlerinin yakınında. Modern elektronikte, bazen yukarıda listelenenlere benzer durumlarda ortaya çıksa da, elektriksel bozulmaların meydana gelmesi olası değildir.

    Maskeleme için bekçi uygulaması zamanlayıcısının kullanılması önerilmez. yazılım sorunları. Bu zamanlayıcı, yazılım hatası olasılığını azaltabilirken, olası tüm hata nedenlerinin ortadan kaldırılmasını sağlamaz. Yazılım hatalarını önlemek için donanıma güvenmek yerine, daha kapsamlı test yapmak daha iyidir yazılımçeşitli durumlarda.

    Birçok kullanıcı, kesintilerin kendi haline bırakılması en iyi olan bir donanım parçası olduğunu düşünür, çünkü bunların kullanımı, bir kesinti işleyici programı geliştirmek için işlemci hakkında üstün bilgi gerektirir. Aksi takdirde, bir kesinti meydana geldiğinde sistem "uykuya dalar" veya "seyyar satıcılık yapar". Bu duygu genellikle bir geliştiricinin, bir kesme işleyicisinin oluşturulmasını zorlaştıran bir takım özelliklere sahip kişisel bir bilgisayar için kesintilerle ilgili deneyiminden kaynaklanır. Bu sorunların çoğu mikrodenetleyici tabanlı donanımlarda yoktur. kullanım bu ekipman kesmeler, gelişimini ve uygulamasını büyük ölçüde basitleştirebilir.

    Kesintilerle hiç uğraşmadıysanız, o zaman bir sorunuz olacak - bu nedir? İÇİNDE bilgisayar sistemi Kesme, bir donanım sinyali tarafından çağrılan özel bir alt programın ("kesme işleyicisi" veya "kesme hizmet yordamı" olarak adlandırılır) yürütülmesidir. Bu alt programın süresi boyunca, geçerli programın yürütülmesi durdurulur. "Kesme talebi" terimi, bazen program kesmeyi onaylamayı reddettiği ve kesme işleyicisini hemen çalıştırdığı için kullanılır (Şekil 2.19).

    Bir bilgisayar sistemindeki kesintiler, günlük yaşamdaki kesintilere benzer. Böyle bir kesintinin klasik bir örneği, bir TV programı izlerken telefonla aranmasıdır. Telefon çaldığında üç seçeneğiniz vardır. İlki, aramayı görmezden gelmektir. İkincisi, aramayı cevaplamak, ancak daha sonra geri arayacağını söylemek. Üçüncüsü, tüm mevcut işleri erteleyerek aramayı cevaplamaktır. Bilgisayar sistemi ayrıca, harici bir donanım isteğine yanıt olarak kullanılan üç benzer yanıta sahiptir.

    İlk olası yanıt - ʼʼmevcut görev tamamlanana kadar bir kesmeye cevap vermeʼʼ - kesme talebinin servisi devre dışı bırakılarak (maskelenerek) uygulanır. Görev tamamlandıktan sonra iki seçenekten biri mümkündür: maskeyi sıfırlamak ve kesme işleyicisinin çağrılmasına neden olacak hizmeti etkinleştirmek veya bitlerin değerini analiz etmek ("yoklama"). kesme isteklerinin alındığını ve hizmet programının kesme işleyicisini çağırmadan doğrudan yürütüldüğünü gösterir. Bu kesme işleme yöntemi, sağlanması gerektiğinde kullanılır. verilen zaman herhangi bir kesinti hayati bir arayüzün uygulanmasını bozabileceğinden, ana programın yürütülmesi.

    Pirinç. 2.18 - Bir kesintinin yürütülmesi.

    Uzun kesinti maskeleme önerilmez, çünkü bu süre zarfında birkaç kesinti olayı çakışabilir ve yalnızca biri tanınacaktır. İzin verilen maskeleme süresi, mikrodenetleyicinin özel uygulamasına, bu tür olayların tipine ve sıklığına bağlıdır. Kesinti talep eden olaylar için beklenen minimum aralığın yarısından fazlası için kesintilerin devre dışı bırakılması önerilmez.

    Kesme işleyicisi her zaman aşağıdaki eylem sırasını sağlar:

    2. Kesme denetleyicisini ve isteğe neden olan donanımı sıfırlayın.

    3. Verileri işleyin.

    4. Bağlam kayıtlarının içeriğini geri yükleyin.

    5. Kesilen programa geri dönün.

    Bağlam kayıtları, ana programın mevcut yürütme durumunu belirleyen kayıtlardır. Bunlar genellikle program sayacını, durum kayıtlarını ve toplayıcıları içerir. İndeks kayıtları gibi diğer işlemci kayıtları, kesme işlemi sırasında kullanılır ve bu nedenle içeriklerinin kaydedilmesi de son derece önemlidir. Diğer tüm kayıtlar, belirli bir mikrodenetleyiciye ve onun uygulamasına özeldir.

    sıfırladıktan sonra ilk durum kesme denetleyicisi bir sonraki isteği kabul etmeye hazırdır ve kesmeye neden olan donanım, uygun nedenler ortaya çıktığında bir istek göndermeye hazırdır. Yeni bir kesme isteği gelirse, işlemcinin kesme maskeleme kaydı kesmenin işlenmesini engeller, ancak kesme durum kaydı düzeltir verilen istek kim onların hizmetini bekliyor olacak. Mevcut kesmenin işlenmesi tamamlandıktan sonra kesme maskesi sıfırlanacak ve yeni alınan istek işlenecektir.

    İç içe kesmelerin, yığını olmayan bazı mikrodenetleyici türlerinde uygulanması zordur. Bu kesintiler, yığın taşması sorunlarına da neden olabilir. Taşma sorunu, sınırlı miktarda veri belleği ve yığını nedeniyle mikrodenetleyicilerle ilgilidir: bir dizi iç içe kesme, yığına izin verilenden daha fazla verinin yerleştirilmesine neden olabilir.

    Son olarak, kesme işlenir. İkinci TV örneği, mevcut görevi çözdükten sonra kullanılacak olan gerekli verileri alarak bir kesme isteğine hızlı bir şekilde yanıt verebileceğinizi göstermektedir. Mikrodenetleyicilerde bu, alınan verileri bir bellek dizisinde depolayarak ve ardından orijinal programın yürütülmesi tamamlandığında bunları işleyerek gerçekleştirilir. Bu tür bir hizmet, uzun zaman alabilen kesintiyi tamamen anında ele almak ile kesintiye neden olan olay hakkında bilgi kaybına yol açabilecek kesintiyi yok saymak arasında iyi bir uzlaşmadır.

    Bağlam kayıtlarını geri yüklemek ve kesme dönüş komutunu yürütmek, işlemciyi kesme gerçekleşmeden önceki durumuna döndürür.

    Kesinti işleme sırasında çeşitli kayıtların içeriğine ne olduğunu düşünün. Durum kaydının içeriği genellikle kesme işlenmeden önce program sayacının içeriğiyle birlikte otomatik olarak kaydedilir. Bu, hafızada tutmanın aciliyetini ortadan kaldırır. yazılım araçları transfer komutlarını kullanın ve ardından geri döndüğünüzde geri yükleyin. orijinal program. Aynı zamanda, böyle otomatik kaydetme her tür mikrodenetleyicide uygulanmaz, bununla bağlantılı olarak kesme işleme organizasyonuna özel dikkat gösterilmelidir.

    Durum kaydının içeriği, kesme işleyici yürütmesi başlamadan önce kaydedilirse, dönüş komutu tarafından otomatik olarak geri yüklenir.

    Diğer işlemci kayıtlarının içeriği kesme hizmeti sırasında değiştirilirse, değişiklikten önce bellekte saklanmalı ve ana programa dönmeden önce geri yüklenmelidir. Bulunması çok zor olan öngörülemeyen hatalardan kaçınmak için tüm işlemci kayıtlarını kaydetmek yaygın bir uygulamadır.

    Kesme işleyicisine atladığınızda program sayacına yüklenen adrese "kesme vektörü" denir. Birkaç vektör türü vardır. Mikrodenetleyici başlatıldığında (sıfırlama) program sayacına yüklenen adres genellikle "sıfırlama vektörü" olarak adlandırılır. Farklı vektörlere farklı kesinti vektörleri atanabilir, bu da bakım programını kesintinin nedenini belirlemenin aşırı öneminden kurtarır. Aynı vektörün farklı kesintilerinin kullanılması genellikle mikrodenetleyicilerin çalışmasında sorunlara neden olmaz, çünkü çoğu zaman mikrodenetleyici tek bir program yürütür. Bu mikrodenetleyici, çalışması sırasında çeşitli kesme kaynaklarının eklenebildiği kişisel bir bilgisayardan farklıdır. (Daha önce iki cihazı COM1 ve COM3 bağlantı noktalarına bağladıysanız, bunun ne hakkında olduğunu hayal edebilirsiniz). Donanımı iyi bilinen bir mikrodenetleyicide herhangi bir sorun olmaması gerekir. paylaşım kesme vektörleri.

    Dikkate alınması gereken son şey, yazılım kesintileridir. Donanım kesintilerini simüle etmek için kullanılabilecek işlemci talimatları vardır. Bu komutların en belirgin kullanımı, bellekte keyfi bir konumda bulunan veya bunlara erişmek için bölümler arası atlamalar gerektiren sistem alt programlarını çağırmaktır. Bu özellik, Intel i86 ailesinin mikroişlemcilerinde uygulanmaktadır ve temel sistem G/Ç BIOS'u(Temel Giriş/Çıkış Sistemi) ve çalıştırma DOS sistemi kişisel bilgisayarlar giriş noktasını sabitlemenin aşırı önemi olmadan sistem rutinlerini çağırmak. Bunun yerine, böyle bir yazılım kesintisi meydana geldiğinde yürütülecek talimatı seçerek çeşitli kesme vektörleri kullanılır.

    Belki de bu bölümü okuduktan sonra, kesme mekanizması sizin için daha anlaşılır hale gelecek veya tam tersi. Sadece daha fazla kafan karışacak. Her bir mikrodenetleyici açıklanırken, kesme kullanımının uygulamasını nasıl basitleştirebileceği gösterilecektir.

    kesintiler. - kavram ve türleri. "Kesintiler" kategorisinin sınıflandırılması ve özellikleri. 2017, 2018.

    3. Kesme örnekleri

    3.1. G/Ç bağlantı noktalarında sinyal değişikliğinde kesinti (PROTEUS'ta örnek)

    3.2. Harici kesinti INT (PROTEUS'ta örnek)

    dsPIC mimarisinin tüm mikrodenetleyici türleri aynı kesintilere sahiptir. Bu nedenle kesmeleri PROTEUS programında güvenle inceleyebilirsiniz. Çalışma için PROTEUS'ta bulunan mikrodenetleyiciyi kullanacağız.

    Peki, dsPIC33FJ32GP204 mikrodenetleyicisinde ne tür kesintiler var?

    Ve mikrodenetleyicide çok fazla kesinti var. Ve bu dersteki her şeyi listelemek mantıklı değil. Sonuçta, bir mikrodenetleyici seçerken ilk dikkat ettiğimiz şey, sahip olduğu modüllerdir ve ancak o zaman sahip olduğu kesintilere bakarız. Aynı şekilde her şeyi aynı sırayla inceleyeceğiz. Mikrodenetleyiciyi incelerken, çeşitli modüllerin kesintilerini analiz edeceğiz.

    Genel olarak, program belleğinde yer alan mikrodenetleyici için bir kesme vektör tablosu olduğunu bilmeniz gerekir. Her kesmenin kendi vektörü vardır, yani belirli kesme işleyici (ISR) rutininin başlangıç ​​adresi. Alternatif bir kesinti vektör tablosu da vardır. Tek bir ALTTERS biti ile kesme yordamı adresinin hangi tablodan alınması gerektiğini belirleyebilirsiniz. Yani, ana tabloya bir alternatif var. Ancak, ALTTERS bitinin tüm tablo için bir kerede kullanıldığını hatırlamanız gerekir. Alternatif bir tablo kurulursa, ana program kesme işleme rutininin kesinlikle tüm adreslerini alternatif tablodan alacaktır. Alternatif tablo, kontrolöre bir kez bir program yazmanıza ve örneğin bir düğmeyi kullanarak iki program çalıştırma algoritması arasında seçim yapmanıza izin verdiği için hata ayıklama modu için çok kullanışlıdır.

    dsPIC, kesme öncelikleri aralığını genişletti. PIC18'de yalnızca 2 tane varsa, o zaman dsPIC'de zaten 8 seviye vardır. Ve bir GPRS kanalı üzerinden iletişim için bir modül geliştirirken, bu benim için çok faydalı oldu, çünkü mikrodenetleyici kartta bulunan hemen hemen tüm çevre birimlerini kullandı ve işlenen kesintilerin sayısı yaklaşık yirmi idi.

    Bilinmesi gereken en önemli şey, her kesme ile çalışacak yalnızca 3 ana bit (kayıt) olduğudur: kesme etkinleştirme biti, kesme bayrağı ve üç kesme önceliği seçim biti.

    Öyleyse, kesintilerle çalışmak için bir programcıdan gerekenler:

    1. Belirli bir kesintiye izin vermesi gerekiyor.

    2. Kesintiye neden olan olay meydana geldikten sonra, karşılık gelen kesme bayrağı ayarlanır ve program tabiri caizse kesme vektörü boyunca atlar. Ve normal bir dilde şöyle derseniz: o zaman, bir kesme meydana gelir gelmez, belirli bir kesmeyi işlemek için alt program hemen çağrılacaktır.

    3. Asıl mesele, kesme rutininde bu kesmenin bayrağını sıfırlamayı unutmamaktır.

    dsPIC mikrodenetleyicisi için, C30 derleyicisi, örneğin INT1 kesintisi için kesme rutinlerini açıklamak için aşağıdaki kuralı sağlar:

    geçersiz __ Öznitellikler__((__ yarıda kesmek__)) _ INT1 Yarıda kesmek()

    Dikkat etmeniz gereken asıl şey, alt program başlık metninin sonudur: _ INT1 Yarıda kesmek() - bu, değiştirilmesi gereken tek parametredir. Çeşitli türler araya girer. Kesinti vektör tablosundaki her kesmenin kendi ataması vardır. verilen parametre. Ve burada C30 derleyicisi için yardım dosyasını, özellikle (benim var ...) “dsPIC30F DSCs (SMPS) Interrupt Vectors” bölümünü açmanız ve hangi interrupt'ın ne şekilde çağrılması gerektiği tablosuna bakmanız gerekecek. C30 derleyicisi olan herkesin ekinde bir yardım dosyası olması gerektiği için bu yazıda bu tabloyu sunmayı uygun bulmuyorum. hlpMPLABC30.chm(Şahsen ben buna böyle derim). Ve bu derleyiciye sahip olmayanlar için J tablosuna ihtiyaçları yoktur. Tamam, konudan sapın ...

    Bu arada, kesme işlevini açıklama ilkelerini daha yakından tanırsanız, özel bir auto_psv özniteliğinin varlığını tespit edebileceksiniz. Bu parametrenin amacı, mikrodenetleyiciye, işlemeyi kesmeye devam etmeden önce ana kayıtları kaydetmesi gerektiğini belirtmektir. Anahtar kayıtlarının ne için olduğunu bildiğinizi varsayıyorum.

    Örneğin, bir kesme açıklaması şuna benzer:

    geçersiz__attribute__((interrupt, auto_psv)) _INT1Interrupt()

    Yukarıda, ana tablonun adresini kullanan bir alt program çağrı başlığı örneği vardı. Ve alternatif bir masa için ihtiyacınız olan tek şey değiştirilebilir parametre altı çizgiden sonra ekle alternatif, Örneğin:

    _ INT1 Yarıda kesmek() -> _ AltINT1 Yarıda kesmek()

    Kesme yordamı bir alt program gibi görünse de bildirilmesi gerekmediğine ayrıca dikkat çekmek istiyorum. ana , zaten derleyici tarafından bildirildiğinden, yalnızca kesme yordamının başlığını doğru yazmanız gerekir.

    Temel kesintilerin incelenmesiyle başlayalım ve ardından her modülün çalışmasında, bunların doğasında bulunan kesintileri tanıyacağız.

    3.1. G/Ç bağlantı noktası değişikliği kesintisi (CN)

    Anlaşılması en kolay kesmelerden biri CN kesmesidir. dsPIC33FJ32GP204 mikro denetleyicisi bu tür girdilerle dolu, bu yüzden bu sayının herhangi bir talebi karşılayacağını düşünüyorum. Bu kanallarda ("1" -> "0" veya "0" -> "1") hangi durumun değiştiği önemli değildir, bu değişiklik etkinleştirilirse "CNIF" bayrağının ayarlanmasına neden olur. Sinyal değişikliği kesintisini etkinleştirmek için aşağıdakileri yapmanız gerekir:

    1. Gerekli CN kanallarını girişe ayarlayın (TRISx kaydını kullanarak).

    2. İlgili CN girişinde sinyal değişikliği kontrolünü etkinleştirin. Bunun için zaten 2 kayıt CNEN1 ve CNEN2 var. Ayar için her bir kayda tamamen erişebilir veya karşılık gelen bitlere erişebilirsiniz (örneğin _CN15IE=1; _CN6IE=1;)

    3. Gerekirse çekme dirençlerini açın. Bunun için ayrıca CNPU1 ve CNPU2 olmak üzere iki register vardır. Ayrı olarak da mümkündür, örneğin _CN15PUE=1; _CN6PUE=1;

    4. CN'ye sinyal değişikliği kesintisini etkinleştirin ( _ CNIE=1 )

    5. Şimdi, izlenen CN pinlerindeki sinyal değişir değişmez, kesme bayrağı _CNIF ayarlanacaktır. Ve program kesme işleme fonksiyonuna girer. CN'ye sinyal değişikliğinde kesinti için C30 derleyicisi aşağıdaki işlev açıklamasını sağladı:

    geçersiz __ Öznitellikler __((__ yarıda kesmek __)) _ CNInterrupt ()

    Bu kesintinin işlenmesinin gerçekleştiği yer burasıdır (örneğe bakın)

    6. Kesme rutininde kesme bayrağını sıfırlamayı unutmayın.

    Bu tür bir kesinti hakkında bilgi sahibi olmak için aşağıdaki örneği göz önünde bulundurun. Bir motor ve 4 sensör var. Her şey yolunda olduğunda, motor saat yönünün tersine dönmelidir. Ancak sensörün durumu değişir değişmez (acil durum modu) - motor hemen dönmeye başlamalıdır. ters taraf(saat yönünde). Ve belirli bir süre sonra tekrar saat yönünün tersine dönmeye başlar.

    Benzer şekilde, hasat makinelerinde bir metal detektörü uygulanmaktadır. Örneğin, makineye biçilmiş çim girdiğinde, bu normal çalışma modudur. Ancak metal dedektörü metal bir nesne algılar algılamaz anında tersine döner ve makine, mekanizmaya zarar vermemek için olduğu gibi bu metal nesneyi tükürür. Ve metal, birkaç bağımsız kanaldan oluşan, ancak tek bir kanalda birleştirilen özel bir sensör tarafından algılanır. genel cihaz. Örneğimizde elbette her şeyi çok basitleştireceğiz, metal varlık sensörü yerine sıradan düğmeler kullanacağız.

    Devrenin PROTEUS'ta montajı

    Ve şimdi görevi gerçekleştirmek için bir program yazıyoruz.

    # katmak " P33 fxxxx. H"

    _ FOSSEL(0 X02);

    _ FOSC(0 xE2);

    karakter durum; // değişken, motorun dönüş yönünü saklar

    // "1" - acil durum modu, "0" - normal mod

    geçersiz içinde (geçersiz);

    geçersiz içinde (geçersiz)

    { _ CN8 PUE=1; // pull-up direncini CN8 (RC0) girişine açın

    _ CN10 PUE=1; // pull-up direncini CN10 (RC2) girişine açın

    _ CN17 PUE=1; // pull-up direncini CN17 (RC7) girişine açın

    _ CN19 PUE=1; // pull-up direncini CN19 (RC9) girişine açın

    AD1 PCFGL=0 xffff;

    PORTC=0; // port C'yi başlat

    LATÇ=0;

    TRISC=0 xFFFF; // port C'yi giriş olarak ayarla

    PORTC=0 xFFFF;

    PORTA=0; // port A'yı başlat

    LATA=0;

    TRISA=0; // Tüm çıktılar çıktı olarak ayarlandı,

    PORTA=0;

    _ CN8 IE=1; // sinyal değişikliği kontrolünü etkinleştir

    _ CN10 IE=1; // ilgili pinler

    _ CN17 IE=1; // üzerlerindeki sinyal değişirse, o zaman

    _ CN19 IE=1; // kesme işaretini ayarla _CNIF

    _ CNIE=1; // INT1 kesmesini etkinleştir

    geçersiz __ Öznitellikler__((__ yarıda kesmek__)) _ CNInterrupt()

    durum=1; // bu bir acil durum modudur

    _ CNIF=0; // sinyal değişikliğinde kesme bayrağını sıfırla

    geçersiz ana (geçersiz)

    { statik uzun int Ben;

    içinde();

    durum=0; // başlangıçtaki çalışma modunun normal olduğunu kabul edin

    sırasında(1) // koşmak sonsuz döngü

    { eğer (durum) // acil durum modu ise, o zaman

    { _ CNIE=0; // sinyal değişikliğinde kesmeyi devre dışı bırak

    _ RA8=0;

    _ RA0=1; // acil durum modunda

    için(Ben=0; Ben<210000; Ben++) // bir gecikme sağlayın

    durum=0; // normal motor çalışmasını etkinleştir

    _ CNIE=1; // CN kesintilerini etkinleştir

    { _ RA8=1; // normal modda

    _ RA0=0; // motor dönüş yönlerini sağlayın

    } // süre(1)

    3.2. Harici kesintiINT

    Harici cihazların eylemlerine anında yanıt vermek için mikrodenetleyicinize ihtiyacınız varsa, ihtiyacınız olan şey INT kesmesidir. dsPIC33FJ32GP204 mikro denetleyicisinin üç INT kanalı vardır (INT0, INT1, INT2). Yani, üç harici cihazın her biri için kendi kesmenizi sağlayabilirsiniz. Bu kesinti, denetleyiciyi UYKU modundan uyandırabilmesi açısından iyidir. Ayrıca mikrodenetleyici kaynaklarını tüketecek olan bu girişleri sürekli taramanıza gerek yoktur.

    Kesinti INT, girişteki sinyal "0" -> "1" veya "1" -> "0" olarak değiştiğinde gerçekleşir. Bitin durumuna bağlıdır _INT1EP. Eğer _INT1EP=1, ardından arka kenarda; Eğer _INT1EP=0, ardından yükselen kenarda (örneğin _INT1EP=1 - kesme INT0, düşen kenarda gerçekleşir).

    Önceliğe gelince, INT0 kesmesi en yüksek önceliğe sahiptir ve kesme tablosundaki ilk kişidir. Aşağıda INT1 ve INT2 kesmeleri bulunmaktadır.

    Prensip olarak, bu kesintinin tüm özellikleri budur. Diğer her şey diğer kesmelerle aynıdır, yani ilgili harici kesmeyi etkinleştirmeniz gerekir. Ve bir kesinti meydana gelirse, uygun _INTxIF bayrağını ayarlayacaktır (örneğin, _INT1IF). düşürmeyi unutmayın. Genel olarak, her şey basit.

    bir örneğe gidelim

    Bir daireye veya eve elektronik bir çağrı gönderiyoruz. Cihaz, butona basıldığında şu mesajı vermelidir: ses sinyali ve ışıkla göz kırpın (yüksek sesle müzik dinlemeyi sevenler için).

    PROTEUS'ta bir devre çiziyoruz, mikrodenetleyiciye ek olarak başka bir düğmeye, bir zile ve bir LED'e ihtiyacımız var.

    Bence resim çok net. Programa geçelim.

    #katmak"p33Fxxxx.h"

    // Osilatör Ayar Bitlerini Ayarlayın (HS)

    _ FOSSEL(0 X02);

    _ FOSC(0 xE2);

    karakterdurum;// "1" - aramayı aç, "0" - aramayı kapat

    geçersizbaşlangıç(boşluk);//bir başlatma yordamı bildiriliyor

    // ** alt program başlatma **

    geçersizbaşlangıç ​​(geçersiz)

    ( _CN4PUE=1;// pull-up direncini CN4 (RB0) girişine açın

    AD1PCFGL=0xffff;// tüm pinler dijital I/O olarak

    PORTB=0x00;// port B'yi başlat

    LATB=0;

    TRISB=0x0001;// çıkış RB0 girişi olarak ayarlandı

    PORTB=0x00;

    // port C'yi başlat

    PORTC=0;

    LATC=0;

    TRISC=0;// tüm pinleri çıkış olarak ayarla

    PORTC=0;

    RPINR0=0x0000;// INT1 sinyali RP0 (RB0) çıkışından (bu

    // komut tüm dsPIC için değil

    _INT1EP=1;// INT1 kesmesi düşen kenarda gerçekleşir

    _INT1IE=1;// INT1 kesmesini etkinleştir

    // ****** rutini kesme *

    geçersiz __ Öznitellikler__((__ yarıda kesmek__)) _ INT1 Yarıda kesmek()

    durum=1; // aramayı etkinleştirmeniz gerekiyor

    _ INT1 EĞER=0; // INT1 kesme bayrağını sıfırla

    // **** Program giriş noktası *

    geçersiz ana (geçersiz)

    { statik uzun int Ben; //gecikmeyi düzenlemek için bir değişken tanımlıyoruz

    içinde();// çağrı başlatma rutini

    durum=0;// önce çağrı kapatılmalıdır

    süre(1)// sonsuz bir döngü başlat

    ( if (durum)// durum "1" ise, o zaman

    (_RC0=1;// LED'i yak

    _RC2=1;// zili aç

    için(i=0;i<160000;i++) // gecikme, oynamak için belirli bir süre sağlar

    durum=0;// zil sesinin devre dışı bırakılması gerektiğini belirtin

    başka// aksi takdirde, eğer durum "0" ise, o zaman

    (_RC0=0;// led'i kapat

    _RC2=0;// bip sesini durdur

    } // süre(1)

    Benzer şekilde, INT0 ve INT2 kesmeleriyle çalışın. Diğer örneklerde, bu kesmeleri birden fazla kullanacağız.

    Tek bir çevresel cihaza birçok farklı görevi asmanız gerektiğinde böyle bir durum vardır, ancak bu yalnızca bir tanesidir ve bu konuda bir şeyler yapılması gerekir.

    Basit bir örnek, bir zamanlayıcı ve onun taşma kesintisidir.
    Bazı işlemleri yapmak için deklanşör hızını ve kesintiyi ayarlayabiliriz. Ancak, zamanın bir noktasında, kesme zamanlayıcısının bir işlem yapmasını ve ardından üçüncü işlemi yapmasını istiyorsak. Evet, duruma göre istediğiniz kadar. Ve sadece bir vektör var.

    Veya örneğin USART. Kesme moduna bağlı olarak, bir bayt geldiğinde farklı bir kodun yürütülmesini kolayca isteyebiliriz. Bir modda - bir selamlama, diğerinde - banyoya müstehcen bir dil göndermek. Kafaya üçüncü darbede. Ve sadece bir vektör var.

    Tabii ki, kesme işleyicisine bir anahtar kasası yapısı ekleyebilir ve bir mod seçerek kodun istenen bölümüne gidebilirsiniz, ancak bu oldukça zahmetlidir ve en önemlisi, geçiş süresi bağlı olarak farklı olacaktır. geçiş durumu anket karşılaştırmasının gideceği sıra yapılar.

    Yani, formun bir anahtarında:

    1 2 3 4 5 6 7 anahtar (x) ( 1 : Eylem 1 2 : Eylem 2 3 : Eylem 3 4 : Eylem 4 )

    switch(x) ( 1: Eylem 1 2: Eylem 2 3: Eylem 3 4: Eylem 4 )

    X'in önce 1 ile, sonra 2 ile, sonra 3 ile ve tüm seçenekler tükenene kadar sıralı bir karşılaştırması yapılacaktır. Ve bu durumda, Eylem 1'e verilen tepki, Eylem 4'e verilen tepkiden daha hızlı olacaktır. Bu, zamanlayıcıdaki kesin zaman aralıklarını hesaplarken özellikle önemlidir.

    Ancak bu sorunun basit bir çözümü var - bir dizin atlama. Kesintiyi beklemeye başlamadan önce, vektörümüzü yeniden yönlendirmemiz ve dizin geçişini kesme işleyicisine yapıştırmamız gereken yönü değişkenleri önceden yüklememiz (veya hemen Z dizin kaydına girebilirsiniz) yeterlidir. Ve işte! Geçiş, herhangi bir seçenek karşılaştırması olmadan ihtiyacınız olan yerde olacaktır.

    Bellekte, kayan bir vektör için değişkenler yaratırız:

    Timer0_Vect_L: .byte 1 ; İki adres baytı, yüksek ve düşük Timer0_Vect_H: .byte 1

    Bir kesmeyi beklemeye hazırlanmak basittir, onu alıp istediğimiz adresle değişkenimize yüklüyoruz

    CLI; kritik parça. Kesintiler KAPALI LDI R16,düşük(Zamanlayıcı_01) ; Adresi alıp STS Timer0_Vect_L,R16'yı kaydediyoruz; bir bellek hücresine aktarın. LDI R16,Yüksek(Zamanlayıcı_01) ; Benzer şekilde, ancak en yüksek vektör STS ile Timer0_Vect_H,R16 SEI; Kesintiler AÇIK

    Her şey, zamanlayıcıyı başlatabilir ve kesintimizi bekleyebilirsiniz. Diğer durumlarda benzer.

    Ve işleyici şöyle görünür:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 ;============================== ; Timer0'dan taşma kesme girişi ;=========================== TIMER_0: PUSH ZL ; PUSH ZH'yi yığınlamak için dizin kaydını kaydedin; Çünkü PUSH R2 kullanıyoruz; R2'yi kaydedin, çünkü R2,SREG'DE onu da bozarız; Bayrak kaydını alın ve kaydedin PUSH R2 ; Bunu yapmazsanız, %100 hata alırız LDS ZL,Timer0_Vect_L ; yeni vektör LDS'nin adresini yükleyin ZH,Timer0_Vect_H ; her iki bayt. CLR R2; R2 VEYA R2,ZL'yi Temizle; Vektörü sıfır için kontrol ediyoruz. Aksi takdirde, OR R2,ZH analogunu alırız; reset"a. Kontrol işlemi VEYA BREQ Exit_Tm0 ; sonucun R2'de birikmesiyle ; böylece Z'nin içeriğini bozmayız ve buna gerek kalmaz; tekrar yükleyin IJMP ; Yeni boyunca ayrılıyoruz vektör; Kesintiden çık Exit_Tm0: POP R2 ; Flag register OUT SREG,R2 POP R2 ; restore R2 POP ZH ; restore Z POP ZL RETI ; Ek vektör 1 Timer_01: NOP ; Bunlar bizim yeni vektörlerimiz NOP ; burada herhangi bir NOP yapabiliriz; tercihen uzun süre değil - aynı kesme NOP'unda; Başka NOP ; kayıtları kullanırsak, onları RJMP Exit_Tm0 yığınına da kaydederiz; Bu, kesmeden çıkmak için bir geçiştir; özel olarak yapılır RJMP; Ek vektör 2 ; dönüş kodunda on bayt tasarruf edin :))) Timer_02: NOP NOP NOP NOP NOP RJMP Exit_Tm0 ;Ek Vektör 3 Timer_03: NOP NOP NOP NOP NOP RJMP Exit_Tm0

    ;============================== ; Timer0'dan taşma kesme girişi ;=========================== TIMER_0: PUSH ZL ; PUSH ZH'yi yığınlamak için dizin kaydını kaydedin; Çünkü PUSH R2 kullanıyoruz; R2'yi kaydedin, çünkü R2,SREG'DE onu da bozarız; Bayrak kaydını alın ve kaydedin PUSH R2 ; Bunu yapmazsanız, %100 hata alırız LDS ZL,Timer0_Vect_L ; yeni vektör LDS'nin adresini yükleyin ZH,Timer0_Vect_H ; her iki bayt. CLR R2; R2 VEYA R2,ZL'yi Temizle; Vektörü sıfır için kontrol ediyoruz. Aksi takdirde, OR R2,ZH analogunu alırız; reset"a. Kontrol işlemi VEYA BREQ Exit_Tm0 ; sonucun R2'de birikmesiyle ; böylece Z'nin içeriğini bozmayız ve buna gerek kalmaz; tekrar yükleyin IJMP ; Yeni boyunca ayrılıyoruz vektör; Kesintiden çık Exit_Tm0: POP R2 ; Flag register OUT SREG,R2 POP R2 ; restore R2 POP ZH ; restore Z POP ZL RETI ; Ek vektör 1 Timer_01: NOP ; Bunlar bizim yeni vektörlerimiz NOP ; burada herhangi bir NOP yapabiliriz; tercihen uzun süre değil - aynı kesme NOP'unda; Başka NOP ; kayıtları kullanırsak, onları RJMP Exit_Tm0 yığınına da kaydederiz; Bu, kesmeden çıkmak için bir geçiştir; özel olarak yapılır RJMP; Ek vektör 2 ; dönüş kodunda on bayt tasarruf edin :))) Timer_02: NOP NOP NOP NOP NOP RJMP Exit_Tm0 ;Ek Vektör 3 Timer_03: NOP NOP NOP NOP NOP RJMP Exit_Tm0

    RTOS için uygulama
    Ancak, tüm kodların RTOS dağıtıcısı aracılığıyla görev zincirleri boyunca döneceği şekilde oluşturulmuş bir programımız varsa ne olur? Bu zincirlerin birbirine göre nasıl çalıştığını akılda hesaplamak çok zordur. Ve her biri zamanlayıcıyı ele geçirmeye çalışabilir (elbette keyfi olarak değil, bizim önerimiz üzerine programı yazıyoruz, ancak her şeyin zamanında nasıl olacağını takip etmek zor olacak).
    Modern büyük eksenlerde, bu durum için bir Karşılıklı dışlama - muteks mekanizması vardır. Onlar. bir çeşit meşgul bayrağıdır. Bir işlem örneğin UART ile iletişim kurarsa, başka bir işlem oraya bir bayt koymaya cesaret edemez ve görev bilinciyle ilk işlem bayrakla gösterilen UART'ı serbest bırakana kadar bekler.

    Madende karşılıklı dışlama mekanizmaları yok ama uygulanabilir. En azından biraz benzerlik göster. Tüm bu saçmalıkların tam teşekküllü bir uygulamasını yapmak istemiyorum çünkü amacım çekirdek boyutunu 500-800 baytta tutmak.
    En kolay yol, bellekte bir bayt daha ayırmaktır - meşgul değişken. Ve bir süreç bir kaynağı aldığında, bu değişkene onu yaklaşık olarak ne zaman serbest bırakacağını yazar. Zaman, 1ms'ye sahip olduğum sistem zamanlayıcısının tikleriyle geçiyor.
    Başka herhangi bir işlem aynı donanım kaynağına erişmeye çalışırsa, önce meşgul durumuna bakar, meşgul olacağı süreyi sayar ve bu süre boyunca sigara içmeye bırakılır - zamanlayıcı ile kendini kuyruğa yükler. Orada tekrar kontrol edecek vb. Bu en basit seçenektir.

    Buradaki sorun şu ki, bir vektör için çok sayıda başvuran varsa, o zaman süreçler, festival şenlikleri sırasında meydandaki tek tuvaletin etrafında güm güm atan gençler gibi, dönüp duracaktır. Birinin mesanesi buna dayanamaz - algoritma bozulur. Ve incirleri kim tahmin ediyor, çünkü. modellemek zor olacaktır.

    Sorunun çözümü, bu sefer kaynağa erişim için başka bir düzenli zincir eklemektir. Böylece hiç boş durmuyor. Onlar. biri atladı, sonra ikinci, üçüncü vb. tüm süreçler bir tür USART'ta işini yapana kadar.
    Dezavantajı açıktır - başka bir sıra, ek bellek, ek kod, ek süredir. Elbette, kuyruktaki ana devre dağıtım kodunu vektöre saptırabilir ve kışkırtabilirsiniz. Ancak burada her şeyi dikkatlice ayıklamanız gerekir, çünkü kesinti ile çağrılacaktır! Evet ve hantal, yalnızca çok sayıda başvuranımız olduğunda gereklidir.

    İkinci çözüm, meşgul zaman değişkenini atıp geriye yalnızca "Meşgul!" bayrağını bırakmaktır. Ve uygulamaya çalışan süreç sigara içmek için kaçmaz, ancak birkaç adım geri döner - görev kuyruğunun sonuna kadar ve hemen geri döner. Tuvaletin etrafındaki insanlar koşarak değil, ilk kim sürünecek prensibine göre girişte dirseklerini itiyor.
    Diğer bir dezavantaj, ana boru hattındaki büyük bir yük, tüm RAM için bu kadar uzun süre şişmek ve yığınla buluşmak için bir dizi kuyruk talebidir ve bu, küresel bir kıyametle doludur.

    Elbette, zamanlayıcı burada örnek olarak verilmiştir, görevlerin çoğu RTOS sistem zamanlayıcısı ile çözülebilir, ancak birdenbire bir olaya daha az ayrıklık veya yüksek hızlı yanıt vermeniz gerekirse (ve ana boru hattı sürüklenene kadar değil) yürütme görevi), ardından kontrollü kesinti mekanizması, IMHO, ardından doktorun reçete ettiği şey.