硬件驅動——I.MX6ULL裸機啟動(3)(按鍵設置及中斷設置

重點:

1.GIC:(Generic??Interrupt??Controller)通用中斷控制器,是ARM架構中用于管理中斷的核心模塊,主要用于現代多核處理器系統。它負責接收,分發并分發中斷請求,減輕CPU負擔,使其專注于計算任務。目前GIC有四個版本,V1~V4,現在只有V2~V4正在大量使用,IMX6ULL搭載的是V2的GIC控制器。

2.協處理器是一種專門用于輔助CPU執行特定任務的硬件模塊,通過分擔CPU的運算負荷來提升系統整體效率

AMR?Cortex??A7內核配備了16個協處理器

3.將異常向量表重映射的原因:默認情況下,異常向量表在低地址(0x00000000),但系統運行時,可能需要把異常向量表放到其他的地址(比如更高的內存地址,放在操作系統或應用程序靈活管理內存空間),這樣能更合理的利用內存,也便于對異常處理程序進行組織和管理。

重映射異常向量表的方法:通過協處理器(CP15)中的相關寄存器(比如向量基地址寄存器),將異常向量表的基地址修改為目標地址,是的處理器在處理異常時,能到新的地址去獲得異常處理程序的入口

一.實現按鍵功能

相關代碼:

#include "key.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "core_ca7.h"void init_key(void)
{IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);   //設置IO復用功能IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF0B0);   //配置該引腳的電氣屬性struct GPIO_Type_t t ={.direction = gpio_input     };init_gpio(GPIO1,18,&t);        //按鍵為輸出方式
}
int key_pressed(void)
{if(read_gpio(GPIO1,18) == 0)    //判斷該引腳是高電平還是低電平,低電平為按下按鍵返回0,高電平為沒按按鍵返回1{return 1;}else{return 0;}}
#ifndef __KEY_H__
#define __KEY_H__
#include "gpio.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"extern void init_key(void);extern int key_pressed(void);
#endif
int main(void)
{enable_clocks();system_interrupt_init();init_beep();init_led();init_key();while(1){delay(0xFFFFF);}return 0;
}

匯編代碼與上一節一樣

二.中斷

1.中斷步驟:

? ? ? ? 1)中斷源發出中斷請求;

? ? ? ? 2)內核檢查是否響應相應中斷以及判斷該中斷是否屏蔽;

? ? ? ? 3)內核檢查中斷的優先級;

? ? ? ? 4)保護現場

? ? ? ? 5)執行中斷服務函數;

? ? ? ? 6)恢復現場

2.GIC中斷控制器

GIC:(Generic??Interrupt??Controller)通用中斷控制器,是ARM架構中用于管理中斷的核心模塊,主要用于現代多核處理器系統。它負責接收,分發并分發中斷請求,減輕CPU負擔,使其專注于計算任務。目前GIC有四個版本,V1~V4,現在只有V2~V4正在大量使用,IMX6ULL搭載的是V2的GIC控制器。

GIC能處理1200個中斷,分為三大類:

1.SPI:共享外設中斷? ? ? ? 32~1019

2.PPI:私有外設中斷,內核與內核之間的通信中斷? ? ? ? 16~31號

3.SGI:軟件產生中斷? ? ? ? 0~15號

IMX6ULL中有160個中斷

IAR:中斷通知寄存器? ? ? ? 將中斷編號傳給內核

EOIR:中斷結束寄存器? ? ? ? 清除中斷

3.協處理器(Techinal手冊)

ARM內核支持16個協處理器,CP0~CP15,

SCTLR:映射異常向量表

VBVR:異常向量的基地址

mrc:用來讀的目標寄存器(CP15)的值放到通用寄存器當中去

mcr:用來將通用寄存器里的值寫到(CP15)目標寄存器當中去

MRC{cond} p15, <opc1>, <Rt>, <CRn>, <CRm>, <opc2>
cond:指令執行的條件碼,就是之前我們使用過的指令條件,eq,lt什么的。如果忽略的話就表
示無條件執行;

p15:表示要讀取的是CP15當中的某個寄存器;

opc1:協處理器要執行的操作碼1,其實就是一個數,要做什么將來查表;

Rt:ARM 目標寄存器,讀出來的數據放到哪個ARM寄存器里。CP15

CRn:CP15 協處理器的目標寄存器,就是你要讀取CP15的哪個寄存器(C0~C15);

CRm:協處理器中附加的目標寄存器或者源操作數寄存器,如果不需要附加信息就將CRm 設置
為 C0,否則結果不可預測。?

opc2:可選的協處理器特定操作碼2,使用時查表。

4.實現的代碼

#include "key.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "core_ca7.h"
#include "interrupt.h"
#include "led.h"
void init_key(void)
{IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);   //設置IO復用功能IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF0B0);   //配置該引腳的電氣屬性struct GPIO_Type_t t ={.direction = gpio_input     };init_gpio(GPIO1,18,&t);        //按鍵為輸出方式GPIO1->ICR2 |= (3 << 4);       //將GPIO1當中的18號引腳設置為下降沿觸發方式  ICR為中斷方式的寄存器GPIO1->IMR |= (1 << 18);       //將GPIO1當中的18號引腳置1,打開18號引腳的中斷屏蔽寄存器     IMR為中斷屏蔽寄存器system_interrupt_register(GPIO1_Combined_16_31_IRQn,key_interrupt_handler);GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);       //打開指定的中斷,該位置打開編號為99的中斷GIC_SetPriority(GPIO1_Combined_16_31_IRQn,0);   //設置中斷優先級為0,即優先級最高
}void key_interrupt_handler(void)
{if((GPIO1->ISR &(1 << 18)) != 0)    //判斷中斷標記寄存器中產生中斷是由GPIO1的18號引腳造成的{led_nor();GPIO1->ISR |= (1 << 18);        //清除中斷標記寄存器}
}
int key_pressed(void)
{if(read_gpio(GPIO1,18) == 0)    //判斷該引腳是高電平還是低電平,低電平為按下按鍵返回0,高電平為沒按按鍵返回1{return 1;}else{return 0;}}
#include "interrupt.h"
#include "MCIMX6Y2.h"
#include "core_ca7.h"static irq_handler_t interrupt_vector_table[160];  //定義一個函數的指針的數組,用來存放中斷void system_interrupt_init(void)
{GIC_Init();     //對GIC控制器進行初始化操作
}void system_interrupt_register(int num, irq_handler_t handler)  //注冊中斷服務函數
{interrupt_vector_table[num] = handler;      
}void system_interrupt_handler(int num)      //中斷服務函數,num為哪一個中斷發出的中斷請求,傳遞其中斷號
{if(interrupt_vector_table[num] != NULL)    //什么原因造成的中斷,該處為中斷編號為99的中斷{interrupt_vector_table[num]();      //調用這個函數的指針數組}}
.global _start_start:ldr pc, =_reset_handlerldr pc, =_undefine_handlerldr pc, =_svc_handlerldr pc, =_prefetch_abort_handlerldr pc, =_data_abort_handlerldr pc, =_reserved_handlerldr pc, =_irq_handlerldr pc, =_fiq_handler_undefine_handler:ldr pc, =_undefine_handler_svc_handler:ldr pc, =_svc_handler_prefetch_abort_handler:ldr pc, =_prefetch_abort_handler_data_abort_handler:ldr pc, =_data_abort_handler_reserved_handler:ldr pc, =_reserved_handler
//在main函數當中初始化irq中斷函數
_irq_handler:subs lr, lr, #4         //通過查表,將鏈接寄存器的值減4(異常狀態返回地址)mrc p15, 4, r1, c15, c0, 0      //將GIC的基地址放到r1當中去add r1, r1, #0x2000         //得到的是C_CTLR的基地址ldr r0, [r1, #0x0C]         //將r1當中的基地址偏移0x0C的地址(C-IAR(發出中斷請求的寄存器))存(讀)到r0寄存器當中stmfd sp!, {r0-r12, lr}     //保護現場stmfd sp!, {r0, r1}         //將r0和r1入棧cps #0x1F                   //切換為system模式stmfd sp!, {lr}             //保護system模式下的lrbl system_interrupt_handler //調用C語言函數ldmfd sp!, {lr}             //恢復system模式下的lrcps #0x12                   //切換為irq模式ldmfd sp!, {r0, r1}         //將第38行的r0和r1出棧str r0, [r1, #0x10]         //將r0當中的值寫到r1偏移0x10的地址上去(C_EOIR(清除中斷標志的寄存器))ldmfd sp!, {r0-r12, pc}^    //恢復現場并且改變模式
_fiq_handler:ldr pc, =_fiq_handler_reset_handler:
/*     mrs r0,cpsrbic r0, r0, #0x1Forr r0, r0, #0x12   //irp(10010)bic r0, r0, #(1 << 7)       //打開irq中斷msr cpsr, r0ldr sp, =0x86000000mrs r0,cpsrbic r0, r0, #0x1Forr r0, r0, #0x1F   //system(11111)msr cpsr, r0ldr sp, =0x84000000
*/cps #0x12           //irq(10010)模式ldr sp, =0x86000000 cps #0x1F           //system(11111)模式cpsie ildr sp, =0x84000000//先通過CP15寫處理器打開設置基地址的選項,再通過映射異常向量表bl _enable_icahce       bl _set_vbar bl _bss_clear b main  //跳轉至main函數當中//處理CP15協處理器(SCTLR)
_enable_icahce:         mrc p15, 0, r0, c1, c0, 0       //讀目標寄存器的值放到通用寄存器r0上bic r0, r0, #(1 << 13)          //根據查表,將SCTLR的第13位清0,此位用來選擇異常向量的基地址,目的是軟件可以通過VBAR來重新設置這個基地址orr r0, r0, #(1 << 12)          //根據查表,將SCTLR的第12位置1,此位用來將指令cache進來打開,默認是關閉狀態mcr p15, 0, r0, c1, c0, 0       //將修改后的目標寄存器的值重新寫入目標寄存器bx lr
//設置異常向量表基地址(VBAR)
_set_vbar:ldr r0, =0x87800000              //將異常向量表的基地址存入到r0當中mcr p15, 0, r0, c12, c0, 0       //根據查表,將r0當中的基地址通過cp15協處理器寫入CBAR當中,當作GIC的基地址bx lr_bss_clear:ldr r0, =__bss_startldr r2, =__bss_end
loop:mov r1, #0str r1, [r0]add r0, r0, #4cmp r0, r2blt loopbx lrfinished:b finished
#include "beep.h"
#include "led.h"
#include "key.h"
#include "core_ca7.h"
#include "interrupt.h"void enable_clocks(void)    //將所有時鐘都打開
{CCM->CCGR0 = 0xFFFFFFFF;CCM->CCGR1 = 0xFFFFFFFF;CCM->CCGR2 = 0xFFFFFFFF;CCM->CCGR3 = 0xFFFFFFFF;CCM->CCGR4 = 0xFFFFFFFF;CCM->CCGR5 = 0xFFFFFFFF;CCM->CCGR6 = 0xFFFFFFFF;
}void delay(unsigned int n)
{while(n--);             //進行延時}int main(void)
{enable_clocks();system_interrupt_init();init_beep();init_led();init_key();while(1){delay(0xFFFFF);}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/100378.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/100378.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/100378.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用deepseek對GPU服務器進行壓力測試

利用 DeepSeek 模型對 GPU 服務器進行壓力測試&#xff0c;核心思路是通過模擬高負載的模型推理 / 微調任務&#xff0c;驗證 GPU 服務器在計算、顯存、網絡等維度的承載能力&#xff0c;同時觀察穩定性與性能瓶頸。以下是具體的測試方案&#xff0c;涵蓋測試環境準備、核心測試…

ARM(7)IMX6ULL 按鍵控制(輪詢 + 中斷)優化工程

一、硬件介紹1. 開關功能定義共 3 個開關&#xff08;兩紅一黃&#xff09;&#xff0c;功能分工明確&#xff1a;中間開關&#xff1a;復位按鈕左邊開關&#xff1a;低功耗按鈕右邊開關&#xff1a;用戶獨立控制的試驗按鍵&#xff08;核心控制對象&#xff09;2. 核心電平邏輯…

【QT隨筆】什么是Qt元對象系統?Qt元對象系統的核心機制與應用實踐

【QT隨筆】什么是Qt元對象系統&#xff1f;Qt元對象系統的核心機制與應用實踐 之所以寫下這篇文章&#xff0c;是因為前段時間自己面試的時候被問到了&#xff01;因此想借此分享一波&#xff01;&#xff01;&#xff01;本文主要詳細解釋Qt元對象系統的概念、作用及實現機制…

從技術視角解析加密貨幣/虛擬貨幣/穩定幣的設計與演進

隨著加密貨幣行情的持續走高&#xff0c;除了資產價值&#xff0c;我想試著從底層程序設計與架構角度解析比特幣、以太坊、穩定幣以及新興公鏈的核心技術方案。作者在2018年設計實施了基于區塊鏈技術的金融項目&#xff0c;并榮獲了國家課題進步獎&#xff0c;對加密貨幣及場景…

[MySQL]Order By:排序的藝術

[MySQL]Order By&#xff1a;排序的藝術 1. 簡介 在數據庫管理中&#xff0c;數據的排序是一項至關重要的操作。MySQL 的 ORDER BY 子句為我們提供了強大而靈活的功能&#xff0c;用于對查詢結果進行排序。無論是按照字母順序排列名稱&#xff0c;還是根據日期或數值進行升序…

【工具代碼】使用Python截取視頻片段,截取視頻中的音頻,截取音頻片段

目錄 ■截取視頻方法 1.下載 ffmpeg-8.0-essentials_build 2.配置到環境變量 3.python代碼 4.運行 5.效果 ■更多 截取視頻中的音頻 截取音頻 Sony的CR3圖片&#xff0c;轉換為JPG ■截取視頻方法 1.下載 ffmpeg-8.0-essentials_build "https://www.gyan.de…

Three.js 平面始終朝向相機

instanceMesh需要讓實例像粒子一樣始終朝向相機 可以如下處理shaderexport const billboarding // billboarding函數的GLSL實現 // 參數: // - position: 頂點動態位置偏移 // - positionLocal: mesh的position // - horizontal: 水平方向是否朝向相機 // - vertical: 垂直方…

旗訊 OCR 識別系統深度解析:一站式解決表格、手寫文字、證件識別難題!

在數字化辦公日益普及的今天&#xff0c;“紙質文檔轉電子”“圖片信息提取” 等需求愈發頻繁&#xff0c;但傳統手動錄入不僅效率低下&#xff0c;還容易出現數據錯誤。近期發現一款實用性極強的工具 —— 旗訊數字 OCR 識別系統&#xff0c;其覆蓋多場景的識別功能、極簡操作…

MissionPlanner架構梳理之(十四)日志瀏覽

概述和目的 Mission Planner 中的日志瀏覽系統提供了加載、查看、分析和解讀 ArduPilot 驅動的飛行器生成的飛行日志的工具。飛行日志包含飛行操作期間記錄的關鍵遙測數據&#xff0c;使用戶能夠查看飛行性能、診斷問題并從過去的飛行中獲取見解。 本頁記錄了日志瀏覽系統的架…

機器學習shap分析案例

在進行數據分析和機器學習時經常用到shap&#xff0c;本文對shap相關的操作進行演示。波士頓數據集鏈接在這里。 SHAP Analysis Guide Set up 導入必要包 import pandas as pd import numpy as np import lightgbm as lgb import matplotlib import matplotlib.pyplot as p…

網絡編程相關函數

1. 套接字操作相關1.1 socketint socket(int domain, int type, int protocol);參數說明int domain協議族&#xff0c;常用 AF_INET&#xff08;IPv4&#xff09;、AF_INET6&#xff08;IPv6&#xff09;int type套接字類型&#xff0c;SOCK_DGRAM&#xff08;UDP&#xff09;、…

ESLint 自定義 Processor(處理器)

ESLint 自定義 Processor&#xff08;處理器&#xff09; &#x1f539; 什么是 Processor&#xff1f; 在 ESLint 中&#xff0c;Processor&#xff08;處理器&#xff09;是一種擴展機制&#xff0c;允許處理非標準 JavaScript/TypeScript 文件。默認情況下&#xff0c;ESLin…

C++語法 | static靜態|單例模式

這里寫目錄標題static 關鍵字靜態局部變量 vs 局部變量靜態全局變量 vs 全局變量靜態成員變量 vs 成員變量靜態成員函數單例模式static 關鍵字 在此之前, 先了解一下 static 關鍵字 靜態局部變量 vs 局部變量 在靜態局部變量中&#xff0c;變量不會在函數調用結束后銷毀&…

KEDA/HPA/VPA 三件套:ABP 后臺作業的事件驅動伸縮

&#x1f680; KEDA/HPA/VPA 三件套&#xff1a;ABP 后臺作業的事件驅動伸縮 &#x1f4da; 目錄&#x1f680; KEDA/HPA/VPA 三件套&#xff1a;ABP 后臺作業的事件驅動伸縮0. TL;DR ?1. 背景與目標 &#x1f3af;2. 架構與協作機制 &#x1f9e9;2.1 系統總覽&#xff08;組…

webRTc 為何深受直播實現的青睞?

WebRTC(Web Real-Time Communication)之所以在直播場景中備受青睞,核心原因在于它天然契合了現代直播對低延遲、實時互動、跨平臺兼容性的核心需求,同時大幅降低了實時音視頻開發的門檻。具體來說,其優勢體現在以下幾個方面: 1. 超低延遲,滿足實時互動需求 傳統直播協…

HarmonyOS迷宮游戲鴻蒙應用開發實戰:從零構建隨機迷宮游戲(初版)

在鴻蒙應用開發中&#xff0c;游戲類應用能很好地鍛煉 UI 布局、狀態管理與邏輯交互能力。本文將以一個隨機迷宮游戲為例&#xff0c;詳細拆解從首頁設計到迷宮生成、角色控制、通關判定的完整開發流程&#xff0c;帶你掌握 ArkUI 框架的核心應用技巧。一、項目整體架構本次開發…

石頭科技出海升級:全球電商業財一體化與OMS實踐

石頭科技作為智能清潔設備領域的獨角獸&#xff0c;2023 年海外收入占比超過 60%&#xff0c;產品銷往全球 60 多個國家。然而&#xff0c;智能硬件出海的復雜性&#xff0c;讓企業在業財管理上面臨前所未有的挑戰。智能硬件業財痛點 產品生命周期管理&#xff1a;研發、生產到…

《URP管線中后處理效果的創新應用與優化實踐》

硬件性能的飛速提升與玩家對畫面品質的高要求形成了相互推動的態勢,而渲染效果作為游戲視覺體驗的核心載體,直接決定了玩家對游戲的第一印象與沉浸感。后處理效果作為URP管線的“點睛之筆”,通過在渲染流程末尾對最終圖像進行二次加工,能夠模擬真實世界的光學現象(如光線散…

【Java 底層】JVM 垃圾回收機制深度剖析:從對象生死判定到收集器實戰

【Java 底層】JVM 垃圾回收機制深度剖析&#xff1a;從對象生死判定到收集器實戰 【Java 底層】JVM 垃圾回收機制深度剖析&#xff1a;從對象生死判定到收集器實戰 Java 之所以被稱為 “開發效率利器”&#xff0c;很大程度上得益于其自動內存管理機制 —— 開發者無需手動分配…

網絡問題排查

網絡連通性測試&#xff1a;ping ip持續性監測&#xff1a;ping -t ipnetstat 可以查看網絡連接狀態&#xff0c;可以看到顯示系統的網絡連接&#xff0c;路由表&#xff0c;接口等信息。netstat -nult 回車-t:顯示的是tcp的連接-u:顯示udp的連接-l:只顯示監聽狀態的端口-n:顯示…