在sm501的驅動中,暫存器非常多,每個暫存器位域的定義也特別多。 驅動採用了一套非常奇妙的巨集來操作暫存器的位域。覺得有必要總結一下。
1)相關定義
包括3 個方面:暫存器,暫存器位域,暫存器位域的可取值。
其中,暫存器位域的表示用以0為起始索引的 高位:低位 來表示。這點非常重要,因為後面的巨集定義就是利用了其中的冒號,來構造乙個條件操作符。
三種定義在識別符號安排上的關係:暫存器為r,則r中某位域f定義為r_f,則該位域某個值v定義為r_f_v.:
比如:
#define system_ctrl 0x000000
#define system_ctrl_dpms 31:30
#define system_ctrl_dpms_vphp 0
#define system_ctrl_dpms_vphn 1
#define system_ctrl_dpms_vnhp 2
#define system_ctrl_dpms_vnhn 3
2)低層巨集操作
#define _f_start(f) (0 ? f)
#define _f_end(f) (1 ? f)
#define _f_size(f) (1 + _f_end(f) - _f_start(f))
#define _f_mask(f) (((1 << _f_size(f)) - 1) << _f_start(f))
#define _f_normalize(v, f) (((v) & _f_mask(f)) >> _f_start(f))
#define _f_denormalize(v, f) (((v) << _f_start(f)) & _f_mask(f))
其中f 表示位域,v表示位域的值。
_f_start(f) 表示取位域中的起始索引,即冒號右邊的值。展開就是乙個條件操作符。如 _f_start(system_ctrl_dpms) 展開就相當於
(0?31:30) 顯然值為30,正是表示起始索引。 其餘就比較好理解了。
_f_end(f) 表示 位域的結束索引位置。即位域冒號的左邊的值。
_f_size(f) 表示 位域的寬度,也就是包含幾位。
_f_mask(f)為位掩碼,在_f_start(f) 到 _f_end(f)的位為1,其餘為0。
_f_normalize(v, f) 以整數值的方式得到位域的值。位域右移到0開始的位置。
_f_denormalize(v, f)將以整數表示的值放到位域中去的表示。將值左移到位域的位置。
上面這些是底層巨集定義。
3)位域巨集操作:
實際上對位域的操作往往是獲取或設定某暫存器某位域的值。這些巨集定義如下
#define field_get(x, reg, field) /
( /
_f_normalize((x), reg ## _ ## field) /
)
#define field_set(x, reg, field, value) /
( /
(x & ~_f_mask(reg ## _ ## field)) /
| _f_denormalize(reg ## _ ## field ## _ ## value, reg ## _ ## field) /
)
#define field_clear(reg, field) /
( /
~ _f_mask(reg ## _ ## field) /
)
上述三個巨集只返回值,並不修改暫存器。上述巨集定義中,field,value都不是完整的巨集定義名稱,完整的巨集定義名稱是reg_field,reg_field_value。這就是為什麼3個定義要按照這種關係來寫的原因。好處是關係更清晰。**顯得短小。
一般的使用過程 是 使用 field_get獲取值,再使用field_set修改某個位域的值,最後用新值修改暫存器。典型的使用:
void panelplaneenable(void)
這樣做的好處是程式可以只使用暫存器,位域,位域值,和幾個巨集來進行操作。可讀性好,也簡化了程式設計!!
android lcd驅動簡析
對於lcd驅動的分析主要分為三部分 底層硬體結構 framebuffer mipi 底層硬體結構 1 要使一塊lcd正常的顯示文字或影象,不僅需要lcd驅動器,而且還需要相應的lcd控制器。在通常情況下,生產廠商把lcd驅動器與lcd玻璃基板製作在一起,而lcd控制器則是由外部的電路來實現 平台自帶...
位運算 簡析
位運算 在很多系統程式中常要求在位 bit 一級進行運算或處理,c語言提供了位運算的功能,使得c語言也能像組合語言一樣用來編寫系統程式,位運算共有 這六種。1.1.1按位與運算 按位與運算 是雙目運算子。按位運算通常用來對某些位清0 或者 保留某些位,如把a的高8位清0,保留低8位,與作 255運算...
TCP標誌位簡析
tcp標誌位簡析 tcp標誌位 urg 此標誌表示tcp包的緊急指標域 後面馬上就要說到 有效,用來保證tcp連線不被中斷,並且督促中間層裝置要盡快處理這些資料 ack 此標誌表示應答域有效,就是說前面所說的tcp應答號將會包含在tcp資料報中 有兩個取值 0和1,為1的時候表示應答域有效,反之為0...