色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

淺談按鍵驅動的編寫和設備樹的修改

YCqV_FPGA_EETre ? 來源:未知 ? 2019-11-28 17:48 ? 次閱讀

引言

隨著深度學習5G的應用,對FPGA的功能要求越來越多。因此近幾年FPGA大廠紛紛將自己的器件集成了更多的內核,比如賽靈思的zynq系列就集成了armGPU,PCIE,射頻處理模塊等等,用于滿足各種各樣的需求。出身FPGA的工程師們也必須擁抱這些變化,不僅僅要精通FPGA開發,還需要了解其他方面的知識。比如基于zynq的開發者,就需要了解arm,linux驅動以及linux系統。做深度學習加速的還需要了解深度學習網絡以及網絡壓縮等知識。學習這些知識會讓你的眼界更加開闊,會站得高看得遠,在開始一項任務的時候不再是盲人摸象,而是高瞻遠矚,把握全局。

這是我介紹linux系統和驅動的第4篇文章,如有不恰當的地方歡迎指正,因為本人也是處于學習入門階段。三人行,必有我師焉。討論的多了,問題也就清晰了。這一篇主要介紹按鍵驅動的編寫,了解中斷的處理過程,以及設備樹的修改。

1. vivado工程搭建

工程搭建很簡單,就是配置完zynq核的外設后,增加一個axi_gpio模塊,作為外部按鍵的接口。雖然按鍵并不是直接連接到arm的IO上,但是axi_gpio也被映射到zynq系統的內存空間中,linux驅動通過讀寫key對應的映射內存來控制和檢測。要檢測到key被按下我們必須開啟中斷,因此axi_gpio模塊設置如下圖。Address editor是gpio的對應的內存空間。Zynq已經為不同外設類型分配了可選的內存映射,通常工程建立完后,由軟件工具自行分配就好了。如果一些外設內存有沖突,是無法生成hdf的。


配置完成后,進行管腳約束,然后綜合實現,生成bit文件。再導出hdf文件,打開SDK來生成fsbl,u-boot還使用前幾篇介紹驅動中的u-boot。U-boot通常不會因為驅動的新增而修改。但是由于增加了key按鍵,我們需要去設備樹中修改對應的配置。

具體如何修改設備樹,可以到linux驅動文件夾Documentation/devicetree中去尋找對應的外設文件,其中有設備樹修改的介紹。Gpio的修改可以到gpio文件夾下的gpio-zynq.txt查看。其基本形式為:

         gpio@e000a000 { #gpio-cells = <2>;
                   compatible = "xlnx,zynq-gpio-1.0";
                   clocks = <&clkc 42>;
                   gpio-controller;
                   interrupt-parent = <&intc>;
                   interrupts = <0 20 4>;
                   interrupt-controller;
                   #interrupt-cells = <2>;
                   reg = <0xe000a000 0x1000>; };
其中compatible主要是用于linux驅動去匹配設備樹中相應的節點,后面我們會介紹,這個名字和那一塊程序有關。主要是配置中斷,其中interrupts-cell指定了interrupts有多少個屬性。Interrupts的第一個屬性是中斷類型,第二個是中斷號,最后一個表示觸發類型:高電平觸發、低電平觸發、上升沿觸發和下降沿觸發四種類型。Interrupt-parent是中斷所屬的中斷控制器。我們在SDK中產生了設備樹,我們看到按鍵的相應節點位于amba_pl節點下,其中amba_pl是PL端的總線節點,而amba是PS端的總線節點,修改pl.dtsi中的gpio內容:

我們改了compitable的內容,同時要關注inerrupts,xlnx,all-inputs,xlnx,gpio-width這些屬性。Gpio-width是寬度,all-inputs是表示為輸入。

設備樹修改完后就可以編譯設備樹文件,然后用fsbl,u-boot,設備樹來制作boot.bin了。放到SD卡,啟動linux系統。接下來進入關鍵環節,key驅動的編寫。

2. 按鍵驅動代碼剖析

對于一個剛剛入門的人來說,其實了解了驅動的基本框架就好了。每個驅動都按照它的框架進行編寫和修改。能理解驅動的各個模塊功能,在驅動調試或者編寫中就能有的放矢。一個簡單的驅動的構成也很復雜,代碼也很多,篇幅有限,我只介紹主要部分。

1)platform框架

Platform是一種虛擬的平臺,提供了驅動和具體硬件交互的接口。Platform_device類似于虛擬的總線,IIC,LCD,GPIO等外設都可以看做platform_device,通過它可以遍歷所有的總線設備,而對應的驅動就是platform_driver。基本流程是:先注冊platform_device,再注冊platform_driver,然后匹配設備和驅動,最后注冊整個驅動。

在linux3以前的版本,需要定義platform_device結構體,然后通過platform_device_register函數來注冊設備。但是linux3.0以后出現了設備樹,內核函數of_platform_default_populate_init會在內核啟動后遍歷設備樹,自動注冊每個節點對應的設備。因此只需要修改設備樹參數就行了。首先看這個結構體:

static const struct of_device_id key_of_match[] __devinitdata={
         {.compatible="xlnx,gpio-keys",},
         {/*end of list*/},
};

這實際上定義了設備的匹配號,compatible就是在設備樹節點axi-gpio中對應的節點匹配名稱。我們只要讓compitable和設備樹中對應節點的值匹配上就可以將節點對應的設備注冊到總線上了。

platform_driver用于對設備的搜索和配置,主要就是去解析設備樹,根據設備樹中節點信息來填充設備結構體對應信息或者直接對設備完成配置。

static struct platform_driver key_driver={
         .driver={
                   .name=DRIVER_NAME,
                   .owner=THIS_MODULE,
                   .of_match_table=key_of_match,
         },
         .probe=key_probe,
         .remove=key_remove,
};

我們主要關注其三個變量,of_match_table就是of_device_id結構體定義的,用來匹配節點。Probe函數用來解析節點,配置設備。Remove主要是釋放在probe中使用的資源等。

編寫key驅動主要就是去填充probe和remove兩個函數。

來看probe函數是如何查找到設備的一些屬性的,比如我們要確定key鍵的數量,那么我們可以這樣來做:

         if(of_property_read_u32(node, "xlnx,gpio-width", &width)){
                   printk(KERN_ERR "get the gpio-width
");
         }

通過匹配“xlnx,gpio-width”來獲得key的位寬,這個屬性就在設備中定義的。

如果我們要操作key,需要獲得key設備的內存映射空間,這個可以通過函數platform_get_resource函數來完成。

mem=platform_get_resource(pdev, IORESOURCE_MEM, 0);
         if(!mem){
                   printk(KERN_ERR "get memory resource
");
                   return -ENODEV;
         }

第一個參數pdev是platform_device結構體,在進入probe函數之前就已經被注冊了,其指向的就是key對應的設備。第二個參數是類型,主要有IORESOURCE_MEM, IORESOURCE_IRQ等。最后一個參數是號碼,指示platform_device結構體中不同的資源類型,即IORESOURCE類型。

以上獲得的mem就是在設備樹中由reg指定的內存映射:

reg = <0x41210000 0x10000>;

中斷的獲得可以通過函數:

       r_irq=irq_of_parse_and_map(node, 0);
         if(!r_irq){
                   printk(KERN_ERR "get interrupt
");
         }
其中device_node就是設備節點,在platform_device注冊的時候,含有該節點,所以可以通過該結構體獲得。第二個參數表示一個設備樹節點有多個中斷時的索引

通過設備樹獲得了硬件信息后,我們將其填充到key_device中,key_device定義如下:

struct key_dev{
         struct cdev dev;
         struct work_struct work;                 
         int irq;
         int major;
         unsigned long start_addr;
         unsigned long size;
         void __iomem *baseaddr;
         int width;
         int inout;
         int key_prs;
        
};
其中irq為中斷號,cdev是字符設備結構體,因為key等屬于字符設備。填充如下:
lp->start_addr=mem->start;
         lp->size=mem->end-mem->start;
         lp->irq=r_irq;
         lp->width=width;

2)中斷處理

在platform中我們談到了對中斷號的獲取,那么取得了中斷號之后如何來檢測中斷事件呢?中斷處理過程可以被分成兩部分:頂半部和底半步。頂半部主要處理硬件上比較緊急的事物,比如檢測中斷,底半部用于處理中斷產生之后需要進行的事務處理。在底半部處理過程中不會耽誤檢測下一個中斷。這兩個部分不是絕對的,也可以只有一個部分。

驅動中首先需要定義一個中斷函數,用于中斷產生后進行的操作。然后申請中斷,實現函數:

err=request_irq(k_dev->irq,key_interrupt, IRQF_SHARED|IRQF_TRIGGER_RISING, DRIVER_NAME, k_dev);

第一個是中斷號,第二個為中斷處理函數,第三個參數為中斷產生類型,上升沿下降沿一類,第四個為名字,可以命名中斷,最后一個是設備結構體。

釋放中斷就通過free_irq(unsigned int irq, void *dev_id)來完成。

實現中斷底半部處理機制主要有tasklet,工作隊列,軟中斷和線程化irq。中斷機制較為復雜,任何一種機制都可以讓你竭盡腦汁。入門者還是循序漸進,所以我也只用了一種簡單的方法。類似鎖機制,我們定義一個事件:

static DECLARE_WAIT_QUEUE_HEAD(press_queue);
然后在中斷函數中喚醒這個事件,在其他函數中可以通過等待這個事件來進行中斷處理。我們的中斷函數為:
static irqreturn_t key_interrupt(int irq, void *dev_id){
         struct key_dev *dev=dev_id;
         dev->key_prs++;
         printk(KERN_INFO "interruptted
");
         wake_up_interruptible(&press_queue);
         return IRQ_HANDLED;
 
}
而等待該事件放在key_read函數中:
ssize_t key_read(struct file *filp, char __user *buf, size_t count, loff_t *fops)
{
         int err;
         struct key_dev *dev=filp->private_data;        
         wait_event_interruptible(press_queue, event_press);
         event_press=0;
         err=copy_to_user(buf, &dev->key_prs, count);
         return err ? -EFAULT : 0;
}

3)文件結構

Linux一切皆文件,任何驅動最終都被封裝為一個文件,用戶空間通過讀寫文件來操作驅動。文件操作包括打開,關閉,讀和寫等。我們不做具體介紹,簡單列出文件結構體為:

struct file_operations key_fops={
         .owner=THIS_MODULE,
         .open=key_open,
         .read=key_read,
         .release=key_close,
};
總結

對以上進行總結就是:

1) 首先進行設備樹節點屬性修改;

2) 填充platform框架下的probe,remove等函數,并定義of_device_id和platform_driver結構體;

3) 申請中斷,釋放中斷,編寫中斷函數等;

4) 填充文件結構,編寫open,close,read等函數;

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • FPGA
    +關注

    關注

    1629

    文章

    21758

    瀏覽量

    604241
  • 5G
    5G
    +關注

    關注

    1355

    文章

    48476

    瀏覽量

    564766
  • 深度學習
    +關注

    關注

    73

    文章

    5507

    瀏覽量

    121272

原文標題:【驅動初發】如何在zynq上做個按鍵驅動

文章出處:【微信號:FPGA-EETrend,微信公眾號:FPGA開發圈】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    i.MX6ULL 驅動開發7—按鍵輸入捕獲與GPIO輸入配置與高低電平讀取

    本篇主要介紹了i.MX6ULL的按鍵檢測的使用,主要的知識點是設備修改,以及GPIO的輸入配置與高低電平的讀取。
    的頭像 發表于 05-24 09:11 ?6281次閱讀
    i.MX6ULL <b class='flag-5'>驅動</b>開發7—<b class='flag-5'>按鍵</b>輸入捕獲與GPIO輸入配置與高低電平讀取

    linux驅動編寫:從hello world到 LED驅動

    的讀寫操作等都被抽象成文件操作了。本篇從hello world開始,簡要介紹驅動的基本結構,然后再進一步介紹LED硬件的搭建,以及驅動編寫設備
    的頭像 發表于 11-29 10:28 ?2760次閱讀
    linux<b class='flag-5'>驅動</b><b class='flag-5'>編寫</b>:從hello world到 LED<b class='flag-5'>驅動</b>

    Linux 設備詳解

    信息,以供相應的內核代碼使用。編寫設備文件是以.dts的文本文件存儲的,主要是為了修改、添加編輯方便。那么問題來了,如果純文本解析的話,顯然比較慢且麻煩。譬如如果屬性值是一個I/O地
    發表于 10-19 15:53

    Linux 設備詳解

    信息,以供相應的內核代碼使用。編寫設備文件是以.dts的文本文件存儲的,主要是為了修改、添加編輯方便。那么問題來了,如果純文本解析的話,顯然比較慢且麻煩。譬如如果屬性值是一個I/O地
    發表于 11-02 13:46

    Linux 設備詳解

    信息,以供相應的內核代碼使用。編寫設備文件是以.dts的文本文件存儲的,主要是為了修改、添加編輯方便。那么問題來了,如果純文本解析的話,顯然比較慢且麻煩。譬如如果屬性值是一個I/O地
    發表于 11-29 17:58

    am437x基于linux4.1.18平臺移植按鍵驅動失敗

    您好,我在am437x平臺上使用的是linux4.1.18內核,添加按鍵驅動總是失敗。我所做的步驟是: 1,修改設備xxx.dts,紅色為
    發表于 06-01 08:24

    「正點原子Linux連載」第五十五章設備樹下的platform驅動編寫

    platform驅動即可。55.3.1 修改設備文件首先修改設備
    發表于 03-21 10:03

    如何修改內核設備

    本文檔介紹了內核設備的位置和包含關系 1.內核設備位置 文件 備注 dts longan/device/config/chips/t507/configs/evb/board.dt
    發表于 12-14 13:42

    ARM Device Tree設備

    近期在學校如何寫linux的設備驅動,這片文章告訴我們為什么要引進設備Device Tree,以及舉例說明設備
    發表于 11-17 18:16 ?22次下載

    AVR編寫的矩陣按鍵

    AVR編寫的矩陣按鍵
    發表于 03-20 11:07 ?5次下載

    淺談ADC按鍵的應用設計

    淺談ADC按鍵的應用設計(現代電源技術pdf王建輝)-淺談ADC按鍵的應用設計? ? ? ? ??
    發表于 09-17 13:37 ?25次下載
    <b class='flag-5'>淺談</b>ADC<b class='flag-5'>按鍵</b>的應用設計

    【i.MX6ULL】驅動開發5——設備原理與點亮LED

    本篇介紹了設備的基本原理以及設備的使用方法,在上一篇點亮LED的代碼基礎上,通過設備的方式
    的頭像 發表于 05-21 21:41 ?4065次閱讀
    【i.MX6ULL】<b class='flag-5'>驅動</b>開發5——<b class='flag-5'>設備</b><b class='flag-5'>樹</b>原理與點亮LED

    Linux驅動開發-編寫按鍵驅動

    這篇文章介紹,如何使用雜項設備框架編寫一個簡單的按鍵驅動,完成編寫、編譯、安裝、測試等流程,了解一個雜項字符
    的頭像 發表于 09-17 15:08 ?1667次閱讀
    Linux<b class='flag-5'>驅動</b>開發-<b class='flag-5'>編寫</b><b class='flag-5'>按鍵</b><b class='flag-5'>驅動</b>

    zynq開發中的設備

    在zynq開發中經常會修改設備,每次遇到這種情況都有點發愁,今天把設備相關的知識點總結一下,希望以后遇到
    的頭像 發表于 05-25 11:29 ?2265次閱讀
    zynq開發中的<b class='flag-5'>設備</b><b class='flag-5'>樹</b>

    如何修改內核設備

    如何修改內核設備
    的頭像 發表于 12-14 14:06 ?840次閱讀
    如何<b class='flag-5'>修改</b>內核<b class='flag-5'>設備</b><b class='flag-5'>樹</b>
    主站蜘蛛池模板: 自慰弄湿白丝袜| 粉嫩极品国产在线观看| 国产午夜精AV在线麻豆| 亚洲精品第一页| 久久久久久久久a免费| 99久久99| 午夜片无码区在线观看| 考好老师让你做一次H| 爱穿丝袜的麻麻3d漫画acg| 性欧美videos俄罗斯| 美女内射少妇三区五区| 公和熄洗澡三级中文字幕| 亚洲永久精品ww47| 日本xxxx19| 久久re亚洲在线视频| 成人免费网址在线| 伊人亚洲AV久久无码精品| 日韩国产精品欧美一区二区| 精品免费在线视频| 超碰 无码 中文字幕| 亚洲日韩一区精品射精| 人人干人人爽| 久久久久伊人| 国产成人在线免费观看| 中文字幕亚洲无线码高清不卡| 手机在线免费看毛片| 伦理电影2499伦理片| 国产欧美日韩视频怡春院| 99精品视频免费在线观看| 亚洲国产成人综合| 亲嘴扒胸摸屁股视频免费网站 | xxnx18日本| 亚洲中久无码永久在线| 三级黄毛片| 男人一进一出桶女人视频| 红桃视频国产AV| 国产 高清 无码 在线播放| 99久久99久久精品国产片果冻| 一本大道无码AV天堂欧美| 无码日本亚洲一区久久精品 | 久久两性视频|