該博客文章以MKL15Z4系列單片機為例,參考文檔均來自NXP官方提供的芯片用戶手冊和數據手冊;所使用的的開發環境是MCUXpresso。
一、簡單的介紹
首先請看兩張截圖:
一張是截取於單片機工程的驅動文件內容,另一張截取於芯片用戶手冊。通過對照我們不難發現標題中所說的NMI_Handler正是不可屏蔽中斷,簡稱NMI。
在程序中NMI的實現函數也有定義,在芯片驅動函數中該函數是一個弱定義,表示允許用戶在其他地方定義一個該函數,具體實現如下所示:
繼續查看芯片用戶手冊,可以找到這樣一句話,也是對NMI的解釋:
看完這段話的解釋似乎單片機有一個引腳能通過低電平觸發NMI中斷,於是我們就查一下有沒有這個引腳,查找的結果如下圖所示:
NMI對外的確有一個引腳與之相關聯,該引腳的默認功能就是NMI。
總結以上信息,我們可以知道,當我們使用該引腳用作其它功能的時候,如果把NMI引腳在電路上接地,程序在啟動的時候就會觸發NMI中斷,從而進入到NMI_Handler函數中去(如果是把該引腳復用為其它功能再輸入低電平是不會觸發NMI中斷的)。
二、如何解決不能直接在NMI引腳上接地的問題
當我們需要在電路設計上接地的時候,需要關閉NIM中斷,接下來我們看下面截圖:
這是FOPT(flash操作寄存器)寄存器的信息,默認的時候NMI中斷是打開的,如果想關閉該中斷需要我們把NMI_DIS位置0。我們都知道NMI屬於內部中斷,通常芯片廠商只給我們提供了關閉外部中斷的API函數,關閉內部中斷的基本沒有提供,那么我們該如何寫該寄存器的值,從而關閉NMI中斷?因為編譯環境的不同,筆者這里只記錄自己使用的編譯環境關NMI中斷的方法,對於使用不同編譯環境的可以以此作為參考!
查看官方提供的寄存器的定義文件中有沒有關於FOPT寄存器的定義;
這里有一處有關於FOPT寄存器的定義,但是該地址是從0x40020000開始的,而我使用的單片機FLASH的地址范圍是0x0--0x20000,很顯然該地址的內容我們是沒法通過程序改的。繼續搜索后面還一處有關FOPT的定義,如下圖所示:
當看到這些內容后,我知道這正是我要找的內容,為了進一步證明我的判斷我在用戶手冊上找到了這樣一些內容,而這些描述和我在單片機的驅動文件中看到的一段程序是相吻合的:
我想此時就是你也應該知道該如何屏蔽NMI中斷了,沒錯就是直接更改如下圖圈起來的地方,把0xFFFFFFFE改成0xFFFFFBFE,即禁止NMI中斷。
有些人可能會有疑問為何不在main函數中操作寄存器更改?我只能說這樣是行不通的,NMI屬於內部中斷,並且默認是使能的,當你的NMI引腳接地,在你還沒進入main函數中就會因檢測到低電平觸發NMI中斷,
#endif