系列文章目录
第三章 DW_i2c功能及使用流程介绍
文章目录
前言
一、功能介绍
1.1 i2c写操作:
1.1.1 详细flow介绍
1.2 i2c读操作:
1.2.1 详细flow介绍
二、软件流程介绍
2.1 定义WDT中断服务子程序
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定义:
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函数
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简单化了。文章来源:https://www.toymoban.com/news/detail-774271.html
在实际验证过程中,不仅仅要根据需求设计严谨的case,还要同时控制收发双方的驱动程序,以及添加数据的自动化checker,这样后期在大量回归测试时,可以更快的完成回归测试。文章来源地址https://www.toymoban.com/news/detail-774271.html
到了这里,关于SOC系统经典IP介绍以及使用方法说明之dw_i2c的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!