打印
[其他ST产品]

str710 iic 错误

[复制链接]
6161|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
shenmou|  楼主 | 2007-4-2 16:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
iic, ST, I2c, se, AD


我在用 str710 的iic 和 isl1208 rtc 芯片连接。 使用过程中发现上电时候出现 iic 总线错误的情况  

具体表象为  iic start 、发送从设备地址后,等待 I2C_ENDAD 死循环。
  /* Generate the START condition */
  I2C_STARTGenerate (I2C, ENABLE);
  /* Wait until SB bit is set */
  while (I2C_FlagStatus (I2C, DIRECT, I2C_SB )== RESET);
  /* Send the EEPROM address with LSB bit reset */
  I2C_AddressSend (I2C,DeviceADDRESS,I2C_Mode7, I2C_TX);
  /* Wait until ENDAD bit is set */  
  while (I2C_FlagStatus (I2C, DIRECT, I2C_ENDAD )== RESET); --》死机

检查寄存器发现:M/SL 被清零  ARLO 被置位。

iic 被从主模式改成了从模式。
沙发
shenmou|  楼主 | 2007-4-3 13:44 | 只看该作者

没有人可以回答吗?

使用特权

评论回复
板凳
浪淘沙| | 2007-4-3 13:56 | 只看该作者

正在处理中。。。。

使用特权

评论回复
地板
shenmou|  楼主 | 2007-4-4 08:59 | 只看该作者

等待中ing

使用特权

评论回复
5
shenmou|  楼主 | 2007-4-4 09:16 | 只看该作者

iic 错误,调试实况

使用特权

评论回复
6
shenmou|  楼主 | 2007-4-4 09:19 | 只看该作者

发送地址前

使用特权

评论回复
7
shenmou|  楼主 | 2007-4-5 08:46 | 只看该作者

等待中 2

使用特权

评论回复
8
ST_ARM| | 2007-4-5 10:40 | 只看该作者

图片检测

根据你的图片,我对照我的调试,未能重现你的现象,我将将你的问题提交给欧洲的工程师。另外你能否另换一片芯片再测试一下。

使用特权

评论回复
9
shenmou|  楼主 | 2007-4-5 11:03 | 只看该作者

它是偶尔出现的

它不是经常性出现的现象,一般在设备上电启动的比较容易出现。 而且,如果上电的时候出现了这样的错误,接下来我继续上电重启还是比较容易出现的。但是,当设备正常运行了,就不会出现这个问题。

我想要了解:
A、它是通过什么判断当前出现 ‘总线冲突’,
B、while (I2C_FlagStatus (I2C, DIRECT, I2C_ENDAD )== RESET);  I2C_ENDAD  在什么条件下被置位, 1、收到从设备的 ack信号。2、缓存中的数据发送完成。3、其他,请解释。

使用特权

评论回复
10
浪淘沙| | 2007-4-5 11:24 | 只看该作者

请楼主把这段程序编译后的汇编列表发给我们

同时把I2C_FlagStatus()函数的汇编列表发给我们。

怀疑是编译器在编译I2C_FlagStatus()函数时有问题。

这个函数中用到了可变参数表的技术,我们要确认不是由于你的编译器所造成的问题。

可发email到:mcu.china@st.com

谢谢


关于I2C_ENDAD的设置,在芯片资料的180页有这样的解释:
ENDAD: End of address transmission.
This bit is set by hardware when:
- 7-bit addressing mode: the address byte has been transmitted;
- 10-bit addressing mode: the MSB and the LSB have been transmitted during the addressing phase.
When the master needs to receive data from the slave, it has to send just the MSB of the slave address once again; hence the ENDAD flag is set, without waiting for the LSB of the address.It is cleared by software by reading SR2 and a following write to the CR or by hardware when the interface is disabled (PE=0).
0: No end of address transmission
1: End of address transmission

即当I2C地址发送完成后,此位置1。

使用特权

评论回复
11
shenmou|  楼主 | 2007-4-5 12:34 | 只看该作者

可变参数

我也注意到了这个问题,这里是直接访问的I2C_FlagStatus (I2C, DIRECT, I2C_ENDAD )  函数里面做了判断做直接访问的时候和 可变参数无关。

另外 “在芯片资料的180页有这样的解释” 很含糊,只是讲发送完成会被置位。但是,没有解释arm 通过什么判断发送完成了。

使用特权

评论回复
12
shenmou|  楼主 | 2007-4-5 12:35 | 只看该作者

汇编代码

/*******************************************************************************
* Function Name  : I2C_FlagStatus
* Description    : Checks whether any I2C Flag is set or not.
* Input          : I2Cx ( I2C0 or I2C1 )
*                  Access(DIRECT or INDIRECT)
*                  Flag : the flag to be read
*                  input 4: an (u8) variable needed in the case
*                                     of the INDIRECT access
* Return         : the NewState of the Flag (SET or RESET).
*******************************************************************************/
FlagStatus I2C_FlagStatus (I2C_TypeDef *I2Cx, RegisterAccess Access, I2C_Flags Flag, ...)
{
[0xe92d000f]   stmfd    r13!,{r0-r3}
[0xe92d4008]   stmfd    r13!,{r3,r14}
  u32 Tmp=0;
  
  if (Access == DIRECT)
[0xe1a02001]   mov      r2,r1
[0xe3520001]   cmp      r2,#1
[0xe59d1010]   ldr      r1,[r13,#0x10]
[0x1a000007]   bne      0x400087ec  ; (I2C_FlagStatus + 0x38)
    /* Store in Tmp variable the register where is located the flag */
    Tmp = I2C_GetStatus(I2Cx)&Flag;
[0xe0000001]   and      r0,r0,r1
[0xea000006]   b        0x40008808  ; (I2C_FlagStatus + 0x54)
  else
  { 
  /* Get the fourth register */
    va_list list;  
    
    va_start(list,Flag);
[0xe28d0014]   add      r0,r13,#0x14
[0xe58d0000]   str      r0,[r13,#0]
    Tmp = va_arg(list,u32);
[0xe59d2000]   ldr      r2,[r13,#0]
[0xe59d0014]   ldr      r0,[r13,#0x14]
[0xe2822004]   add      r2,r2,#4
[0xe58d2000]   str      r2,[r13,#0]
    Tmp&=Flag;
[0xe0000001]   and      r0,r0,r1
    // Tmp = ((u16)*((u32 *)&Flag + sizeof(Flag)))&Flag;
  }
  /* Return the Flag NewState */
  return Tmp != 0 ? SET : RESET;
[0xe3500000]   cmp      r0,#0
[0x0a000002]   beq      0x4000881c  ; (I2C_FlagStatus + 0x68)
[0xe3a00001]   mov      r0,#1
[0xe28dd004]   add      r13,r13,#4
......
[0xe3a00000]   mov      r0,#0
[0xeafffffb]   b        0x40008814  ; (I2C_FlagStatus + 0x60)
}
[0xe49df014]   ldr      pc,[r13],#0x14

使用特权

评论回复
13
浪淘沙| | 2007-4-5 13:29 | 只看该作者

STR710 IIC函数调用的错误

从你给出的编译结果看,在函数I2C_FlagStatus()中下面这行的调用I2C_GetStatus()不见了:
Tmp = I2C_GetStatus(I2Cx)&Flag;

另外,在(Access == INDIRECT)的处理可变参数表部分,编译结果似乎是对的。

我们正在修改函数I2C_FlagStatus()的内容,把DIRECT和INDIRECT部分分成两个函数,借此回避可变参数表的使用。不同的编译器对可变参数表有不同的处理,我们也发现IAR在这里的处理有问题;记得前几天有人也提出过类似的问题,好像麻烦不少;回避了可变参数表的使用,也就回避了编译器在这方面的缺陷。


关于芯片通过什么判断发送完成,可以参考174页的图;如Master发送地址的情况,参看7-bit Master transmitter部分EV6的说明,IIC模块是在收到Slave的Acknowledge后置位ENDAD为1。

使用特权

评论回复
14
ST_ARM| | 2007-4-5 15:06 | 只看该作者

修改I2C.c的函数

希望使用i2c的客户目前对I2C.c的函数进行修改,后期我们对I2C.c的函数的修改会在此进行通告。

去除掉i2c.c中的这个函数:FlagStatus I2C_FlagStatus (I2C_TypeDef *I2Cx, RegisterAccess Access, I2C_Flags Flag,...);

将应用程序中的I2C_FlagStatus( I2C1, DIRECT, I2C_SB)函数替换为下面的函数:
FlagStatus I2C_FlagStatus_1 (I2C_TypeDef *I2Cx, I2C_Flags Flag)
{
    return (I2C_GetStatus(I2Cx) & Flag) != 0 ? SET : RESET;        // Return the Flag NewState
}

将程序中的I2C_FlagStatus( I2C1, INDIRECT, I2C_AF, I2CStatus )函数替换为下面的函数:
FlagStatus I2C_FlagStatus_2 (I2C_TypeDef *I2Cx, I2C_Flags Flag, u32 cStatus)
{
    return (cStatus & Flag) != 0 ? SET : RESET;        // Return the Flag NewState
}

使用特权

评论回复
15
shenmou|  楼主 | 2007-4-5 19:32 | 只看该作者

I2C_GetStatus(I2Cx) 是 inline 的

I2C_GetStatus(I2Cx)  是 inline 的. 从看到的现象来判断,寄存器的值已经发生的改变,指示当前遇到总线冲突.并且,iic 返回到了默认的从模式.

要么是我们主板的布线问题,引起了干扰.  但如果是这样的话库函数的设计要修改下,while (I2C_FlagStatus (I2C, DIRECT, I2C_ENDAD )== RESET);  如果数据干扰的时候极其容易死机.

使用特权

评论回复
16
浪淘沙| | 2007-4-5 20:49 | 只看该作者

还是觉得你的函数调用有问题

根据你提供的代码,在应该出现调用I2C_GetStatus()的地方,只有一条指令:
   Tmp = I2C_GetStatus(I2Cx)&Flag;
[0xe0000001]   and      r0,r0,r1

请问这里r0的值等于多少?你说I2C_GetStatus(I2Cx)是inline的,那么对应哪条指令呢?

使用特权

评论回复
17
shenmou|  楼主 | 2007-4-6 09:45 | 只看该作者

interleave disassambly 显示不是很完整的

interleave disassambly 显示不是很完整的,下面才是真正的汇编码

I2C_FlagStatus    [0xe92d000f]   stmfd    r13!,{r0-r3}
400087b8    [0xe92d4008]   stmfd    r13!,{r3,r14}
400087bc    [0xe1a02001]   mov      r2,r1
400087c0    [0xe3520001]   cmp      r2,#1
400087c4    [0xe59d1010]   ldr      r1,[r13,#0x10]
400087c8    [0x1a000007]   bne      0x400087ec  ; (I2C_FlagStatus + 0x38)
400087cc    [0xe5d02000]   ldrb     r2,[r0,#0]
400087d0    [0xe5d03004]   ldrb     r3,[r0,#4]
400087d4    [0xe5d00008]   ldrb     r0,[r0,#8]
400087d8    [0xe1830400]   orr      r0,r3,r0,lsl #8
400087dc    [0xe3c00cc0]   bic      r0,r0,#0xc000
400087e0    [0xe1800702]   orr      r0,r0,r2,lsl #14
400087e4    [0xe0000001]   and      r0,r0,r1
400087e8    [0xea000006]   b        0x40008808  ; (I2C_FlagStatus + 0x54)
400087ec    [0xe28d0014]   add      r0,r13,#0x14
400087f0    [0xe58d0000]   str      r0,[r13,#0]
400087f4    [0xe59d2000]   ldr      r2,[r13,#0]
400087f8    [0xe59d0014]   ldr      r0,[r13,#0x14]
400087fc    [0xe2822004]   add      r2,r2,#4
40008800    [0xe58d2000]   str      r2,[r13,#0]
40008804    [0xe0000001]   and      r0,r0,r1
40008808    [0xe3500000]   cmp      r0,#0
4000880c    [0x0a000002]   beq      0x4000881c  ; (I2C_FlagStatus + 0x68)
40008810    [0xe3a00001]   mov      r0,#1
40008814    [0xe28dd004]   add      r13,r13,#4
40008818    [0xe49df014]   ldr      pc,[r13],#0x14
4000881c    [0xe3a00000]   mov      r0,#0
40008820    [0xeafffffb]   b        0x40008814  ; (I2C_FlagStatus + 0x60)

使用特权

评论回复
18
shenmou|  楼主 | 2007-4-6 09:47 | 只看该作者

I2C_GetStatus(I2Cx) 缺少部分

inline u32 I2C_GetStatus(I2C_TypeDef *I2Cx)
{
  u8 i2c_cr, i2c_sr1,i2c_sr2;

  i2c_cr  = I2Cx->CR;
[0xe5d02000]   ldrb     r2,[r0,#0]
......
[0xe5d01000]   ldrb     r1,[r0,#0]
  i2c_sr1 = I2Cx->SR1;
[0xe5d03004]   ldrb     r3,[r0,#4]
......
[0xe5d02004]   ldrb     r2,[r0,#4]
  i2c_sr2 = I2Cx->SR2;
[0xe5d00008]   ldrb     r0,[r0,#8]
......
[0xe5d03008]   ldrb     r3,[r0,#8]

 return (((i2c_cr)<<14)|(i2c_sr1|(i2c_sr2<<8))&0x3FFF);
[0xe1830400]   orr      r0,r3,r0,lsl #8
[0xe3c00cc0]   bic      r0,r0,#0xc000
[0xe1800702]   orr      r0,r0,r2,lsl #14
......
[0xe1822403]   orr      r2,r2,r3,lsl #8
[0xe3c22cc0]   bic      r2,r2,#0xc000
[0xe1824701]   orr      r4,r2,r1,lsl #14
}

使用特权

评论回复
19
shenmou|  楼主 | 2007-4-11 09:22 | 只看该作者

这个问题,欧洲那边有答案了没?

这个问题还是存在的,现在只是用软件的方法在遇到这个问题的时候避开。但是,最好还是可以知道硬件上面引起这个错误的原因。

使用特权

评论回复
20
香水城| | 2007-4-11 09:53 | 只看该作者

楼主能否把这部分的电路图发上来

请用示波器看一下在出错时SDA和SCL线上波形;这种问题在软件上看不出,而你的硬件情况我们也看不见;在我们的板上没有发现你说的问题。

因为不能正确判断你的问题所在,我们不会把你的问题转到欧洲的工程师,除非涉及到芯片的问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

34

帖子

0

粉丝