日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

zynq linux内核驱动编写,【原创】Linux下驱动Zynq GPIO (Switch、button、led)

發布時間:2025/3/15 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 zynq linux内核驱动编写,【原创】Linux下驱动Zynq GPIO (Switch、button、led) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

版權聲明:

本文由電子技術應用博主“cuter”發布。歡迎轉載,但不得擅自更改博文內容,也不得用于任何盈利目的。轉載時不得刪除作者簡介和作者單位簡介。如有盜用而不說明出處引起的版權糾紛,由盜用者自負。

博客官方地址:

1硬件設計:

1.1) Vivado Block Design

1.1.1)設計自主AXI-Lite IP核

關鍵邏輯如下:

下圖所示的是寄存器讀操作,主要目的是為了讀取led、switch和button的狀態。這里并沒有做任何處理,對于button而言,可以利用硬件進行預處理之后,將結果傳遞給軟件,這樣可以減少軟件工作量。

下圖所示的邏輯用于將寄存器內的值送至led引腳。

1.1.2)添加IP核至block design

完成后的block design如下圖所示。

1.1.3)編寫約束文件

led、switch和button所用的引腳都需要約束。使用Run Automation的時候,Vivado會幫助完成約束,我們自主IP暫時未實現Run Automation功能,所以要手動約束。約束代碼如下:

#NET LD0 ? ? ? ? ? LOC = T22 ?| IOSTANDARD=LVCMOS33; ?# "LD0"

set_property PACKAGE_PIN T22 [get_ports {zed_led[0]}]

set_property IOSTANDARD LVCMOS33 [get_ports {zed_led[0]}]

#NET LD1 ? ? ? ? ? LOC = T21 ?| IOSTANDARD=LVCMOS33; ?# "LD1"

set_property PACKAGE_PIN T21 [get_ports {zed_led[1]}]

set_property IOSTANDARD LVCMOS33 [get_ports {zed_led[1]}]

#NET LD2 ? ? ? ? ? LOC = U22 ?| IOSTANDARD=LVCMOS33; ?# "LD2"

set_property PACKAGE_PIN U22 [get_ports {zed_led[2]}]

set_property IOSTANDARD LVCMOS33 [get_ports {zed_led[2]}]

#NET LD3 ? ? ? ? ? LOC = U21 ?| IOSTANDARD=LVCMOS33; ?# "LD3"

set_property PACKAGE_PIN U21 [get_ports {zed_led[3]}]

set_property IOSTANDARD LVCMOS33 [get_ports {zed_led[3]}]

#NET LD4 ? ? ? ? ? LOC = V22 ?| IOSTANDARD=LVCMOS33; ?# "LD4"

set_property PACKAGE_PIN V22 [get_ports {zed_led[4]}]

set_property IOSTANDARD LVCMOS33 [get_ports {zed_led[4]}]

#NET LD5 ? ? ? ? ? LOC = W22 ?| IOSTANDARD=LVCMOS33; ?# "LD5"

set_property IOSTANDARD LVCMOS33 [get_ports {zed_led[5]}]

set_property PACKAGE_PIN W22 [get_ports {zed_led[5]}]

#NET LD6 ? ? ? ? ? LOC = U19 ?| IOSTANDARD=LVCMOS33; ?# "LD6"

set_property PACKAGE_PIN U19 [get_ports {zed_led[6]}]

set_property IOSTANDARD LVCMOS33 [get_ports {zed_led[6]}]

#NET LD7 ? ? ? ? ? LOC = U14 ?| IOSTANDARD=LVCMOS33; ?# "LD7"

set_property IOSTANDARD LVCMOS33 [get_ports {zed_led[7]}]

set_property PACKAGE_PIN U14 [get_ports {zed_led[7]}]

#NET SW0 ? ? ? ? ? LOC = F22 ?| IOSTANDARD=LVCMOS18; ?# "SW0"

set_property PACKAGE_PIN F22 [get_ports {zed_sw[0]}]

set_property IOSTANDARD LVCMOS18 [get_ports {zed_sw[0]}]

#NET SW1 ? ? ? ? ? LOC = G22 ?| IOSTANDARD=LVCMOS18; ?# "SW1"

set_property PACKAGE_PIN G22 [get_ports {zed_sw[1]}]

set_property IOSTANDARD LVCMOS18 [get_ports {zed_sw[1]}]

#NET SW2 ? ? ? ? ? LOC = H22 ?| IOSTANDARD=LVCMOS18; ?# "SW2"

set_property PACKAGE_PIN H22 [get_ports {zed_sw[2]}]

set_property IOSTANDARD LVCMOS18 [get_ports {zed_sw[2]}]

#NET SW3 ? ? ? ? ? LOC = F21 ?| IOSTANDARD=LVCMOS18; ?# "SW3"

set_property PACKAGE_PIN F21 [get_ports {zed_sw[3]}]

set_property IOSTANDARD LVCMOS18 [get_ports {zed_sw[3]}]

#NET SW4 ? ? ? ? ? LOC = H19 ?| IOSTANDARD=LVCMOS18; ?# "SW4"

set_property PACKAGE_PIN H19 [get_ports {zed_sw[4]}]

set_property IOSTANDARD LVCMOS18 [get_ports {zed_sw[4]}]

#NET SW5 ? ? ? ? ? LOC = H18 ?| IOSTANDARD=LVCMOS18; ?# "SW5"

set_property PACKAGE_PIN H18 [get_ports {zed_sw[5]}]

set_property IOSTANDARD LVCMOS18 [get_ports {zed_sw[5]}]

#NET SW6 ? ? ? ? ? LOC = H17 ?| IOSTANDARD=LVCMOS18; ?# "SW6"

set_property PACKAGE_PIN H17 [get_ports {zed_sw[6]}]

set_property IOSTANDARD LVCMOS18 [get_ports {zed_sw[6]}]

#NET SW7 ? ? ? ? ? LOC = M15 ?| IOSTANDARD=LVCMOS18; ?# "SW7"

set_property PACKAGE_PIN M15 [get_ports {zed_sw[7]}]

set_property IOSTANDARD LVCMOS18 [get_ports {zed_sw[7]}]

#NET BTNC ? ? ? ? ?LOC = P16 ?| IOSTANDARD=LVCMOS18; ?# "BTNC"

set_property IOSTANDARD LVCMOS18 [get_ports {zed_btn[0]}]

set_property PACKAGE_PIN P16 [get_ports {zed_btn[0]}]

# BTNU

set_property IOSTANDARD LVCMOS18 [get_ports {zed_btn[1]}]

set_property PACKAGE_PIN T18 [get_ports {zed_btn[1]}]

# BTND

set_property IOSTANDARD LVCMOS18 [get_ports {zed_btn[2]}]

set_property PACKAGE_PIN R16 [get_ports {zed_btn[2]}]

# BTNL

set_property IOSTANDARD LVCMOS18 [get_ports {zed_btn[3]}]

set_property PACKAGE_PIN N15 [get_ports {zed_btn[3]}]

# BTNR

set_property IOSTANDARD LVCMOS18 [get_ports {zed_btn[4]}]

set_property PACKAGE_PIN R18 [get_ports {zed_btn[4]}]

1.1.4)生成bitstream

1.2)制作BOOT.bin

1.3)修改dts文件

小改動,為簡單起見,保持和驅動程序中的設備名稱一致。IP的物理地址一定要改!

2驅動設計:

2.1) digilent驅動學習

首先,姑且不管每個函數的具體作用,我們將驅動程序的框架剝離出來進行分析,這樣程序結構更加清晰。

2.1.1) platform_driver成員函數

//設備的驅動:platform_driver這個結構體中包含probe()、remove()、shutdown()、suspend()、resume()函數,通常也需要由驅動實現。

struct platform_driver?{

int?(*probe)(struct platform_device?*);

int?(*remove)(struct platform_device?*);

void?(*shutdown)(struct platform_device?*);

int?(*suspend)(struct platform_device?*,?pm_message_t state);

int?(*suspend_late)(struct platform_device?*,?pm_message_t state);

int?(*resume_early)(struct platform_device?*);

int?(*resume)(struct platform_device?*);

struct pm_ext_ops?*pm;

struct device_driver driver;

};

驅動程序對platform_driver進行初始化的代碼:

/* platform driver structure for mygpio driver */

static struct platform_driver mygpio_driver =

{

.driver =

{

.name = DRIVER_NAME,

.owner = THIS_MODULE,

.of_match_table = mygpio_of_match

},

.probe = mygpio_probe,

.remove = __devexit_p(mygpio_remove),

.shutdown = __devexit_p(mygpio_shutdown)

};

這些函數的命名本身具有一定的自明性,此段代碼進一步闡明了probe()、remove()和shutdown()函數的作用,具體每個函數的作用可以參考函數體前面的注釋,寫得很詳細。

2.1.2)文件操作函數

關鍵代碼:

static const struct file_operations proc_mygpio_operations = {

.open = proc_mygpio_open,

.read = seq_read,

.write = proc_mygpio_write,

.llseek = seq_lseek,

.release = single_release

};

文件操作深究起來,也能獨立成文了,對于字符設備而言,要提供的主要入口有:open()、release()、read()、write()、ioctl()、llseek()、poll()等,這里簡單說一下用到的幾個函數。

loff_t (*llseek) (struct file *, loff_t, int);

llseek方法用作改變文件中的當前讀/寫位置,并且新位置作為(正的)返回值。

ssize_t (*read) (struct file * filp, char __user * buffer, size_t??? size , loff_t *? p);

這個函數用來從設備中獲取數據。

ssize_t (*write) (struct file *? filp, const char __user *?? buffer, size_t? count, loff_t * ppos);

發送數據給設備。

int (*open) (struct inode * inode , struct file *? filp ) ;

對設備文件進行open()系統調用時,將調用驅動程序的open()函數。該函數主要作用是確定硬件處在就緒狀態、驗證次設備號的合法性、控制使用設備的進程數、根據執行情況返回狀態量等。

int (*release) (struct inode *, struct file *);

release()函數在文件結構被釋放時引用這個操作,當最后一個打開設備的用戶進程執行close()系統調用的時候,內核將調用驅動程序release()函數。release()函數的主要任務是清理未結束的輸入輸出操作,釋放資源,用戶自定義排他標志的復位等。

2.2)驅動修改

名字什么的就不多說了,必然要改的,最大的改動在于proc_xxxx_show(),添加了寄存器讀取操作,具體代碼如下:

static int proc_mygpio_show(struct seq_file *p, void *v)

{

u32 mygpio_value;

mygpio_value = ioread32(base_addr);// read out data

seq_printf(p, "led = 0x%x ", mygpio_value);

mygpio_value = ioread32(base_addr+0x01);// read out data

seq_printf(p, "switch = 0x%x ", mygpio_value);

mygpio_value = ioread32(base_addr+0x02);// read out data

seq_printf(p, "button = 0x%x ", mygpio_value);

mygpio_value = ioread32(base_addr+0x03);// read out data

seq_printf(p, "reg3 = 0x%x ", mygpio_value);

return 0;

}

Ps~關于這塊,我在想,既然修改的地方這么具有規律性,那么是不是能夠設計出一種方法自動創建驅動程序模板,從而可以把精力集中在讀寫函數的實現上來?

3測試結果:

開關這塊稍微有點問題:bit3狀態讀取結果始終為1,改變sw位置無效,具體原因待查。Button和led正常(測試button時,長按5個按鍵中間一個BTNC)。

附1:錯誤筆記

正所謂無知者無畏,在沒有完全掌握一些知識就妄下定論,是不負責任的,以后要多注意。

上一篇博文提到:“這里發現一點小問題,初始化proc_myled_opertaions.read時使用了seq_read,但在驅動程序里定義的讀函數卻是proc_myled_show,在實際使用時,讀led狀態也是失敗的。所以這里的初始化應該是有問題的,下次要改掉測試一下。”最近又深入學習了驅動程序里的各個函數,發現使用seq_read對proc_myled_operations.read進行初始化是正確的,是一種“套路”。

調用cat指令時,系統首先會調用proc_myled_open()函數,在open()函數內會調用proc_myled_show將讀取到的數據存入seq_file。讀失敗的真正原因是Vivado中使用的axi-gpio IP核導致,該IP核的引腳用作輸入時,需要操作方向寄存器,將引腳設為輸入才可以讀取到引腳狀態。但我嘗試操作方向寄存器總是失敗,換成自己的IP,操作多個寄存器又沒有問題,不知道咋回事……

總結

以上是生活随笔為你收集整理的zynq linux内核驱动编写,【原创】Linux下驱动Zynq GPIO (Switch、button、led)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 在线免费观看视频a | 激情综合网五月婷婷 | xxxx在线播放 | 性按摩玩人妻hd中文字幕 | 欧美精品视 | 久久久久久久极品内射 | 热久久久久久久 | 99re6在线视频 | 欧洲精品免费一区二区三区 | 肥臀av | freesex性hd公交车上 | 又黄又骚又爽 | 日本女人性视频 | 久久精品第一页 | 亚洲精品无码永久在线观看 | 亚洲av无码国产精品久久 | 日韩av电影手机在线观看 | 一本黄色片 | 夫妻黄色片 | 中文字幕人乱码中文字 | 中文字幕69 | 麻豆一区产品精品蜜桃的特点 | 给我看高清的视频在线观看 | 又大又粗弄得我出好多水 | 久久午夜网站 | 艳情五月 | 色呦呦网站在线观看 | 国产福利在线视频观看 | 天天爱天天爽 | 87福利视频 | 2017狠狠干 | 激情吧| 亚洲国产精品成人午夜在线观看 | 色午夜 | 开心激情网五月天 | 男人操女人免费视频 | 人妻大战黑人白浆狂泄 | 亚洲欧美自拍一区 | 青青伊人国产 | www.毛片.com| 日本在线视频不卡 | 亚洲av熟女一区 | 九九爱精品 | 日本一级淫片免费放 | 日本久久成人 | 少妇一级淫片免费看 | 欧美日韩爱爱 | 亚洲精品久久久久久 | 日本伦理一区二区三区 | 免费在线毛片 | 风流还珠之乱淫h文 | 美美女高清毛片视频免费观看 | n0659极腔濑亚美莉在线播放播放 | 国产日产亚洲精品 | 亚洲涩涩爱| 午夜人体视频 | 日韩欧美二区 | 亚洲天堂视频网 | 久久日视频 | 亚洲自拍偷拍精品视频 | 99精品视频网站 | 久插网 | 国产第四页| 国产熟女高潮一区二区三区 | 国产日韩欧美精品一区 | 国产精品伦理一区 | 不卡一区二区三区四区 | 91小视频在线 | 日韩欧美一 | 高清欧美性猛交xxxx黑人猛交 | 秋霞影院午夜伦 | 国产二区视频 | 在线视频这里只有精品 | 伊人tv| 国产精品一区二区久久 | 四虎精品在永久在线观看 | 美女一二三区 | 在线日韩免费 | 色人阁五月 | 久久爱综合 | 蘑菇av | 亚洲欧美日本在线观看 | 亚洲国产高清国产精品 | 99久久婷婷国产一区二区三区 | 西西4444www大胆无视频 | 国产91免费看 | 亚洲自拍偷拍精品 | 黄色大片在线看 | 奇米网一区二区 | 免费无码国产v片在线观看 三级全黄做爰在线观看 | 精品欧美久久久 | wwwxxx在线| 久久免费在线视频 | 无码日韩人妻精品久久蜜桃 | 亚洲2022国产成人精品无码区 | 91久久国产综合久久91精品网站 | 岛国av噜噜噜久久久狠狠av | 波多野结衣二区三区 | 国产欧美一区二区精品久久久 |