對于Linux這種龐大的操作系統(tǒng),代碼重用性非常重要,所以需要有相關(guān)的機制來提升效率,去除重復(fù)無意義的代碼,尤其是對于驅(qū)動程序,所以就有了platform和INPUT子系統(tǒng)這兩種工作機制。
學(xué)習(xí)視頻地址:【正點原子】STM32MP157開發(fā)板
platform子系統(tǒng)
platform 驅(qū)動框架分為總線、設(shè)備和驅(qū)動??偩€在Linux內(nèi)核提供,不需要我們進(jìn)行考慮,所以只需考慮設(shè)備和驅(qū)動。
因為目前的Linux內(nèi)核都支持設(shè)備樹了,所以platform_device設(shè)備信息都通過設(shè)備樹進(jìn)行描述了,因此只需要在代碼中編寫platform_driver驅(qū)動代碼
Linux驅(qū)動的分離與分層示意圖
GPIO電氣屬性配置
采用的是設(shè)備樹中的pinctrl控制器,在STM32MP1中,pinctrl配置只在platform平臺上被引用。
創(chuàng)建設(shè)備的pinctrl節(jié)點
led_pins_a: gpioled-0 {
pins {
pinmux = <STM32_PINMUX('I', 0, GPIO)>; # 設(shè)置 PI0 復(fù)用為 GPIO 功能。
drive-push-pull; # 設(shè)置 PI0 為推挽輸出。
bias-pull-up; # 設(shè)置 PI0 內(nèi)部上拉。
output-high; # 設(shè)置 PI0 默認(rèn)輸出高電平。
slew-rate = <0>; # 設(shè)置 PI0 的速度為0檔,也就是最慢。
};
};
在設(shè)備樹中創(chuàng)建設(shè)備節(jié)點
gpioled {
compatible = "alientek,led";
pinctrl-names = "default";
status = "okay";
pinctrl-0 = <&led_pins_a>;
led-gpio = <&gpioi 0 GPIO_ACTIVE_LOW>;
};
兼容屬性
// 定義兼容屬性表
static const struct of_device_id led_of_match[] = {
{ .compatible = "alientek,led" }, /* 兼容屬性 */
{ /* Sentinel */ }
};
// 聲明設(shè)備匹配表
MODULE_DEVICE_TABLE(of, led_of_match);
// 定義platform驅(qū)動
static struct platform_driver led_platform_driver = {
.driver = {
.name = "stm32mp1-led",
.of_match_table = led_of_match,
},
.probe = led_probe,
.remove = led_remove,
};
檢查引腳復(fù)用配置
STM32MP1 的一個引腳可以復(fù)用為多種功能,但是在配置設(shè)備樹時,一個引腳只能復(fù)用為一個功能。
檢查GPIO占用
盡管引腳配置上只復(fù)用為了一個功能,但是可能存在該引腳被多個設(shè)備使用的情況,所以需要檢查設(shè)備樹,確保只有一個設(shè)備在使用該GPIO引腳。
linux,default-trigger屬性設(shè)置
這個屬性可以將LED配置為某個特定模式。
backlight:LED 燈作為背光。
default-on:LED 燈打開。
heartbeat:LED 燈作為心跳指示燈,可以作為系統(tǒng)運行提示燈。
disk-activity:LED 燈作為磁盤活動指示燈。
ide-disk:LED 燈作為硬盤活動指示燈。
timer:LED 燈周期性閃爍,由定時器驅(qū)動,閃爍頻率可以修改。
MISC驅(qū)動系統(tǒng)
定位:當(dāng)某些外設(shè)無法進(jìn)行分類的時候就可以使用MISC驅(qū)動。MISC驅(qū)動其實就是最簡單的字符設(shè)備驅(qū)動,通常嵌套在 platform 總線驅(qū)動中,實現(xiàn)復(fù)雜的驅(qū)動。
設(shè)備定義
所有的MISC設(shè)備驅(qū)動的主設(shè)備號都為 10,不同的設(shè)備使用不同的從設(shè)備號。定義一個 MISC 設(shè)備(miscdevice 類型)以后需要設(shè)置 minor、name 和 fops 這三個成員變量。
設(shè)備注冊
int misc_register(struct miscdevice * misc)
設(shè)備注銷
int misc_deregister(struct miscdevice *misc)
input子系統(tǒng)
系統(tǒng)架構(gòu)
input子系統(tǒng)的所有設(shè)備主設(shè)備號都為13,我們在使用 input 子系統(tǒng)處理輸入設(shè)備的時候就不需要去注冊字符設(shè)備,只需要向系統(tǒng)注冊一個input_device即可。
驅(qū)動編寫流程
API函數(shù)
// 申請input_dev結(jié)構(gòu)體變量
struct input_dev* input_allocate_device(void)
// 釋放input_dev結(jié)構(gòu)體變量
void input_free_device(struct input_dev* dev)
// 注冊input_dev
int input_register_device(struct input_dev* dev)
// 注銷input_dev
void input_unregister_device(struct input_dev* dev)
事件類型
初始化(以按鍵為例)文章來源:http://www.zghlxwxcb.cn/news/detail-723987.html
/* 申請設(shè)備內(nèi)存 */
inputdev = input_allocate_device();
inputdev->name = "test_inputdev";
/* 設(shè)置事件和事件值 */
keyinputdev.inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_set_capability(keyinputdev.inputdev, EV_KEY, KEY_0);
/* 注冊設(shè)備 */
input_register_device(inputdev);
上報事件文章來源地址http://www.zghlxwxcb.cn/news/detail-723987.html
/* 通用的事件上報函數(shù) */
void input_event(struct input_dev *dev, unsigned int type,
unsigned int code, int value)
/* 衍生所得的上報函數(shù) */
void input_report_rel(struct input_dev *dev, unsigned int code, int value)
void input_report_abs(struct input_dev *dev, unsigned int code, int value)
void input_report_ff_status(struct input_dev *dev, unsigned int code, int value)
void input_report_switch(struct input_dev *dev, unsigned int code, int value)
void input_mt_sync(struct input_dev *dev)
/* 事件上報完成后,需要用該函數(shù)上報一個同步事件 */
void input_sync(struct input_dev *dev)
到了這里,關(guān)于【嵌入式Linux學(xué)習(xí)筆記】platform設(shè)備驅(qū)動和input子系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!