SPI驱动:(Linux驱动7)

来源:互联网 发布:windows优化大师64 编辑:程序博客网 时间:2024/06/10 18:38

说明:

spi,i2c,usb等总线,在cpu上均有相应的控制器,与之对应的数据结构是spi_master,i2c_adapter等.主机控制器和外设分离,外设用于
驱动不同的芯片,通过这样设计避免了外设驱动与控制器关联.
spi驱动包括spi核心(/drivers/spi/spi.c),主要包括主机控制器,外设的注册,注销
driver和device的关系:driver用于将外设挂载到总线上,device描述设备的特性,与platform_device使用board_info来描述device类似,
spi使用spi_board_info来描述spi_device.通过spi_driver将spi外设挂载到spi总线,在driver的probe函数中,注册spi所属本身设备驱动.

变量:

spi_master{//用于描述spi主机控制器
struct device dev;
bus_num
num_chipselect
(setup)(struct spi_device)
(transfer)(spi_device dev,spi_message *msg);
(*cleanup)(spi_device *dev);
}

spi_driver{//用于描述外设,挂载外设驱动
probe
remove
shutdown
suspend
resume
device_driver driver;
}

spi_device{//用于描述外设
struct device dev;
struct spi_master *master;
max_speed_hz;
chip_select;
mode;
bits_per_word;
irq;
*controller_state;
*controller_data;
modalias[SPI_NAME_SIZE];
}

spi_transfer{//用于描述传输数据
*tx_buf;
*rx_buf;
len
dma_addr_t tx_dma;
dma_addr_t rx_dma;
cs_change;
bits_per_word;
delay_usecs;
speed_hz;
list_head transfer_list;
}

spi_message{//用于组织spi_transfer
list_head transfers;
spi_device *spi;
is_dma_mapped;
(*complete)(void*context);
void *context;
actual_length;
status;
list_head queue;
void *state;
}

struct spi_board_info{//描述spi外设数据结构
modalias;外设驱动的名称
bus_num;//用到的spi主机控制器号
chip_select;//片选信号
max_speed_hz;//spi传输速率
plat_form_data;//平台数据,用在spi_device.dev.platform_data;
controller_data;//用在spi_device.controller_data中
}

函数:

spi核心函数:

  • spi外设函数

(struct spi_device *)
spi_alloc_device(struct spi_master* master);

int spi_add_device(struct spi_device *dev);

int spi_new_device(struct spi_device dev,struct spi_board_info info);//调用alloc_device和add_device

void spi_unregister_device(struct spi_device *dev);

int spi_register_board_info(struct spi_board_info* info,int nr);//将外设与master联系的函数,会调用spi_new_device

int spi_register_driver(struct spi_driver *driver);

int spi_unregister_driver(struct spi_driver *driver);

  • spi控制器函数
    struct spi_master *
    spi_alloc_master(stuct device *dev,int size);
    int spi_register_master(struct spi_master *master);
    int spi_unregister_master(struct spi_master *master);
    spi_master_get_dev_data(struct spi_master*master)//通常通过此函数获得用户定义的控制器的spi资源,
    xx_spi{
    int irq;
    struct clk *clk;
    void *buf;

    struct spi_device *dev;
    }
    spi_master_set_dev_data(struct spi_master *master,void *data);
  • spi传输函数

spi_message_init 初始化spi message

spi_message_add_tail(struct spi_transfer *t,struct spi_message *msg)

spi_sync(spi_device *spi,spi_message *msg)

spi_write(spi_device *spi,char *buf,size_t len);

spi_read(spi_device*spi,char *buf,size_t len);

用法:

  • spi适配器驱动实现:

    • 适配器驱动文件
      xx_transfer(struct spi_device* dev,struct spi_message *msg){
      }
      xx_setup(struct *spi_device *dev){
      }

      int xx_probe(struct platform_device *dev){
      读取适配器资源,配置资源
      spi_alloc_master();

      填充spi_master中的setup,transfer等函数
      spi_register_master();
      }

      struct platform_driver xx_spi_driver={
      .driver={
      .name=”xx_spi_driver”;
      .owner=THIS_MODULE;
      }
      .probe=xx_probe;
      .remove=xx_remove;
      .resume=xx_resume;
      }
      xx_init(){
      platform_driver_register(&xx_spi_driver);
      }

      xx_exit(){
      platform_driver_unregister(&xx_spi_driver);
      }
      或者
      module_platform_driver(&xx_spi_driver);//不需要init,exit函数

    • 适配器资源描述
      struct resources={
      [0]={
      .start
      .end
      .flags=
      }

      }
      struct platform_device xx_spi_device={
      [0]={
      name=”xx_spi_driver”,
      resources=&xx_spi_resources;
      num_resorces=
      dev={
      .platform_data=xx_spi_data;
      }
      }
      }

    • 合适的地方调用
      platform_device_register(&xx_spi_device);

  • spi外设驱动实现

    • xx外设驱动文件
      定义外设自身的驱动
      xx_fun();
      定义外设driver函数
      xx_probe(struct platform_device *pdev){
      注册外设功能函数
      }

    • 定义driver
      xx_driver={
      .probe=xx_probe;
      .remove=xx_remove;
      .driver={
      .name=”xx_driver”;
      .owner=THIS_MODULE;
      }
      }
      xx_init(void){
      spi_register_driver(&xx_driver);
      }
      xx_exit(void){
      spi_unregister_driver(&xx_driver);
      }

    • 外设的资源描述,通常在板子的初始化文件中
      描述spi外设,填充spi_board_info
      struct spi_board_info xx_spi_device={
      .modalias=”xx_driver”;//对应的外设驱动名称
      .bus_num
      .max_speed_hz
      .chip_select
      .platform_data
      .mode;

      }

    • 在合适的地方调用

    spi_register_board_info(&xx_spi_device,ARRAY_SIZE(xx_spi_device));

可以看出spi驱动与上面讲的rtc驱动很像,除了最后驱动注册函数不一样外,以上rtc部分均可以套用.

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 vivo手机突然开不了机怎么办 苹果六关不了机怎么办 微信老是无响应怎么办 打游戏被骂了怎么办 微信运动跳转排行榜失败怎么办 小恩爱账号忘了怎么办 华为账号更换后游戏账号怎么办 注册游戏账号需要身份证怎么办 英雄联盟被裁决了怎么办 百度网盘密码重置不了怎么办 sap密码输入被锁怎么办 dnf二级密码错10怎么办 大网卡网速慢了怎么办 小米路由器无线速度慢怎么办 小米手机无线速度慢怎么办 电脑网卡驱动没了怎么办 电脑显示网卡驱动不正常怎么办 微信别人拒收消息怎么办 电脑无线网卡速度慢怎么办 网吧吃鸡更新慢怎么办 手机号注册不了微信怎么办 小米账号密码忘了怎么办 小米手机账号密码忘了怎么办 华为手机账号密码忘记了怎么办 老年机开不了机怎么办 天谕没有顺网登陆怎么办 苹果密保问题忘了怎么办 密保手机没用了怎么办 qq密保手机没用了怎么办 手机开机按钮坏了怎么办 改了账号游戏角色消失怎么办 华为开机键坏了怎么办 抖音账号已重置怎么办 抖音账号被重置怎么办 吃鸡账号密码忘了怎么办 微信只记得账号忘了手机号怎么办 红米3开机键失灵怎么办 晚自习教室有许多虫子怎么办 泰迪吃草又呕吐怎么办 手机不断收到验证码信息怎么办 樱桃吃多了上火怎么办