笔记 针对i2c适配器调试过程
2011-03-10 20:09
351 查看
/****************************************************/
date:20110310
在对EEPROM 24C01B/02B的操作中发现,在write结束后不能立刻进行读操作,而是要先delay一下才可以。
/****************************************************/
date:20110329
我现在搞不清楚对于我的这个i2c适配器怎么样来使用FIFO的中断方式。
我在想,可以设置接收缓冲区的阈值,当缓冲区的待处理数据个数低于这个值的时候发生一个中断告诉cpu现在可以继续向缓冲区送入新的待处理数据了。问题是如果我不停的向缓冲区送入数据,满了怎么办?datasheet上说满了会发生一个中断,并且会将FSM重置,并不会继续执行任何命令。我猜这个问题的解决办法就是,每次当中断告诉我可以继续向接收缓冲区送入数据的时候,我不要送进去太多,比如我每次最多送入15个就不在继续搞了!另外在datasheet中我还发现一句话可以让我认为:我只要向该适配器发出任何命令(包括写和读)都会被放到TX缓冲区当中!原文如下:
TX_OVERFLOW INT: set 1 if the transmit buffer is full and the processor attempts to issue another i2c commandby writing to the IC_DARA_CMD register. when this bit is set, the I2C FSM will be reset and it will not excute
any command DATA until this bit is cleared!
这样理解的话,只要我对IC_DARA_CMD register 寄存器进行操作都会被作为待处理的命令放到TX—fifo当中。这当然包括我发出一个读取从设备的命名!
对于接收缓冲区来说,我也可以设置一个阈值,当接收缓冲区的待读取数据超过这个值的时候便发生一个中断告诉cpu赶快来取数据吧,要不就快溢出了。如果这个阈值设置的比较大,一直不发生中断怎么办?
//以下是网络中的一种解释,还是有些帮助的
下面我们来看看I2C模块的数据传输:
I2C模块支持主、从,发送、接收,共4种组合传输模式。通过I2C.I2C_CON[10]可以控制模块的主从模式。I2C.I2C_CON[9]可以控制模块的发送接受模式。在传输时,通过I2C.I2C_DATA[7:0]将数据写入FIFO或从FIFO中读取数据。
我们可以有3种方式管理FIFO:中断,轮询和DMA
中断方式是通过设置FIFO的阈值(thresholds)来实现的,在发送数据时,当FIFO中的数据少于这个阈值时会产生一个中断告诉程序FIFO即将空,可以继续向FIFO发送数据。同样,在接收数据时,当FIFO中的数据大于这个阈值时会产生一个中断告诉程序FIFO即将满,需要读取FIFO中的数据。
轮询方式是通过不断查询FIFO状态寄存器,实现对FIFO的管理。不过由于这种方式十分消耗资源(原因么地球人都知道),所以个人觉得应该尽量避免采用这种方式。
DMA模式是通过DMA通道完成数据传输的方式,这种方式在传输时不占用CPU资源,在传输大数据量时优势尤为明显。是本人强烈建议采用的传输模式。
Draining功能,这个用能用于接收的数据长度不是FIFO阈值倍数的情况下。我举个例子来说明这个功能的作用:第一种情况,当一个FIFO的阈值是10bytes,接收的数据是30bytes时,接收的数据长度是FIFO阈值的倍数。当数据第一个10byte数据进入入FIFO时会产生了一个阈值中断我们可以从FIFO中读取数据,接着第二个10bytes数据进入FIFO,最后是第三个10bytes的数据。这样我们可以顺利的通过FIFO的阈值中断将30bytes的数据接收。但当接收的数据长度不是FIFO阈值的倍数时,我们以25bytes为例。当第二个10bytes数据进入FIFO产生了阈值中断并被我们从FIFO中读取,这时还剩下5bytes的数据。当这5bytes数据进入FIFO后没有达到10bytes的FIFO阈值,不会产生中断,这会导致最后这5bytes数据在FIFO中的滞留。Draining功能提供了解决这种问题的一种处理机制。
具体的传输操作在DataSheet中给出了详细的流程图,在此就不重复了。
/****************************************************/
date:20110511
i2c总线上不挂接任何设备,这时候i2c适配器发出一个start命名并寻址一个从设备,因为没有从设备,此时会收到NACK中断,然后i2c适配器将试图发出一个stop信号,但是在测试中示波器始终无法捕获这个stop信号,我怀疑是不是i2c协议不允许在start寻址后直接发送stop命令,但是参考s3c2410的代码发现这样的逻辑是完全可以的,一种用法就是这样做只是为了确定总线上是不是挂了某个设备。这到底是什么原因呢?
刚才又看了一下i2c的协议,里面有一句话这么说“当从机不能响应从机地址时,例如它正在执行一些实时函数不能接收或发送。从机必须使数据线保持高电平,主机然后产生一个停止条件终止传输或者产生重复起始条件开始新的传输”。这句话似乎是说,总线上必须有一个上拉电阻?
所以明天应该这么测试下:
在总线上连接上已经确认可以正常使用的RRPROM测试模块,然后将从设备地址写错做个寻址测试,如果此时能正常执行stop命令,则可验证以上推测是正确的!
/****************************************************/
date: 20110704
rootfs/etc/init.d/rcS
这个shell脚本要干什么呢?
在这里运行那个mdev 就是启动udev的守护进程,(mdev据说是由busybox提供的 udev 的一个简化版)这个进程在发现有设备注册进来的时候就会自动在/dev目录下根据主从设备号创建该设备的文件节点。如果不用mdev的话,我们就需要在这个脚本中用mknod命令自行创建设备的文件节点。如:
mknod /dev/i2c-0 c 89 0
mknod /dev/i2c-1 c 89 1
前面针对芯片i2c adapter 的测试一直是跑的单线程,也没有操作系统。这两天kernel在芯片上终于跑起来了,我也把针对i2c adapter的 kernel driver完成了,初次实验便成功读出了eeprom的数据,真让人兴奋!为了全面测试,我把设备地址写错,做了一下测试,没想到便打印出了这样的内核错误信息“scheduling while atomic” 。
在网上搜了一下,发现这是由于触发了内核的这样一个条件:
if (unlikely(in_atomic() && !current-> exit_state)) {
printk(KERN_ERR "BUG: scheduling while atomic: "
"%s/0x%08x/%d\n ",
current-> comm, preempt_count(), current-> pid);
dump_stack();
}
分析可知应该是在原子操作过程中休眠所致。可是我的驱动中只有一个地方用到了自旋锁,而这部分代码的边界中也没有可能存在的倒置休眠的代码。
折腾了一下午,后来想到,中断当中也是不允许休眠的呀,我是不是在中断处理函数中出现了休眠呢?妈的,检查了好久终于发现在一条处理“未检测到从设备”的逻辑通路中找到了一个msleep调用,改成mdelay后再无报错!这么难检查主要是因为这个中断处理程序写的太长了。。。。但并不是说它要处理的内容太多。。。。呵呵
git diff 原来还可以这么来用!
git diff HEAD xxx/xxx/xxx.x
那一定也可以这么来用:
git diff 484324375778421878446556897545757545 xxx/xxx/xxx.x
/****************************************************/
date:
这个CTP的数据寄存器需要清除,否则就无法拉高中断引脚!!!! 先前设置的是下降沿触发中断,这样当因为某种情况对丢失某此中断后必然导致CTP死锁,表现为中断引脚一直被拉低。由此可见当CTP缓冲区有待读取的数据时会把中断引脚一直拉低,当读完后便会把中断引脚拉高。故而推断,设置为下降沿触发中断调用是不对的,应该设置为低电平触发!
轮询模式时正常的,同时也发现在轮询期间如果缓冲区的数据没有被读完的话,中断引脚会一直被CTP拉低!!!
以上内容是某天写的一个针对it7260电容屏的笔记,这些结论现在看来可能是不对的,但是因为近期没有研究这个电容屏,所以这个内容先留下,以后再说吧。
由于在A5上中断不允许嵌套,所有的GPIO中断公用一个物理中断,然后再中断后以查询方式得到真正的中断引脚,所以在代码中已经实现了当gpio中断发生时进入主中断处理函数,然后屏蔽这唯一的一个物理的gpio中断,然后当中断处理函数退出的时候打开这唯一的一个物理中断,因此从驱动的角度看,已经没有任何必要在某个驱动内部的中断处理函数中禁止中断,在中断处理函数退出的时候打开中断了。。。。。
gpio被当做中断来用的时候,在0x24 offset 位置的每一位是用来清除中断的,如果不清除的话,这个gpio中断就会一直发生,表现就是你会不停的进入中断处理函数,所以要适时的将该位置1以清除该中断
/****************************************************/
date:
/****************************************************/
date:
/****************************************************/
date:
/****************************************************/
date:
/****************************************************/
date:
date:20110310
在对EEPROM 24C01B/02B的操作中发现,在write结束后不能立刻进行读操作,而是要先delay一下才可以。
/****************************************************/
date:20110329
我现在搞不清楚对于我的这个i2c适配器怎么样来使用FIFO的中断方式。
我在想,可以设置接收缓冲区的阈值,当缓冲区的待处理数据个数低于这个值的时候发生一个中断告诉cpu现在可以继续向缓冲区送入新的待处理数据了。问题是如果我不停的向缓冲区送入数据,满了怎么办?datasheet上说满了会发生一个中断,并且会将FSM重置,并不会继续执行任何命令。我猜这个问题的解决办法就是,每次当中断告诉我可以继续向接收缓冲区送入数据的时候,我不要送进去太多,比如我每次最多送入15个就不在继续搞了!另外在datasheet中我还发现一句话可以让我认为:我只要向该适配器发出任何命令(包括写和读)都会被放到TX缓冲区当中!原文如下:
TX_OVERFLOW INT: set 1 if the transmit buffer is full and the processor attempts to issue another i2c commandby writing to the IC_DARA_CMD register. when this bit is set, the I2C FSM will be reset and it will not excute
any command DATA until this bit is cleared!
这样理解的话,只要我对IC_DARA_CMD register 寄存器进行操作都会被作为待处理的命令放到TX—fifo当中。这当然包括我发出一个读取从设备的命名!
对于接收缓冲区来说,我也可以设置一个阈值,当接收缓冲区的待读取数据超过这个值的时候便发生一个中断告诉cpu赶快来取数据吧,要不就快溢出了。如果这个阈值设置的比较大,一直不发生中断怎么办?
//以下是网络中的一种解释,还是有些帮助的
下面我们来看看I2C模块的数据传输:
I2C模块支持主、从,发送、接收,共4种组合传输模式。通过I2C.I2C_CON[10]可以控制模块的主从模式。I2C.I2C_CON[9]可以控制模块的发送接受模式。在传输时,通过I2C.I2C_DATA[7:0]将数据写入FIFO或从FIFO中读取数据。
我们可以有3种方式管理FIFO:中断,轮询和DMA
中断方式是通过设置FIFO的阈值(thresholds)来实现的,在发送数据时,当FIFO中的数据少于这个阈值时会产生一个中断告诉程序FIFO即将空,可以继续向FIFO发送数据。同样,在接收数据时,当FIFO中的数据大于这个阈值时会产生一个中断告诉程序FIFO即将满,需要读取FIFO中的数据。
轮询方式是通过不断查询FIFO状态寄存器,实现对FIFO的管理。不过由于这种方式十分消耗资源(原因么地球人都知道),所以个人觉得应该尽量避免采用这种方式。
DMA模式是通过DMA通道完成数据传输的方式,这种方式在传输时不占用CPU资源,在传输大数据量时优势尤为明显。是本人强烈建议采用的传输模式。
Draining功能,这个用能用于接收的数据长度不是FIFO阈值倍数的情况下。我举个例子来说明这个功能的作用:第一种情况,当一个FIFO的阈值是10bytes,接收的数据是30bytes时,接收的数据长度是FIFO阈值的倍数。当数据第一个10byte数据进入入FIFO时会产生了一个阈值中断我们可以从FIFO中读取数据,接着第二个10bytes数据进入FIFO,最后是第三个10bytes的数据。这样我们可以顺利的通过FIFO的阈值中断将30bytes的数据接收。但当接收的数据长度不是FIFO阈值的倍数时,我们以25bytes为例。当第二个10bytes数据进入FIFO产生了阈值中断并被我们从FIFO中读取,这时还剩下5bytes的数据。当这5bytes数据进入FIFO后没有达到10bytes的FIFO阈值,不会产生中断,这会导致最后这5bytes数据在FIFO中的滞留。Draining功能提供了解决这种问题的一种处理机制。
具体的传输操作在DataSheet中给出了详细的流程图,在此就不重复了。
/****************************************************/
date:20110511
i2c总线上不挂接任何设备,这时候i2c适配器发出一个start命名并寻址一个从设备,因为没有从设备,此时会收到NACK中断,然后i2c适配器将试图发出一个stop信号,但是在测试中示波器始终无法捕获这个stop信号,我怀疑是不是i2c协议不允许在start寻址后直接发送stop命令,但是参考s3c2410的代码发现这样的逻辑是完全可以的,一种用法就是这样做只是为了确定总线上是不是挂了某个设备。这到底是什么原因呢?
刚才又看了一下i2c的协议,里面有一句话这么说“当从机不能响应从机地址时,例如它正在执行一些实时函数不能接收或发送。从机必须使数据线保持高电平,主机然后产生一个停止条件终止传输或者产生重复起始条件开始新的传输”。这句话似乎是说,总线上必须有一个上拉电阻?
所以明天应该这么测试下:
在总线上连接上已经确认可以正常使用的RRPROM测试模块,然后将从设备地址写错做个寻址测试,如果此时能正常执行stop命令,则可验证以上推测是正确的!
/****************************************************/
date: 20110704
rootfs/etc/init.d/rcS
这个shell脚本要干什么呢?
在这里运行那个mdev 就是启动udev的守护进程,(mdev据说是由busybox提供的 udev 的一个简化版)这个进程在发现有设备注册进来的时候就会自动在/dev目录下根据主从设备号创建该设备的文件节点。如果不用mdev的话,我们就需要在这个脚本中用mknod命令自行创建设备的文件节点。如:
mknod /dev/i2c-0 c 89 0
mknod /dev/i2c-1 c 89 1
前面针对芯片i2c adapter 的测试一直是跑的单线程,也没有操作系统。这两天kernel在芯片上终于跑起来了,我也把针对i2c adapter的 kernel driver完成了,初次实验便成功读出了eeprom的数据,真让人兴奋!为了全面测试,我把设备地址写错,做了一下测试,没想到便打印出了这样的内核错误信息“scheduling while atomic” 。
在网上搜了一下,发现这是由于触发了内核的这样一个条件:
if (unlikely(in_atomic() && !current-> exit_state)) {
printk(KERN_ERR "BUG: scheduling while atomic: "
"%s/0x%08x/%d\n ",
current-> comm, preempt_count(), current-> pid);
dump_stack();
}
分析可知应该是在原子操作过程中休眠所致。可是我的驱动中只有一个地方用到了自旋锁,而这部分代码的边界中也没有可能存在的倒置休眠的代码。
折腾了一下午,后来想到,中断当中也是不允许休眠的呀,我是不是在中断处理函数中出现了休眠呢?妈的,检查了好久终于发现在一条处理“未检测到从设备”的逻辑通路中找到了一个msleep调用,改成mdelay后再无报错!这么难检查主要是因为这个中断处理程序写的太长了。。。。但并不是说它要处理的内容太多。。。。呵呵
git diff 原来还可以这么来用!
git diff HEAD xxx/xxx/xxx.x
那一定也可以这么来用:
git diff 484324375778421878446556897545757545 xxx/xxx/xxx.x
/****************************************************/
date:
这个CTP的数据寄存器需要清除,否则就无法拉高中断引脚!!!! 先前设置的是下降沿触发中断,这样当因为某种情况对丢失某此中断后必然导致CTP死锁,表现为中断引脚一直被拉低。由此可见当CTP缓冲区有待读取的数据时会把中断引脚一直拉低,当读完后便会把中断引脚拉高。故而推断,设置为下降沿触发中断调用是不对的,应该设置为低电平触发!
轮询模式时正常的,同时也发现在轮询期间如果缓冲区的数据没有被读完的话,中断引脚会一直被CTP拉低!!!
以上内容是某天写的一个针对it7260电容屏的笔记,这些结论现在看来可能是不对的,但是因为近期没有研究这个电容屏,所以这个内容先留下,以后再说吧。
由于在A5上中断不允许嵌套,所有的GPIO中断公用一个物理中断,然后再中断后以查询方式得到真正的中断引脚,所以在代码中已经实现了当gpio中断发生时进入主中断处理函数,然后屏蔽这唯一的一个物理的gpio中断,然后当中断处理函数退出的时候打开这唯一的一个物理中断,因此从驱动的角度看,已经没有任何必要在某个驱动内部的中断处理函数中禁止中断,在中断处理函数退出的时候打开中断了。。。。。
gpio被当做中断来用的时候,在0x24 offset 位置的每一位是用来清除中断的,如果不清除的话,这个gpio中断就会一直发生,表现就是你会不停的进入中断处理函数,所以要适时的将该位置1以清除该中断
/****************************************************/
date:
/****************************************************/
date:
/****************************************************/
date:
/****************************************************/
date:
/****************************************************/
date:
相关文章推荐
- 软件调试笔记15 - 用户态调试过程: 调试器进程,被调试进程
- omap 3530 boot i2c 调试笔记
- linux下i2c适配器的注册过程
- 技术笔记5_Asp.net:如何在vs环境下调试sqlserver中的存储过程
- SPI 适配器调试笔记: 关键字 pl022 DMA配置 中断配置 SPI主从模式配置 mater slaver SSP配置 中断嵌套 底半部 顶半部
- omap 3530 kernel i2c 调试笔记
- [RK3288][Android6.0] 调试笔记 --- I2C通信失败问题
- 笔记五 第三章机器级表示总结二, 过程,递归,数组,结构与联合,调试及优化
- davinci i2c 设备注册的过程 笔记
- 安卓逆向学习笔记(5) - 在JNI_Onload 函数处下断点避开针对IDA Pro的反调试
- [RK3288][Android6.0] 调试笔记 --- 测试I2C设备正常传输方法
- SRS学习笔记9-rtmp监听线程创建推流线程的过程分析-gdb调试
- 【DEBUG笔记】VSCode调试python提示“vscode调试适配器已意外终止”
- [RK3288][Android6.0] 调试笔记 --- I2C地址的确定
- Java虚拟机学习笔记-记录一次编译OpenJDK8与调试的过程
- cocos2d-x之qt的port版调试的过程【失败了,仅作笔记】
- 软件调试笔记15 - 用户态调试过程:调试会话
- [RK3288][Android6.0] 调试笔记 --- 测试I2C设备正常传输方法【转】
- [软件调试学习笔记]WinDbg演示IA-32 CPU下的Windows 分页机制下的地址转换过程
- TQIMAX6q调试笔记三:EETI的egalax-i2c触摸屏移植