0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于zynq的IIC驱动的内容和机制

454398 来源:AI加速 作者:AI加速 2020-11-30 15:45 次阅读

本文主要介绍基于zynq的IIC的驱动架构,通过代码编写来深入了解IIC驱动的内容和机制。

1. IIC驱动架构

IIC驱动包含两部分:IIC总线驱动和设备驱动。总线驱动是对硬件设备适配器端的实现,主要包含i2c_adapter,i2c_algorithm和控制i2c适配器产生通信信号的函数。I2c_adapter和一套i2c读写algorithm绑定,i2c_algorithm包含对i2c总线的访问方式。IIC总线驱动完成i2c_driver的注册,IO空间分配,IIC硬件设备时钟的设定,主从模式以及收发模式的设定等。通过i2c_adapter可以控制I2C总线上开始,结束等信号的产生。

IIC设备驱动提供用户空间和i2c总线驱动的交互,其定义了i2c_client数据结构以及文件操作ioctrl,open,write等。I2c_client依附于i2c_adapter,用户通过i2c_client结构来调用相应的i2c_adapter,来实现IIC控制。具体层次结构如下:

User ioctrl--------->

I2c_client------------>

I2c_adapter------------>

I2c_algorithm--------------->

IIC硬件

2. zynq上IIC驱动试验

基于黑金的zynq7020开发板,通过IIC来读写EEPROM,首先在PS端选择IIC端口,导出到PL端,分配引脚。

代码分析:

首先定义一个i2c_dev,用于绑定到platfrom总线上。结构体中包含i2c_adapter,以及用于收发数据的buffer(p_send_buf和p_recv_buf),completion用于等待数据发送过程。

struct eeprom_i2c_dev{
struct device *dev;
struct i2c_adapter adapter;
unsigned long size;
void __iomem *baddr;
struct i2c_msg *p_msg;
unsigned char *p_send_buf;
unsigned char *p_recv_buf;
unsigned int recv_cnt;
unsigned int send_cnt;
int hold_falg;
int irq;
struct completion msg_completion;
spinlock_t xfer_lock;
u32 i2c_clk;
u32 input_clk;
struct clk *clk;
u32 ctrl_reg;
};

I2c_driver中主要包含了驱动注册和卸载函数。

static struct platform_driver eeprom_i2c_driver = {
.driver={
.name=DRIVER_NAME,
.owner=THIS_MODULE,
.of_match_table=eeprom_i2c_of_match,
},
.probe=eeprom_i2c_probe,
.remove=eeprom_i2c_remove,
};

现在分析probe函数:

首先从设备树中获得内存地址以及中断号,并分配IO虚拟内存。

static int eeprom_i2c_probe(struct platform_device *pdev){
……
res=platform_get_resource(pdev, IORESOURCE_MEM, 0);
……
base=ioremap(res->start, resource_size(res));
……
res=platform_get_resource(pdev, IORESOURCE_IRQ, 0);

指定i2c_adapter的i2c_algorithm。

idev->adapter.owner = THIS_MODULE;
idev->adapter.dev.of_node = pdev->dev.of_node;
idev->baddr=base;
idev->irq=irq;
idev->size=size;
idev->dev=&pdev->dev;
idev->adapter.timeout=msecs_to_jiffies(1000);
idev->adapter.algo=&eeprom_i2c_algo;
idev->adapter.algo_data = idev;
idev->adapter.dev.parent = &pdev->dev;
snprintf(idev->adapter.name, sizeof(idev->adapter.name), "EEPROM I2C at %08lx", strt_addr);

根据设备树中时钟配置IIC硬件中的时钟寄存器。

idev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(idev->clk)) {
dev_err(&pdev->dev, "input clock not found./n");
return PTR_ERR(idev->clk);
} ret=clk_prepare_enable(idev->clk);
if(ret)
dev_err(&pdev->dev, "unable to enable clcok/n");
idev->input_clk=clk_get_rate(idev->clk);
idev->ctrl_reg = EEPROM_I2C_CR_ACK_EN | EEPROM_I2C_CR_NEA | EEPROM_I2C_CR_MS;
ret=eeprom_i2c_setclk(idev->input_clk, idev);

IIC接收数据要申请中断。

ret=devm_request_irq(&pdev->dev, irq, eeprom_i2c_irq, 0, DRIVER_NAME, idev);

i2c_add_adapter用于将i2c_adapter加入到总线中。这个时候i2c_dev.c是可以通过通知连来检测到这个i2c_adapter的,并能为其分配设备号。然后用户就可以通过直接操作这个设备来实现IIC读写了。

接下来看i2c_algorithm:

static const struct i2c_algorithm eeprom_i2c_algo = {
.master_xfer=eeprom_i2c_master_xfer,
.functionality=eeprom_i2c_func,
};

eeprom_i2c_master_xfer是通信函数,其中有:

eeprom_i2c_mrcv用于处理接收到IIC设备数据,eeprom_i2c_msend用于处理发送数据,函数主要通过配置IIC硬件设备中寄存器来实现。

现在来看用户如何操作IIC:

i2c_rdwr_ioctl_data是i2c_dev.c中用于存储的收发数据的结构,通过它可以传递数据。在work_queue中的msgs中设定好slave_addr,len等值,然后通过ioctrl可以读写IIC了。

编辑:hfy

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • IIC总线
    +关注

    关注

    1

    文章

    66

    浏览量

    20297
  • Zynq
    +关注

    关注

    10

    文章

    609

    浏览量

    47175
  • IIC驱动程序
    +关注

    关注

    0

    文章

    2

    浏览量

    5038
收藏 人收藏

    评论

    相关推荐

    基于Zynq的OLED驱动设计

    目前OLED的驱动大部分都是基于STM系列ARM芯片和传统FPGA芯片。为适应Xilinx最新平台Zynq的人机交互需要,提出一种基于Zynq的OLED驱动设计方法。##
    发表于 09-04 16:16 1.1w次阅读

    请问IO口模拟IIC协议仲裁机制怎么编写?

    IO口模拟IIC协议仲裁机制如何编写?
    发表于 03-28 23:25

    ZYNQ PS端IIC接口使用笔记分享

    ZYNQ7000系列FPGA的PS自带两个IIC接口,接口PIN IO可扩展为EMIO形式即将IO约束到PL端符合电平标准的IO(BANK12、BANK13、BANK34、BANK35);SDK中
    发表于 12-23 17:06

    ZYNQ PS端IIC接口使用笔记分享

      ZYNQ7000系列FPGA的PS自带两个IIC接口,接口PIN IO可扩展为EMIO形式即将IO约束到PL端符合电平标准的IO(BANK12、BANK13、BANK34、BANK35
    发表于 01-08 16:44

    ZYNQ PS端IIC接口怎么使用?

    ZYNQ PS端IIC接口使用笔记
    发表于 02-23 06:23

    ARM-Linux-IIC设备的添加与驱动实现

    本文分析了ARM-Linux下IIC总线及其设备驱动的层次结构,指出了IIC设备添加与驱动实现的途径,详细阐述了如何采用通用i2c-dev.c驱动
    发表于 06-13 14:37 57次下载
    ARM-Linux-<b class='flag-5'>IIC</b>设备的添加与<b class='flag-5'>驱动</b>实现

    iic驱动

    IIC驱动,含I2C的源码,MCU模拟IIC通讯函数,要改变传输频率,请修改延时函数中的数值即可
    发表于 07-04 17:57 10次下载

    IIC总线初始化基本驱动参考程序应用代码免费下载

    本文档的主要内容详细介绍的是IIC总线初始化基本驱动参考程序应用代码免费下载。程序功能:为IIC总线的基本驱动程序(此程序没有写主函数,只是
    发表于 01-16 08:00 5次下载
    <b class='flag-5'>IIC</b>总线初始化基本<b class='flag-5'>驱动</b>参考程序应用代码免费下载

    使用51单片机进行IIC和EEPROM的驱动程序免费下载

    本文档的主要内容详细介绍的是使用51单片机进行IIC和EEPROM的驱动程序免费下载。
    发表于 06-17 17:44 1次下载
    使用51单片机进行<b class='flag-5'>IIC</b>和EEPROM的<b class='flag-5'>驱动</b>程序免费下载

    使用IIC24C04芯片驱动数码管的程序和仿真电路图

    本文档的主要内容详细介绍的是使用IIC24C04芯片驱动数码管的程序和仿真电路图。
    发表于 07-10 14:28 14次下载
    使用<b class='flag-5'>IIC</b>24C04芯片<b class='flag-5'>驱动</b>数码管的程序和仿真电路图

    Zynq-7000 PS端IIC接口使用笔记

    ZYNQ7000系列FPGA的PS自带两个IIC接口,接口PIN IO可扩展为EMIO形式即将IO约束到PL端符合电平标准的IO(BANK12、BANK13、BANK34、BANK35);SDK中
    的头像 发表于 07-25 17:56 2199次阅读
    <b class='flag-5'>Zynq</b>-7000 PS端<b class='flag-5'>IIC</b>接口使用笔记

    ZYNQ PS端IIC接口使用笔记

    ZYNQ7000系列FPGA的PS自带两个IIC接口,接口PIN IO可扩展为EMIO形式即将IO约束到PL端符合电平标准的IO(BANK12、BANK13、BANK34、BANK35);SDK中
    发表于 01-28 08:05 25次下载
    <b class='flag-5'>ZYNQ</b> PS端<b class='flag-5'>IIC</b>接口使用笔记

    STM32开发中使用C语言实现IIC驱动

    简述 IIC(Inter-Integrated Circuit)其实是IICBus简称,它是一种串行通信总线,使用多主从架构,在STM32开发中经常见到。 使用面向对象的编程思想封装IIC驱动,将
    的头像 发表于 06-21 14:58 3431次阅读

    使用IIC驱动MPU6050时为什么总读取失败

    在使用IIC读取RTC芯片时遇到的问题,并成功解决。 我以为我已经完全学会了IIC,但现实却打了脸,我在使用《STM32IIC详解》文中的IIC驱动
    的头像 发表于 11-06 10:10 7148次阅读
    使用<b class='flag-5'>IIC</b>去<b class='flag-5'>驱动</b>MPU6050时为什么总读取失败

    STM32开发中使用C语言实现IIC驱动

    使用面向对象的编程思想封装IIC驱动,将IIC的属性和操作封装成一个库,在需要创建一个IIC设备时只需要实例化一个IIC对象即可,本文是基于
    发表于 02-08 16:08 4次下载
    STM32开发中使用C语言实现<b class='flag-5'>IIC</b><b class='flag-5'>驱动</b>