arm中GPIO巨集的分析

2021-05-23 04:53:25 字數 4632 閱讀 4483

linux核心標頭檔案中關於s3c2410 gpio的巨集

一、gpio暫存器定義

1.#define gpcon(x)  __reg2(0x56000000, (x) * 0x10) 

這句是定義2410的gpio的控制暫存器,注意:__reg2的引數是暫存器的實體地址,這個實體地址經_reg2巨集轉換為虛擬位址,對照2410的手冊可以得到一下對應關係:

gpcon(1) ------ port a  0x56000000

gpcon(2) ------ port b  0x56000010

gpcon(3) ------ port c  0x56000020

.          .          .        .

.          .          .        .

.          .          .        .

gpcon(8) ------ port h  0x56000070

2.#define gpdat(x)  __reg2(0x56000004, (x) * 0x10)

這句是定義2410的gpio的資料暫存器,定義方法同gpcon巨集。

gpdat(1) ------ port a  0x56000004

gpdat(2) ------ port b  0x56000014

gpdat(3) ------ port c  0x56000024

.          .          .        .

.          .          .        .

.          .          .        .

gpdat(8) ------ port h  0x56000074

3.#define gpup(x)      __reg2(0x56000008, (x) * 0x10)

這句是定義2410的gpio的上拉電阻遮蔽/啟用暫存器,定義方法同gpcon巨集。

gpup(1) ------ port a  0x56000008

gpup(2) ------ port b  0x56000018

gpup(3) ------ port c  0x56000028

.          .          .        .

.          .          .        .

.          .          .        .

gpup(8) ------ port h  0x56000078

二、gpio埠號定義

以gpio_g12來說明在核心標頭檔案$(kernel_include)/asm-arm/arch/s3c2410.h中是如何來定義io port的埠號的。定義gpio埠主要涉及到以下幾個巨集:

#define make_gpio_num(p, o)        ( (p 

(o #define gpio_g12              make_gpio_num(portg_ofs, 12)

gpio_port_shiftt值為8,代表gpio組號在整個gpio埠號(如gpio_g12)欄位中的位移

gpio_ofs_shift值為0,代表gpio組內偏移號在整個gpio埠號(如gpio_g12)欄位中的位移

s3c2410有117個多功能input/output port pins。分為以下八組:

— port a (gpa): 23-output port                    #define porta_ofs                0

— port b (gpb): 11-input/output port              #define portb_ofs                1

— port c (gpc): 16-input/output port              #define portc_ofs            2

— port d (gpd): 16-input/output port              #define portd_ofs                3

— port e (gpe): 16-input/output port                #define porte_ofs          4

— port f (gpf): 8-input/output port                #define portf_ofs          5

— port g (gpg): 16-input/output port              #define portg_ofs            6

— port h (gph): 11-input/output port                #define porth_ofs          7

gpg12屬於g組,組內偏移為12,從上述兩個巨集定義中,我們可以很清楚地看出gpio_g12結構:

圖1  gpio埠號結構圖

埠一共有8組,從上面的巨集定義可以看出,埠組號p的範圍:0~7。而組內偏移各組不盡相同,port a有23個輸出口,因此它的組內偏移o為0~22,port g有16個io口,它的組內偏移o為0~15,其他組的gpio以此類推。

三、write_gpio_bit(x,v)巨集分析

write_gpio_bit巨集傳入兩個引數,第乙個為gpio埠號,如gpio_g12;第二個引數為1或0,為相應io口設定高電平或低電平輸出。具體巨集展開如下:

#define write_gpio_bit(x, v) / ()

grab_port巨集的引數是gpio埠號,功能是從gpio埠號中解析出組號,具體定義如下:

#define grab_port(x)              (((x) & gpio_port_mask) >> gpio_port_shiftt)

其中gpio_port_mask是組號的掩碼,值為0x0000ff00,從圖1中也可看出。

grab_ofs巨集和grab_port類似,它的功能是從gpio埠號中解析出組內偏移:

#define grab_ofs(x)            (((x) & gpio_ofs_mask) >> gpio_ofs_shift)

其中偏移值掩碼gpio_ofs_mask=0x000000ff。

現在我們結合上述說明來分析write_gpio_bit(gpio_g12,1)這條語句:由gpio_g12的巨集定義可計算出其值為0x0000060c,grab_port(gpio_g12)解析得到所操作的io屬於g組,組號為6;grab_ofs(gpio_g12)解析得到此io口為g組的第12個引腳(從0開始算起),為gpg12,表示式值為12。則write_gpio_bit(gpio_g12,1)等價於下面兩條語句:

gpdat(6) &= ~(0x112);  //gpgdat暫存器第12位清零

gpdat(6) | = 112;      // 向gpgdat暫存器第12位寫入『1』

到此,我們知道了write_gpio_bit(gpio_g12,1)這條語句是將gpg12這個引腳拉成高電平。

四、set_gpio_ctrl(x)巨集分析

#define set_gpio_ctrl(x) /

({ gpcon(grab_port((x))) &= ~(0x3 

gpcon(grab_port(x)) |= (grab_mode(x) 

gpup(grab_port((x))) &= ~(1 

gpup(grab_port((x))) |= (grab_pullup((x)) 

完成了對write_gpio_bit巨集的分析,現在來看set_gpio_ctrl就很簡單了!在它的巨集展開中只多了grab_mode(x)和 grab_pullup(x)分別表示從引數x中解析出io口的模式和使能/遮蔽此埠的上拉電阻。值得注意的是set_gpio_ctrl的引數x不僅僅表示gpio埠號,其高16位還帶有模式狀態和上拉電阻控制資訊,引數x的結構如下圖:

圖2 set_gpio_ctrl的引數字段結構圖

低16位即為前面所述的gpio的埠號,高16位中的r欄位用來遮蔽/使能io口的上拉電阻功能。r=0,上拉電阻使能;r=1,上拉電阻失效。m欄位用來設定io口的工作模式,m=0,io口為輸入埠;m=1,io口為輸出埠;m=2,可選功能1;m=3,可選功能2。

set_gpio_ctrl巨集就是通過寫相應gpio所在組的gpxcon(x為a~h)的相應位來設定io口模式(gpacon每乙個位控制乙個io口,而gpbcon~gphcon都是兩個位控制乙個io口的模式),通過寫gpxup(x為a~h)來決定是否啟用上拉電阻。典型的set_gpio_ctrl呼叫方式如下:

set_gpio_ctrl(gpio_mode_out | gpio_pullup_dis | gpio_g12);

這條語句是將gpg12設定成輸出模式,並且不使用埠的上拉電阻。

五、結束

以上主要結合《s3c2410x 32-bit risc microprocessor user's manual》分析了$(linux_kernel_include)/asm-arm/arch/s3c2410.h中所定義的對2410gpio進行操作的幾個巨集,除了文中提及的幾個巨集,除此還有read_gpio_bit(x)、read_gpio_reg(x) 、write_gpio_reg(x, v)等,實現方法和上述類似,在此不再一一贅述! 

arm 彙編中的巨集

巨集定義用乙個單個的有意義的名字來來代替乙個 塊,避免重複乙個 塊好多次 macro label testandbranch dest,reg,cc label cmp reg,0 b cc dest mend 在macro偽指令之後是乙個巨集的原型語句,巨集的原型語句定義了你用來呼叫巨集的名字 t...

ARM 的巨集定義

macro 巨集定義開始 mov pc lr 巨集的名字 thumbcode 表示在thumb工作狀態 bx lr 分支到 thumb lr mov pc,lr 把lr 儲存到pc指標 mend 巨集定義結束 arm處理器有兩種工作狀態 1.arm 32位 這種工作狀態下執行字對準的arm指令 2....

JMVC中的巨集 macros h分析

說明 1.ot表示exp true時執行,of表示exp false時執行 2.nok表示exp m nok時執行 3.m nok和m nerr都屬於err class類 4.巨集的第乙個引數是表示式exp,如果有第二個引數的話,第二個引數為retval,用來做返回值 表1 macros.h巨集定義...