日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 技術(shù)學(xué)院 > 技術(shù)前線
[導(dǎo)讀]內(nèi)核中操作寄存器的方法

內(nèi)核中操作寄存器的方法

由于Linux開(kāi)啟了MMU,所以我們?cè)谠L問(wèn)寄存器時(shí),必須要使用寄存器物理地址對(duì)應(yīng)的虛擬地址來(lái)訪問(wèn)。

1.內(nèi)核提供的讀寫(xiě)接口

利用內(nèi)核提供的寄存器讀寫(xiě)接口會(huì)有較好的可移植性,最重要的是擁有“讀寫(xiě)屏障”

何謂“讀寫(xiě)屏障”?其有何意義?試看以下代碼

#define XXX_SET 0xe0200240

#define XXX_EN 0xe0200244

*((volatile unsigned int *)XXX_SET) = 0xffffffff;

*((volatile unsigned int *)XXX_EN) = 0xffffffff;

現(xiàn)代編譯器為了提高效率,采用的亂序編譯,同樣,現(xiàn)代soc采用的是亂序執(zhí)行。對(duì)于soc和編譯器來(lái)說(shuō),它們判斷這兩個(gè)寄存器設(shè)置的先后順序沒(méi)有邏輯關(guān)系,所以上述兩個(gè)寄存器的設(shè)置順序是不定的。但是某些外設(shè)硬件來(lái)說(shuō),需要先配置再使能

使用內(nèi)核提供的讀寫(xiě)接口,即可保證讀寫(xiě)寄存器的順序不會(huì)改變。其內(nèi)部的實(shí)現(xiàn)機(jī)制是使用了ARM指令集中的各種屏障指令

writel(0xffffffff, XXX_SET);

writel(0xffffffff, XXX_EN);

writel是內(nèi)核提供的寄存器讀寫(xiě)函數(shù)之一,writel代表的是讀long,4字節(jié)(32位),writeb和writew分別代表讀byte1個(gè)字節(jié)和word2個(gè)字節(jié)。其他讀寫(xiě)函數(shù)都以此類推,至于具體參數(shù)格式都可以去看定義

2.動(dòng)態(tài)映射操作寄存器

/*需要的一些定義*/

#define GPJ0_REGBASE 0xe0200240

static void *p_gpj0_base;

/*相關(guān)資源的申請(qǐng)*/

if (!request_mem_region(GPJ0_REGBASE, 8, "gpj0reg")){

return -EINVAL;

}

p_gpj0_base = ioremap(GPJ0_REGBASE, 8);

/*正式操作硬件*/

writel(0x11111111, p_gpj0_base + 0);

writel(0xffffff00, p_gpj0_base + 4);

/*相關(guān)資源的釋放*/

iounmap(p_gpj0_base);

release_mem_region(GPJ0_REGBASE, 8);

這種方法的本質(zhì)其實(shí)還是連續(xù)申請(qǐng)了一長(zhǎng)段內(nèi)存映射,但是沒(méi)有用結(jié)構(gòu)體的方式而是用了基地址+偏移量來(lái)定位地址,然后內(nèi)核提供的寄存器讀寫(xiě)接口通過(guò)這個(gè)地址來(lái)操作寄存器

首先定義需要用到的物理基地址,比如我們要操作GPJ0相關(guān)的寄存器,那么定義GPJ0的物理基地址#define GPJ0_REGBASE 0xe0200240。此外,我們還需要定義一個(gè)指向虛擬基地址的指針,注意類型最好是void *,具體原因在后面講述

動(dòng)態(tài)映射涉及到虛擬地址的申請(qǐng)。任何關(guān)于資源的申請(qǐng)和釋放,順序必須要符合“倒影式結(jié)構(gòu)”,這里也不例外,操作順序是 request_mem_region 申請(qǐng)-> ioremap 建立映射-> 寄存器操作 -> iounmap 解除映射-> release_mem_region 釋放申請(qǐng)。一般來(lái)說(shuō),申請(qǐng)和釋放操作分別放在open和release函數(shù)內(nèi)比較好

記得申請(qǐng)的時(shí)候長(zhǎng)度設(shè)置為自己需要的寄存器量占的地址大小

最值得注意的是指針的加法,前面說(shuō)到虛擬基地址指針應(yīng)該定義為void 。原因是這樣就能直接加上地址偏移量了。比如+4就是定位到偏移量為4的地址處。但是如果基地址指針應(yīng)該定義為unsigned int ,那么偏移量就不能直接加上去了因?yàn)閡nsigned int *類型的指針+1,其實(shí)就相當(dāng)于地址值+4

3. 結(jié)構(gòu)體動(dòng)態(tài)映射操作寄存器

/*需要的一些定義*/

#define GPJ0_REGBASE 0xe0200240

struct GPJ0_REG{

volatile unsigned int gpj0con;

volatile unsigned int gpj0dat;

};

struct GPJ0_REG *p_gpj0_str;

/*相關(guān)資源的申請(qǐng)*/

if (!request_mem_region(GPJ0_REGBASE, sizeof(struct GPJ0_REG), "gpj0reg")){

return -EINVAL;

}

p_gpj0_str = ioremap(GPJ0_REGBASE, sizeof(struct GPJ0_REG));

/*正式操作硬件*/

writel(0x11111111, &(p_gpj0_str->gpj0con));

writel(0xffffff00, &(p_gpj0_str->gpj0dat));

/*相關(guān)資源的釋放*/

iounmap(p_gpj0);

release_mem_region(GPJ0_REGBASE, sizeof(struct GPJ0_REG));

這種以結(jié)構(gòu)體為單位操作的方法,適用于一大塊地址連續(xù)的寄存器申請(qǐng)動(dòng)態(tài)映射

首先定義需要的物理基地址,比如我們要操作GPJ0相關(guān)的寄存器,那么定義GPJ0的物理基地址#define GPJ0_REGBASE 0xe0200240。然后定義一個(gè)結(jié)構(gòu)體以及指向它的指針,由于把需要的寄存器按照地址的順序放進(jìn)去。比如我們這里gpj0con和gpj0dat兩個(gè)連續(xù)的寄存器,就能封裝成一個(gè)結(jié)構(gòu)體(大小為2*32bit=8字節(jié))

動(dòng)態(tài)映射涉及到虛擬地址的申請(qǐng)。任何關(guān)于資源的申請(qǐng)和釋放,順序必須要符合“倒影式結(jié)構(gòu)”,這里也不例外,操作順序是 request_mem_region 申請(qǐng)-> ioremap 建立映射-> 寄存器操作 -> iounmap 解除映射-> release_mem_region 釋放申請(qǐng)。 一般來(lái)說(shuō),申請(qǐng)和釋放操作分別放在open和release函數(shù)內(nèi)比較好

申請(qǐng)映射的時(shí)候,通過(guò)把映射地址長(zhǎng)度設(shè)成結(jié)構(gòu)體的長(zhǎng)度,這樣就能一步到位,申請(qǐng)到一整片寄存器的映射地址了

值得注意的是,當(dāng)我們把ioremap返回的指針賦給我們的結(jié)構(gòu)體指針時(shí),我們的結(jié)構(gòu)體的地址與寄存器的地址重合了,也就是說(shuō)結(jié)構(gòu)體里的元素就相當(dāng)于是寄存器了。我們直接給元素賦值就相當(dāng)于給寄存器賦值!!!

這樣相當(dāng)方便,由此一來(lái),似乎也理解了stm32標(biāo)準(zhǔn)庫(kù)中為什么通過(guò)結(jié)構(gòu)體指針訪問(wèn)寄存器。不得不說(shuō)與這里有異曲同工之妙

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除( 郵箱:macysun@21ic.com )。
換一批
延伸閱讀

在工業(yè)控制、音頻處理等高性能嵌入式場(chǎng)景中,某電機(jī)驅(qū)動(dòng)項(xiàng)目通過(guò)混合使用寄存器操作與CMSIS-DSP庫(kù),將PID控制周期從120μs縮短至38μs,系統(tǒng)響應(yīng)速度提升3倍。本文將揭秘這種"底層+高層"混合編程模式的核心技巧。

關(guān)鍵字: HAL STM32 寄存器

Linux驅(qū)動(dòng)寄存器操作是硬件交互的核心環(huán)節(jié)。然而,多核處理器架構(gòu)、中斷異步性以及編譯器優(yōu)化等因素,可能導(dǎo)致寄存器訪問(wèn)出現(xiàn)競(jìng)態(tài)條件(Race Condition)和內(nèi)存亂序(Memory Reordering)問(wèn)題。這些...

關(guān)鍵字: Linux驅(qū)動(dòng) 寄存器

在嵌入式系統(tǒng)開(kāi)發(fā)中,寄存器操作是控制硬件外設(shè)(如GPIO、UART、SPI)的核心環(huán)節(jié)。傳統(tǒng)方法通過(guò)直接讀寫(xiě)寄存器地址(如*(volatile uint32_t *)0x40021000)實(shí)現(xiàn)控制,但存在可讀性差、易出錯(cuò)...

關(guān)鍵字: 硬件描述語(yǔ)言 寄存器

在資源受限的嵌入式系統(tǒng)中,C語(yǔ)言的位操作不僅是硬件控制的核心工具,更是實(shí)現(xiàn)內(nèi)存壓縮與性能優(yōu)化的關(guān)鍵技術(shù)。通過(guò)直接操作寄存器位域,開(kāi)發(fā)者能夠以極低的資源開(kāi)銷完成復(fù)雜功能,同時(shí)顯著減少內(nèi)存占用。本文將結(jié)合實(shí)戰(zhàn)案例,解析位操作...

關(guān)鍵字: 嵌入式C語(yǔ)言 寄存器

在嵌入式系統(tǒng)開(kāi)發(fā)中,DMA(直接內(nèi)存訪問(wèn))控制器作為硬件加速的核心模塊,通過(guò)獨(dú)立于CPU的數(shù)據(jù)搬運(yùn)能力顯著提升系統(tǒng)性能。以STM32H7系列為例,其雙DMA控制器(各含8通道)可實(shí)現(xiàn)高達(dá)480MHz總線頻率下的數(shù)據(jù)傳輸,...

關(guān)鍵字: 驅(qū)動(dòng)開(kāi)發(fā) DMA 寄存器

在嵌入式系統(tǒng)開(kāi)發(fā)中,硬件抽象層(HAL)通過(guò)隔離底層硬件細(xì)節(jié)與上層應(yīng)用邏輯,成為實(shí)現(xiàn)跨平臺(tái)移植的核心設(shè)計(jì)模式。本文以STM32與NXP LPC系列MCU為例,系統(tǒng)闡述寄存器操作封裝方法與移植優(yōu)化策略。

關(guān)鍵字: 硬件抽象層 HAL 寄存器

在物聯(lián)網(wǎng)、工業(yè)自動(dòng)化和醫(yī)療診斷等領(lǐng)域的快速發(fā)展中,高精度逐次逼近寄存器(SAR)模數(shù)轉(zhuǎn)換器(ADC)已成為信號(hào)采集系統(tǒng)的核心組件。這類器件以中等速度(kSPS至MSPS量級(jí))和中等分辨率(8-18位)著稱,能效比優(yōu)異,廣...

關(guān)鍵字: ADC 寄存器

本文介紹了一款突破性的精密開(kāi)關(guān)產(chǎn)品。這款產(chǎn)品旨在徹底化解需要高通道密度與高精度的印刷電路板(PCB)設(shè)計(jì)和電子測(cè)量系統(tǒng)所面臨的挑戰(zhàn)。這款開(kāi)關(guān)采用創(chuàng)新的無(wú)源元件共封裝方法,并具備直通引腳特性,不僅能顯著優(yōu)化PCB空間利用率...

關(guān)鍵字: 電路板 導(dǎo)通電阻 寄存器

通過(guò)更精確、更高能效的功率監(jiān)測(cè),使得注重功耗和電池續(xù)航的設(shè)計(jì)可在典型工作條件下更長(zhǎng)時(shí)間運(yùn)行

關(guān)鍵字: 數(shù)字功率監(jiān)測(cè)器 電池 寄存器

2025年11月11日,致力于亞太地區(qū)市場(chǎng)的國(guó)際領(lǐng)先半導(dǎo)體元器件分銷商---大聯(lián)大控股宣布,其旗下世平推出基于易沖半導(dǎo)體(ConvenientPower)CPSQ5453和CPSQ5352芯片的汽車(chē)矩陣式大燈方案。

關(guān)鍵字: LED 控制器 寄存器
關(guān)閉