国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

SPI驅動

發布時間:2010-10-30 11:03    發布者:geyingzhen
關鍵詞: spi , 驅動
SPI(同步外設接口)是由摩托羅拉公司開發的全雙工同步串行總線,其接口由MISO(串行數據輸入),MOSI(串行數據輸出),SCK(串行移位時鐘),SS(從使能信號)四種信號構成,SS決定了唯一的與主設備通信的從設備,主設備通過產生移位時鐘來發起通訊。通訊時,數據由MOSI輸出,MISO輸入,數據在時鐘的上升或下降沿由MOSI輸出,在緊接著的下降或上升沿由MISO讀入,這樣經過8/16次時鐘的改變,完成8/16位數據的傳輸。
SPI模塊為了和外設進行數據交換,根據外設工作要求,其輸出串行同步時鐘極性(CPOL)和相位(CPHA)可以進行配置。如果
CPOL=0,串行同步時鐘的空閑狀態為低電平;如果CPOL=1,串行同步時鐘的空閑狀態為高電平。如果CPHA=0,在串行同步時鐘的第一個跳變沿(上升或下降)數據被采樣;如果CPHA=1,在串行同步時鐘的第二個跳變沿(上升或下降)數據被采樣。SPI接口時序如圖12.5所示。

12.5 SPI總線時序

Linux中,用代碼清單12.12spi_master結構體來描述一個SPI主機控制器驅動,其主要成員是主機控制器的序號(系統中可能存在多個SPI主機控制器)、片選數量、SPI模式和時鐘設置用到的函數、數據傳輸用到的函數等。
代碼清單12.12 spi_master結構體
1  struct spi_master {
2      struct device   dev;
3      s16                     bus_num;
4      u16                     num_chipselect;
5
6      /* 設置模式和時鐘 */
7      int                     (*setup)(struct spi_device *spi);
8
9      /* 雙向數據傳輸 */
10     int                     (*transfer)(struct spi_device *spi,
11                                             struct spi_message *mesg);
12
13     void                    (*cleanup)(struct spi_device *spi);
14 };
分配、注冊和注銷SPI主機的APISPI核心提供:
struct spi_master * spi_alloc_master(struct device *host, unsigned
size);
int spi_register_master(struct spi_master *master);
void spi_unregister_master(struct spi_master *master);
Linux中,用代碼清單12.13spi_driver結構體來描述一個SPI外設驅動,可以認為是spi_masterclient驅動。
代碼清單12.13 spi_driver結構體
1 struct spi_driver {
2     int                     (*probe)(struct spi_device *spi);
3     int                     (*remove)(struct spi_device *spi);
4     void                    (*shutdown)(struct spi_device *spi);
5     int                     (*suspend)(struct spi_device *spi,
pm_message_t mesg);
6     int                     (*resume)(struct spi_device *spi);
7     struct device_driver    driver;
8 };

可以看出,spi_driver結構體和platform_driver結構體有極大的相似性,都有probe()、remove()、suspend()、resume()這樣的接口。是的,這幾乎是一切client驅動的習慣模板。

SPI外設驅動中,當透過SPI總線進行數據傳輸的時候,使用了一套與CPU無關的統一的接口。這套接口的第1個關鍵數據結構就是spi_transfer,它用于描述SPI傳輸,如代碼清單12.14
代碼清單12.14 spi_transfer結構體
1  struct spi_transfer {
2      const void      *tx_buf;
3      void            *rx_buf;
4      unsigned        len;
5
6      dma_addr_t      tx_dma;
7      dma_addr_t      rx_dma;
8
9      unsigned        cs_change:1;
10     u8              bits_per_word;
11     u16             delay_usecs;
12     u32             speed_hz;
13
14     struct list_head transfer_list;
15 };

而一次完整的SPI傳輸流程可能不只包含1spi_transfer,它可能包含1個或多個spi_transfer,這些spi_transfer最終通過spi_message組織在一起,其定義如代碼清單12.15。
代碼清單12.15 spi_message結構體
1  struct spi_message {
2     struct list_head        transfers;
3
4     struct spi_device       *spi;
5
6     unsigned                is_dma_mapped:1;
7
8     /* 完成被一個callback報告 */
9     void                    (*complete)(void *context);
10    void                    *context;
11    unsigned                actual_length;
12    int                     status;
13
14    struct list_head        queue;
15    void                    *state;
16 };

通過spi_message_init()可以初始化spi_message,而將spi_transfer添加到spi_message隊列的方法則是:
void spi_message_add_tail(struct spi_transfer *t, struct spi_message *m);

發起一次spi_message的傳輸有同步和異步兩種方式,使用同步API時,會阻塞等待這個消息被處理完。同步操作時使用的API是:
int spi_sync(struct spi_device *spi, struct spi_message *message);

使用異步API時,不會阻塞等待這個消息被處理完,但是可以在spi_messagecomplete字段掛接一個回調函數,當消息被處理完成后,該函數會被調用。異步操作時使用的API是:
int spi_async(struct spi_device *spi, struct spi_message *message);
代碼清單12.16是非常典型的初始化spi_transfer、spi_message并進行SPI數據傳輸的例子,同時它們也是SPI核心層的2個通用API,在SPI外設驅動中可以直接調用它們進行寫和讀操作。
代碼清單12.16 SPI傳輸實例spi_write()、spi_read() API
1  static inline int
2  spi_write(struct spi_device *spi, const u8 *buf, size_t len)
3  {
4          struct spi_transfer     t = {
5                          .tx_buf         = buf,
6                          .len            = len,
7                  };
8          struct spi_message      m;
9
10         spi_message_init(&m);
11         spi_message_add_tail(&t, &m);
12         return spi_sync(spi, &m);
13 }
14
15 static inline int
16 spi_read(struct spi_device *spi, u8 *buf, size_t len)
17 {
18         struct spi_transfer     t = {
19                         .rx_buf         = buf,
20                         .len            = len,
21                 };
22         struct spi_message      m;
23
24         spi_message_init(&m);
25         spi_message_add_tail(&t, &m);
26         return spi_sync(spi, &m);
27 }

LDD6410開發板所使用的S3C6410SPI主機控制器驅動位于drivers/spi/spi_s3c.hdrivers/spi/spi_s3c.c2個文件,其主體是實現了spi_mastersetup()、transfer()等成員函數。

SPI外設驅動遍布于內核的drivers、sound的各個子目錄之下,SPI只是一種總線,spi_driver的作用只是將SPI外設掛接在該總線上,因此在spi_driverprobe()成員函數中,將注冊SPI外設本身所屬設備驅動的類型。

platform_driver對應著一個platform_device一樣,spi_driver也對應著一個spi_device;platform_device需要在BSP的板文件中添加板信息數據,而spi_device也同樣需要。spi_device的板信息用spi_board_info結構體描述,該結構體記錄SPI外設使用的主機控制器序號、片選序號、數據比特率、SPI傳輸模式(即CPOL、CPHA)等。如諾基亞7702SPI設備的板信息數據如代碼清單12.17,位于板文件arch/arm/mach-omap1/board-nokia770.c。
代碼清單12.17諾基亞770板文件中的spi_board_info
1  static struct spi_board_info nokia770_spi_board_info[] __initdata = {
2     [0] = {
3             .modalias       = "lcd_mipid",
4             .bus_num        = 2, /* 用到的SPI主機控制器序號 */
5             .chip_select    = 3, /* 使用哪一號片選 */
6             .max_speed_hz   = 12000000, /* SPI數據傳輸比特率 */
7             .platform_data  = &nokia770_mipid_platform_data,
8     },
9     [1] = {
10            .modalias       = "ads7846",
11            .bus_num        = 2,
12            .chip_select    = 0,
13            .max_speed_hz   = 2500000,
14            .irq            = OMAP_GPIO_IRQ(15),
15            .platform_data  = &nokia770_ads7846_platform_data,
16    },
17 };

Linux啟動過程中,在機器的init_machine()函數中,會通過如下語句注冊這些spi_board_info
spi_register_board_info(nokia770_spi_board_info,
                       ARRAY_SIZE(nokia770_spi_board_info));

這一點和啟動時通過platform_add_devices()添加platform_device非常相似。
本文地址:http://m.qingdxww.cn/thread-35226-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 使用SAM-IoT Wx v2開發板演示AWS IoT Core應用程序
  • 使用Harmony3加速TCP/IP應用的開發培訓教程
  • 集成高級模擬外設的PIC18F-Q71家族介紹培訓教程
  • 探索PIC16F13145 MCU系列——快速概覽
  • 貿澤電子(Mouser)專區

相關視頻

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 四虎精品永久在线 | 欧美日韩国产在线人 | 青青青国产在线观看 | 国产一级在线现免费观看 | 最近中国日本免费观看 | 国产精品久久免费观看 | 国产一区二区视频在线 | 亚洲精品高清国产麻豆专区 | 国产福利一区视频 | 77788色淫免费网站视频 | 五月婷婷网站 | 九色在线免费观看 | 九九热在线免费视频 | 国产一页 | 青青视频国产 | 国产亚洲一区二区精品 | 91精品国产高清91久久久久久 | 国产在线成人一区二区 | 欧美精品片在线观看网站 | 日韩a视频 | 四虎免费影院在线播放 | 亚洲性一级理论片在线观看 | 狠狠狠色丁香婷婷综合激情 | 日韩色视频一区二区三区亚洲 | 高清中文字幕在线 | 99国产精品 | 中文字幕日韩一区二区 | 亚洲成年网站在线观看 | eeuss影院在线奇兵区1页 | 久久青青草原精品国产不卡 | 日日摸夜夜添夜夜免费视 | 亚洲成人在线免费 | 99久久免费国内精品 | 99免费在线观看视频 | 女人18毛片a级毛片一区②区 | 亚洲五月婷 | 国产精品三级国语在线看 | 日本视频不卡 | 亚洲逼| 恐怖片在线观看高清 | 黄色手机看片 |