Kesme işleyicileri Cortex M0'ın CMSIS'inde nasıl uygulanır?


9

Bir LPC1114 kitim var. Son birkaç gündür, işlerin nasıl yapıldığını bulmak için Cortex M0'ın CMSIS uygulamasını inceliyorum. Şimdiye kadar her kaydın nasıl eşlendiğini ve ona nasıl erişebileceğimi anladım. Ama yine de içinde kesintilerin nasıl uygulandığını bilmiyorum. CMSIS'deki kesintiler hakkında bildiğim tek şey, başlangıç ​​dosyasında belirtilen bazı kesme işleyici adları olmasıdır. Ve kendi işleyicilerimi başlangıç ​​dosyasında belirtilen isimlerle bir C fonksiyonu yazarak yazabilirim. Beni şaşırtan şey, kullanım kılavuzunda, tüm GPIO'nun harici kesme kaynakları olarak kullanılabileceği söyleniyor. Ancak başlangıç ​​dosyasında yalnızca 4 PIO kesintisi var. Söyle bana:

  1. Diğer GPIO'lar için harici kesme işleyicilerini nasıl uygulayabilirim?
  2. Kesme tablosu CMSIS'de nerede eşlenir?
  3. NVIC ile AVR / PIC'lerde kesme uygulaması arasındaki büyük farklar nelerdir? (NVIC flaşın herhangi bir yerine eşlenebilir)

Yanıtlar:


14

Aşağıdaki bilgiler Igor'un mükemmel cevabına ek olarak verilmiştir.

C programlama açısından, kesme işleyicileri cr_startup_xxx.c dosyasında tanımlanır (örn. LPC1343 için cr_startup_lpc13.c dosyası). Tüm olası kesme işleyicileri orada bir WEAK takma adı olarak tanımlanır. Bir kesme kaynağı için kendi XXX_Handler () yönteminizi tanımlamazsanız, bu dosyada tanımlanan varsayılan kesme işleyici işlevi kullanılır. Bağlayıcı, cr_startup_xxx.c'deki kesinti vektör tablosu ile birlikte son ikili dosyaya hangi işlevi dahil edeceğini sıralar.

Bağlantı noktalarından kaynaklanan GPIO kesintileri örneği gpio.c'deki demo dosyalarında gösterilmiştir. GPIO bağlantı noktası başına NVIC'ye bir kesme girişi vardır. Bağlantı noktasındaki her bir bit, o bağlantı noktasında bir kesme oluşturmak için etkinleştirilebilir / devre dışı bırakılabilir. Örneğin PIO1_4 ve PIO1_5 bağlantı noktalarında kesilmeye ihtiyacınız varsa, GPIO0IE'de ayrı PIO1_4 ve PIO1_5 kesme bitlerini etkinleştirirsiniz. PIOINT0_Handler () kesme işleyici işlevi tetiklendiğinde, GPIO0RIS kaydını okuyarak ve kesmeyi uygun şekilde işleyerek PIO1_4 veya PIO1_5 (veya her ikisi) kesintilerinin hangisinin beklendiğini belirlemek size bağlıdır.


10

(1. ve 2. noktaların mimari kısıtlamalar değil uygulama ayrıntıları olduğunu lütfen unutmayın.)

  1. Daha büyük NXP çiplerinde (LPC17xx gibi) kendi kesme işleyicisine sahip birkaç özel kesme pimi (EINTn) vardır. GPIO'ların geri kalanında bir ortak kesinti (EINT3) kullanılmalıdır. Daha sonra hangi pinlerin kesmeyi tetiklediğini görmek için kesme durumu kaydını yoklayabilirsiniz.
  2. LPC11xx'e çok aşina değilim ama GPIO portu başına bir kesinti var gibi görünüyor . Belirli pinleri bulmak için durum kaydını tekrar kontrol etmeniz gerekecektir. Uyandırma kaynağı olarak işlev görebilen 12'ye kadar pin de vardır. Onları genel kesintiler olarak ele geçirip geçiremeyeceğinizden emin değilim (yani muhtemelen sadece uyku durumunda tetiklenirler).
  3. Varsayılan işleyici tablosu 0 adresinde (flaş olan) yerleştirilir. İlk giriş SP yazmacı için sıfırlama değeri, ikincisi sıfırlama vektörü ve geri kalanı diğer istisnalar ve kesme vektörleridir. İlklerden birkaçı (NMI ve HardFault gibi) ARM tarafından sabitlenir, geri kalanı çiplere özgüdür. Vektörleri çalışma zamanında değiştirmeniz gerekirse, RAM'e yeniden eşleyebilirsiniz (önce tabloyu kopyalamanız gerekir). LPC11xx'de yeniden eşleme SRAM (0x10000000) başlangıcına sabitlenir, diğer yongalar daha esnek olabilir.
  4. NVIC, verimli kesme işlemleri için optimize edilmiştir:
    • her kesme için 0-3 programlanabilir öncelik seviyesi. Yüksek öncelikli bir kesinti, düşük öncelikli olanları önler (yuvalama). Yüksek öncelikli kesme işlemi tamamlandığında, düşük öncelikli olanın yürütülmesi devam eder.
    • kesme girişinde işlemci durumunun otomatik olarak istiflenmesi; bu, kesme işleyicilerinin doğrudan C'ye yazılmasına izin verir ve montaj sargılarına olan ihtiyacı ortadan kaldırır.
    • kuyruk zincirleme: durumu tekrar patlatmak ve itmek yerine, bir sonraki bekleyen kesinti derhal ele alınır
    • geç gelen: işlemci durumunu istiflerken daha yüksek önceliğe sahip bir kesinti olursa, önceden beklemede olan yerine hemen yürütülür.

PIC'lere aşina olduğunuzdan, bu Uygulamaya bir göz atın Not: PIC Mikrodenetleyicilerinden Cortex-M3'e Geçiş

M3 hakkında, ancak puanların çoğu M0 için de geçerlidir.


8

Austin ve Igor cevapları yeterince ayrıntılı. Ancak, başka bir şekilde cevaplamak istiyorum, belki yararlı bulursunuz.

LPC11xx (Cortex-M0), GPIO pinleri için 4 seviyeye sahiptir, GPIO0.0 - GPIO0.n arasındaki tüm pinler aynı kesme numarasını paylaşır ve GPIO3.0 - GPIO3.m arasındaki tüm pinler aynı kesme numarasını paylaşır.

LPC11xx'de GPIO kesmesini başlatmak için altı adım vardır

  1. Pim Bağlantı Bloğu Kayıtlarını değiştirerek pim işlevini ayarlayın.
  2. GPIO veri yönü kaydını değiştirerek pin yönünü ayarlayın (varsayılan değer girilir).
  3. Her bir pin için kesmeyi ayarlayın, GPIO kesinti maskesi kayıt GPIOnIE'ye gitmeniz ve bit (pime karşılık gelen) mantık 1'i ayarlamanız gerekir.
  4. GPIO kesinti algılama kayıtlarını GPIOnIBE ve GPIOnIS'i değiştirerek yükselen kenar veya düşen kenar veya her ikisi için kesmeyi ayarlayın.
  5. Kesme kaynağını CMSIS işlevlerini kullanarak Yuvalanmış Vektörlü Kesme Kontrolünde PIO_0 / PIO_1 / PIO_2 / PIO_3'ü etkinleştirin.
  6. CMSIS işlevlerini kullanarak kesme önceliğini ayarlayın.

Kod uygulamaları. İki işleve ihtiyacınız vardır: biri yukarıdaki 6 adımı başlatır ve ikincisi, başlatma kodlarında tanımlanan işleyiciyle aynı ad olması gereken kesme işleyicisidir, startup_LPC11xx.sdosya. İsimler gelmektedir PIOINT0_IRQHandleriçin PIOINT3_IRQHandler. Farklı bir ad kullanırsanız, başlangıç ​​dosyasındaki adları değiştirmeniz gerekir.

/*Init the GPIO pin for interrupt control */
void GPIO_Init(){
    LPC_IOCON-> =..              //Pin configuration register
    LPC_GPIO1->FIODIR = ...      //GPIO Data direction register
    LPC_GPIO1->FIOMASK = ..      //GPIO Data mask register - choose  the right pin
    LPC_GPIO1->GPIOnIE = ..      //Set up falling or rising edge 
    NVIC_EnableIRQ(PIO_1);       //Call API to enable interrupt in NVIC
    NVIC_SetPriority(PriorityN); //Set priority if needed
}


/*Must have the same name as listed in start-up file startup_LPC11xx.s */
void PIOINT1_IRQHandler(void){
   //Do something here
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.