驅(qū)動(dòng)程序也可以多次實(shí)例化,每次實(shí)例化都可以采用不同的設(shè)置,目標(biāo)設(shè)備可以有不同的I2C從ID,連接到不同的SPI從選擇,或者映射到不同的物理存儲(chǔ)器地址。所有實(shí)例共用同樣的代碼,以便節(jié)省存儲(chǔ)器,但具有各自的數(shù)據(jù)段。
Linux是一種先占式多任務(wù)、多用戶操作系統(tǒng),因此幾乎所有設(shè)備驅(qū)動(dòng)程序和內(nèi)核子系統(tǒng)都允許多個(gè)進(jìn)程(可能由不同的用戶所有)同時(shí)利用設(shè)備。常見的例子有network(網(wǎng)絡(luò))、audio(音頻)或input(輸入)接口。QWERTY鍵盤控制器ADP5588的鍵按下或釋放事件會(huì)被加上時(shí)間戳、排隊(duì)并發(fā)送至所有已打開input vent device(輸入事件設(shè)備)的進(jìn)程。這些事件代碼在所有架構(gòu)上都相同,并且與硬件無關(guān)。讀USB鍵盤與從用戶空間讀取ADP5588并無區(qū)別。事件類型通過代碼加以區(qū)分。鍵盤發(fā)送鍵事件(EV_KEY)、鍵識(shí)別碼以及代表按下或釋放動(dòng)作的某種狀態(tài)值。觸摸屏發(fā)送絕對(duì)坐標(biāo)事件(EV_ABS)以及由x、y和觸摸壓力組成的一個(gè)三元組,鼠標(biāo)則發(fā)送相對(duì)運(yùn)動(dòng)事件(EV_REL)。加速度計(jì)ADXL346在發(fā)送關(guān)于加速度的絕對(duì)坐標(biāo)事件的同時(shí),可以發(fā)送關(guān)于單振或雙振的鍵事件。
某些應(yīng)用中,加速度計(jì)ADXL346產(chǎn)生相對(duì)事件或者發(fā)送特定鍵代碼(特定應(yīng)用設(shè)置),也很有意義。一般而言,定制驅(qū)動(dòng)程序有兩種方式:運(yùn)行時(shí)或編譯時(shí)。
可能在運(yùn)行時(shí)進(jìn)行定制的設(shè)備特性使用模塊參數(shù)和或/sys條目。
實(shí)現(xiàn)特定目標(biāo)
使用開源Linux驅(qū)動(dòng)程序—通過定制實(shí)現(xiàn)特定目標(biāo),對(duì)于編譯時(shí)配置,將特定板和特定應(yīng)用配置排除在主驅(qū)動(dòng)程序文件之外是Linux的慣例,一般將其放入board support ?le(板支持文件)中。
對(duì)于定制板上的設(shè)備(這是嵌入式和基于SoC片上系統(tǒng)硬件的典型現(xiàn)象),Linux使用platform_data指向描述設(shè)備及其如何連到SoC的特定板結(jié)構(gòu)。這可以包括可用端口、不同芯片版本、首選模式、默認(rèn)初始化、引腳的其他作用等。這將能縮小板支持包(BSP),并盡量減少驅(qū)動(dòng)程序中板和應(yīng)用特定的#ifdef。至于哪些可調(diào)變量進(jìn)入platform_data,哪些應(yīng)當(dāng)在運(yùn)行時(shí)具有訪問權(quán),則由驅(qū)動(dòng)程序的作者決定。
數(shù)字加速度計(jì)特性與應(yīng)用具有非常密切的關(guān)系,不同的板和型號(hào)可能具有不同的特性。下例顯示了一組配置選項(xiàng)。這些變量在頭文件adxl34x.h(include/linux/input/adxl34x.h)中有詳細(xì)描述。
Analog Dialogue 44-03, March (2010)
#include
static const struct adxl34x_platform_data
adxl34x_info={
.x_axis_offset=0,
.y_axis_offset=0,
.z_axis_offset=0,
.tap_threshold=0x31,
.tap_duration=0x10,
.tap_latency=0x60,
.tap_window=0xF0,
.tap_axis_control=ADXL_TAP_X_EN | ADXL_TAP_
Y_EN | ADXL_TAP_Z_EN,
.act_axis_control=0xFF,
.activity_threshold=5,
.inactivity_threshold=3,
.inactivity_time=4,
.free_fall_threshold=0x7,
.free_fall_time=0x20,
.data_rate=0x8,
.data_range=ADXL_FULL_RES,
.ev_type=EV_ABS,
.ev_code_x=ABS_X,/*EV_REL*/
.ev_code_y=ABS_Y,/*EV_REL*/
.ev_code_z=ABS_Z,/*EV_REL*/
.ev_code_tap={BTN_TOUCH,BTN_TOUCH,BTN_TOUCH},/*EV_KEY x,y,z */
.ev_code_ff=KEY_F,/* EV_KEY */
.ev_code_act_inactivity=KEY_A,/*EV_KEY*/
.power_mode=ADXL_AUTO_SLEEP|ADXL_LINK,
.fifo_mode=ADXL_FIFO_STREAM,
};
為將設(shè)備與驅(qū)動(dòng)程序相關(guān)聯(lián),“平臺(tái)和總線模型”無需設(shè)備驅(qū)動(dòng)程序來包含其所控制設(shè)備的硬編碼物理地址或總線ID。平臺(tái)和總線模型還能防止資源沖突,大大改善便攜性,并與內(nèi)核的電源管理特性干凈利落地接口。
利用平臺(tái)和總線模型,設(shè)備驅(qū)動(dòng)程序一旦獲得設(shè)備的物理位置和中斷線路,便知道如何控制設(shè)備。該信息在探測(cè)期間作為一個(gè)數(shù)據(jù)結(jié)構(gòu)傳遞給驅(qū)動(dòng)程序。
與PCI或USB設(shè)備不同,I2C或SPI設(shè)備不會(huì)在硬件層次上進(jìn)行枚舉。相反,軟件必須知道每個(gè)I2C/SPI總線段上連接了哪些設(shè)備,以及這些設(shè)備使用什么地址。因此,內(nèi)核代碼必須明確實(shí)例化I2C/SPI設(shè)備。這可以通過多種不同方法實(shí)現(xiàn),具體取決于上下文和要求。不過,最常用的方法是通過總線號(hào)碼聲明I2C/SPI設(shè)備。
當(dāng)I2C/SPI總線是一條系統(tǒng)總線時(shí),這種方法是合適的;許多嵌入式系統(tǒng)正是這種情況,其中每條I2C/SPI總線都有一個(gè)事先已知的號(hào)碼。因此,可以預(yù)先聲明連到該總線的I2C/SPI設(shè)備。這可以利用一個(gè)結(jié)構(gòu)體i2c_board_info/spi_board_info陣列來完成,該陣列通過調(diào)用以下內(nèi)容注冊(cè)i2c_register_board_info()/spi_register_board_info()
static struct i2c_board_info __initdata bfin_ i2c_board_info[] = {#if defined(CONFIG_TOUCHSCREEN_AD7879_I2C)||defined(CONFIG_TOUCHSCREEN_AD7879_I2C_MODULE)
{
I2C_BOARD_INFO("ad7879",0x2F),
.irq=IRQ_PG5,
.platform_data=(void*)&bfin_ad7879_ts_info,
},
#endif
#ifdefined(CONFIG_KEYBOARD_ADP5588)||defined(CONFIG_KEYBOARD_ADP5588_MODULE)
{
I2C_BOARD_INFO("adp5588-keys",0x34),
.irq=IRQ_PG0,
.platform_data=(void*)&adp5588_kpad_data,
},
#endif
#ifdefined(CONFIG_PMIC_ADP5520)||defined(CONFIG_PMIC_ADP5520_MODULE)
{
I2C_BOARD_INFO("pmic-adp5520",0x32),
.irq=IRQ_PG0,
.platform_data=(void*)&adp5520_pdev_data,
},
#endif
#ifefined(CONFIG_INPUT_ADXL34X_I2C)|| defined(CONFIG_INPUT_ADXL34X_I2C_MODULE)
{
I2C_BOARD_INFO("adxl34x", 0x53),
.irq = IRQ_PG0,
.platform_data = (void *)&adxl34x_info,
},
#endif
};
static void __init blackfin_init(void)
{
(...)
i2c_register_board_info(0,bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info));
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
(...)
}
因此,為了啟用這樣一個(gè)驅(qū)動(dòng)程序,只需要編輯板支持文件,將適當(dāng)?shù)臈l目添加至i2c_board_info(spi_board_info)。
還應(yīng)注意到,需在內(nèi)核配置期間選擇驅(qū)動(dòng)程序。驅(qū)動(dòng)程序按照所屬的子系統(tǒng)分類。可在以下位置查找ADXL34x驅(qū)動(dòng)程序:
Device Drivers--->
Input device support --->
[*] Miscellaneous devices --->
<*>Analog Devices ADXL34x Three-Axis
Digital Accelerometer
<*>support I2C bus connection
<*>support SPI bus connection
評(píng)論
查看更多