SOC系统经典IP介绍以及使用方法说明之dw_i2c

系列文章目录

第三章 DW_i2c功能及使用流程介绍


文章目录

前言

一、功能介绍

[1.1 i2c写操作:](#1.1 i2c写操作:)

[1.1.1 详细flow介绍](#1.1.1 详细flow介绍)

[1.2 i2c读操作:](#1.2 i2c读操作:)

[1.2.1 详细flow介绍](#1.2.1 详细flow介绍)

二、软件流程介绍

[2.1 定义WDT中断服务子程序](#2.1 定义WDT中断服务子程序)

[2.2 定义main函数](#2.2 定义main函数)

三、总结



前言

按照i2c的协议,i2c的时钟由master方提供,master可以向slave发送数据,也可以向slave请求数据。对应的slave既可以接收来自master发送的数据,也可以响应master请求数据。关于i2c协议,后续我们会单独讲解里面的细节和注意事项,这里我们主要接收使用过程中的一些基本配置flow。


一、功能介绍

这里简单介绍一下i2c读写过程涉及到flow:

1.1 i2c写操作:

1.1.1 详细flow介绍

step1:首先master发起i2c start,即在sclk高电平拉低sda;

step2:发送slave设备地址,与之通信,这个设备地址按照协议可以是7bit,也可以是10bit,这里介绍最简单的7bit模式。

step3:紧接着发送一个bit的写控制位,表示当前传输为一笔写操作。

step4:然后后续跟着两个byte的数据,这两个byte数据一般用于软件解析命令用,通常情况下收发双方可以利用这两个byte自定义一些私有协议,比如最简单的就是两个纯粹的mem地址0x1000,表示master即将向0x1000地址写数据,因此后续master发送过来的Data,需要软件将其搬运到系统mem 0x1000地址去。当然也可以将这两个byte拆分成多个不同的命令,方便系统灵活运用。

step5:然后是发送过来的真正的payload数据

step6:当master完成数据写传输后,发送stop,即在scl的高电平拉高sda,结束当前传输。

1.2 i2c读操作:

1.2.1 详细flow介绍

step1:首先master发起i2c start,即在sclk高电平拉低sda;

step2:发送slave设备地址,与之通信,这个设备地址按照协议可以是7bit,也可以是10bit,这里介绍最简单的7bit模式。

step3:紧接着发送一个bit的写控制位,表示当前传输为一笔写操作。

step4:然后后续跟着两个byte的数据,这两个byte数据一般用于软件解析命令用,通常情况下收发双方可以利用这两个byte自定义一些私有协议,比如最简单的就是两个纯粹的mem地址0x1000,表示master即将向0x1000地址写数据,因此后续master发送过来的Data,需要软件将其搬运到系统mem 0x1000地址去。当然也可以将这两个byte拆分成多个不同的命令,方便系统灵活运用。

step5:这里master发送了一个re_start操作,即在scl的高电平拉低了sda,而并非发送payload数据,这里其实是一个读的转身,当slave接收到re_start时,会认为master其实想读数据,访问的数据地址体现在2byte信息里。因此,此时软件需要从内存地址里取数据并加载到i2c tx fifo中;

step6:按照协议重新发送设备地址以及R控制bit,这里配合step5供软件解析读过程。

step7:slave会根据软件填写的tx fifo值,把数据发送出去。

step8:当master接收完数据后,发送stop,即在scl的高电平拉高sda,结束当前传输。

二、软件流程介绍

2.1 定义WDT中断服务子程序

中断handler定义:

cs 复制代码
int dw_i2c_int_handler()
{
   int rdata;
   rdata = REG32(I2C_INTR_STAT);  //read intr status
   //judge which intr bit trigger
   if((rdata & 0x1) == 0x1) //rx_under
     {
       rdata = REG32(I2C_CLR_RX_UNDER); //read clear
     }
   else if((rdata & 0x2) == 0x2) //rx_over
     {
       rdata = REG32(I2C_CLR_RX_OVER); //read clear
     }
   else if((rdata & 0x4) == 0x4) //rx_full
     {
       rdata = REG32(I2C_DATA_CMD); //read recv data
     }
   else if((rdata & 0x8) == 0x8) //tx_over
     {
       rdata = REG32(I2C_CLR_TX_OVER); //read clear
     }
   else if((rdata & 0x10) == 0x10) //tx_empty
     {
       REG32(I2C_DATA_CMD) = 0x12; //cpu initial data into tx fifo
     }
   else if((rdata & 0x20) == 0x20) //rd_req
     {
       REG32(I2C_CLR_RD_REQ); //clr stop
       REG32(I2C_DATA_CMD) = 0x12; //cpu initial data into tx fifo
     }
   else if((rdata & 0x40) == 0x40) //tx_abrt
     {
       rdata = REG32(I2C_CLR_TX_ABRT); //read clear
     }
   else if((rdata & 0x80) == 0x80) //rx_done
     {
       rdata = REG32(I2C_CLR_RX_DONE); //read clear
     }
   else if((rdata & 0x100) == 0x100) //activity
     {
       rdata = REG32(I2C_CLR_ACTIVITY); //read clear
     }
   else if((rdata & 0x200) == 0x200) //stop_det
     {
       REG32(I2C_CLR_STOP_DET); //clr stop
     }
}

这里是一个通用的中断handler,大家可以根据注释以及datasheet上的描述对此进行扩展,比如有些软件需要在tm_empty中断发生的时候CPU填写数据,以及fifo full中断的时候CPU需求将数据取走等等。具体还要根据实际应用情况来做扩展。

当然,对于EDA验证来说,这里相对来说更灵活,可以根据验证环境情况来自定义中断handler。

2.2 定义main函数

main函数

cs 复制代码
int main()
{
   CLK_DW_I2C_EN;   //打开i2c模块的时钟使能,根据设计需求
   
   //may be i2c share gpio with module, this cfg can be used 
   GPIO_FUNC_SEL_I2C;  //配置gpio功能为DW_I2C

   set_irq_vector(NVIC_NUM_DW_I2C, (int)dw_i2c_int_handler); //配置中断服务向量
   __nds32_enable_int(NVIC_NUM_DW_I2C); //使能CPU中断

   //dw i2c initial
   REG32(I2C_ENABLE)      = 0x0;  //在配置i2c之前一定要先disable i2c_en
   REG32(I2C_SDA_HOLD)    = 0x5;  //可选,具体参考datasheet描述
   REG32(I2C_FS_SPKEN)    = 0x2;  //滤除毛刺的深度,建议根据需求配置
   REG32(I2C_TX_TL)       = 0x4;  //tx fifo水线
   REG32(I2C_RX_TL)       = 0x4;  /rx fifo水线
   REG32(I2C_CON)         = (REG32(I2C_CON) & 0xFFFFFF80) | 0x65); //master mode and 400k
   REG32(I2C_FS_SCL_HCNT) = 0x6;  //scl高电平宽度配置,根据需求修改
   REG32(I2C_FS_SCL_LCNT) = 0x6;  //scl低电平宽度配置,根据需求修改

   
   REG32(I2C_ENABLE) = 0x1; //使能i2c
   
   //填写tx fifo数据,硬件会自动将数据发送出去,这里填数据也可以放到int_handler中
   REG32(I2C_DATA_CMD) = 0x12;
   REG32(I2C_DATA_CMD) = 0x34;
   REG32(I2C_DATA_CMD) = 0x56;
   ......

   while(发送中断完成);

}

上述main函数中,本文详细介绍了DW_i2c的初始化流程,里面的步骤基本上是必不可少的,当然,有一些配置可以根据实际情况进行调整,同时,如果使用i2c的更多功能,还需要大家自行添加相关寄存器配置。


三、总结

这里只是介绍了master发送的相关case配置,实际上DW_I2C可以配置为master/slave模式,且两个模式可以分别支持收发,即理论上来收还有其他三种case,master收数据,slave发数据以及slave收数据。在实际设计case时,关于数据的收发可以灵活调整,借助每个中断来进行同步收发是一个比较好的编码风格。这里为了让大家更容易理解,因此设计的case简单化了。

在实际验证过程中,不仅仅要根据需求设计严谨的case,还要同时控制收发双方的驱动程序,以及添加数据的自动化checker,这样后期在大量回归测试时,可以更快的完成回归测试。

相关推荐
代码雕刻家4 分钟前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
一个闪现必杀技7 分钟前
Python入门--函数
开发语言·python·青少年编程·pycharm
AI完全体7 分钟前
【AI知识点】偏差-方差权衡(Bias-Variance Tradeoff)
人工智能·深度学习·神经网络·机器学习·过拟合·模型复杂度·偏差-方差
Fan_web10 分钟前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
龙图:会赢的14 分钟前
[C语言]--编译和链接
c语言·开发语言
GZ_TOGOGO20 分钟前
【2024最新】华为HCIE认证考试流程
大数据·人工智能·网络协议·网络安全·华为
sp_fyf_202420 分钟前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘
新缸中之脑21 分钟前
Ollama 运行视觉语言模型LLaVA
人工智能·语言模型·自然语言处理
胡耀超1 小时前
知识图谱入门——3:工具分类与对比(知识建模工具:Protégé、 知识抽取工具:DeepDive、知识存储工具:Neo4j)
人工智能·知识图谱
陈苏同学1 小时前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm