fujei2003
驱动牛犊
驱动牛犊
  • 注册日期2006-04-07
  • 最后登录2008-09-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望7点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
阅读:1868回复:8

pxa270 I2C驱动奇怪问题

楼主#
更多 发布于:2007-12-25 16:01
硬件:
    PXA270,ATmega8
软件:
    WINCE5.0
系统构成:
    PXA270上的I2C做主,ATmega8的做从。
在PB5.0中做了个I2C的驱动,驱动能够正常加载。
在DWORD IIC_Init( PVOID Context  )中映射I2C控制器的地址后,调用probe函数探测I2C从设备,能够正确探测到ATmega8(probe的工作就是向指定的从设备发送一帧命令,然后读取从设备的回应)。

之后用EVC写个测试程序对I2C进行读写测试,均都失败,于是将probe函数放到
DWORD IIC_Write(    DWORD  dwContext,    LPVOID pBuf,    DWORD  count    ) 中,在EVC写的测试程序中对I2C进行写操作,probe在这里就不正确了,发送第一个字节时调试信息显示:BUS ERROR,即I2C的sda线上没有检测到ACK,拿示波器看了下波形,的确不对。

现在的问题是,为什么probe在 IIC_Init 可以,在IIC_Write却出错?

I2C控制器地址映射代码如下:
#define PAGE_SIZE 0x1000
ptr = VirtualAlloc(0,PAGE_SIZE,MEM_RESERVE,PAGE_NOACCESS);
    
    if (ptr == NULL) {
        printf("VirtualAlloc failed!  size=0x%x, (0x%x)\n",size,GetLastError());
        return(FALSE);
    }
//i2c
printf("I2C VirtualAddress = 0x%x\n",I2C_BASE_U_VIRTUAL);
    if ( !VirtualCopy(    (PVOID)ptr,
                    (PVOID)(I2C_BASE_U_VIRTUAL+0x1000),
                    PAGE_SIZE,
                    PAGE_READWRITE | PAGE_NOCACHE )
    ) {
        printf("VirtualCopy failed!: \n");
        return(FALSE);
    }  
pI2C_v = ptr + 0x680 ;
fujei2003
驱动牛犊
驱动牛犊
  • 注册日期2006-04-07
  • 最后登录2008-09-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望7点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-12-26 12:57
望高人指点下~~~~~
ziyun
驱动小牛
驱动小牛
  • 注册日期2003-07-28
  • 最后登录2009-05-31
  • 粉丝0
  • 关注0
  • 积分17分
  • 威望109点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-12-26 15:47
I2C_BASE_U_VIRTUAL,改用物理地址看看

最好的做法是做成驱动,用readfile或writefile,iocontrol来弄,简单
modernhill
驱动小牛
驱动小牛
  • 注册日期2004-05-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分98分
  • 威望278点
  • 贡献值0点
  • 好评度172点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-12-26 16:27
IIC_init操作之后,总线是否已被释放?我没有用过probe,能否将其原理贴出来看看?
fujei2003
驱动牛犊
驱动牛犊
  • 注册日期2006-04-07
  • 最后登录2008-09-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望7点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2007-12-26 17:23
最终的目的就是做成驱动,在应用程序中调用writefile出错:ISR寄存器的值在发送从机地址后始终为0X442。这才在驱动里写个probe看看问题在那里。
probe的流程:
向从机发送:0X03,0X00,0X03
读取从机回复,若从机回应为:0x03,0x01,0x04表示探测到从机,总线也正常
代码如下:
int write_iic_bus(P_XLLP_I2C_T I2C_regs,unsigned char data,unsigned char ByteType)
{
    int timeout;
    U32 isr;

    // 1 Load target slave address and R/nW bit in the IDBR. R/nW must be 0 for a write.
    I2C_regs->IDBR=data;
printf("data = 0x%x\n",data);    
    // 2.Initiate the write. Set ICR[START], clear ICR[STOP], clear ICR[ALDIE], set ICR[TB]
    if(FRISTBYTE == ByteType){
        I2C_regs->ICR |= ICR_START;
        I2C_regs->ICR &= (~ICR_STOP);
    }else if (MIDBYTE == ByteType){
        I2C_regs->ICR &= (~ICR_START);
        I2C_regs->ICR &= (~ICR_STOP);
    }else if(LASTBYTE == ByteType){
        I2C_regs->ICR &= (~ICR_START);
        I2C_regs->ICR |= (ICR_STOP);
    }
//printf("ICR= 0x%x\n",I2C_regs->ICR);
    
    I2C_regs->ICR |= ICR_TB;

    /* 3.When an IDBR Transmit Empty interrupt occurs.
    //printf("TB is set:ICR= 0x%x\n",I2C_regs->ICR);
    timeout=0;    
    do{
        isr = I2C_regs->ISR;
        printf("ISR = 0x%x \t timeout = %d\n",isr,timeout);
        if(isr&ISR_BED)
        {
            printf("bus error-no ack\n");
            I2C_regs->ICR &= (~ICR_TB);
            return -1;
        }
        if(isr&ISR_ITE)
        {
            I2C_regs->ISR |= ISR_ITE;
            I2C_regs->ICR &= (~ICR_TB);    
            return 1;
        }
        timeout++;
        if(I2C_TIMEOUT < timeout)
        {
            printf("time out\n");
            I2C_regs->ICR &= (~ICR_TB);
            return -1;
        }
        //usWait(25);
    }while( 1 );    
    return 1;
}

probe代码片段:


if( write_iic_bus(I2C_regs,(I2C_SLAVE_DEVICE_ADDR<<1)&0xfe,FRISTBYTE) < 0)
        {    i2c_reset(I2C_regs);
            i2c_pxa_data.reset_mcu();
            
        }
      
        //printf("probe_buf[0]\n");
        for(i=0;i < 3-1 ; i++)
        {
            if( write_iic_bus(I2C_regs,probe_buf,MIDBYTE) < 0)
            {    i2c_reset(I2C_regs);
                i2c_pxa_data.reset_mcu();
                
            }
            //printf("probe_buf\n");
        }        
        //printf("probe_buf[2]\n");
        if( write_iic_bus(I2C_regs,probe_buf[2],LASTBYTE) < 0)
        {    i2c_reset(I2C_regs);
            i2c_pxa_data.reset_mcu();
            
        }
        //read response
        memset(read_buff,0,256);
        if( !i2c_read_nByte(pHWhead,read_buff,3) )
        {
            for(i=0;i<3;i++)
                printf("0x%x ",read_buff);
        }
modernhill
驱动小牛
驱动小牛
  • 注册日期2004-05-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分98分
  • 威望278点
  • 贡献值0点
  • 好评度172点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2007-12-27 10:15
write_iic_bus函数没有完全按照SPEC上的流程来写,我没有验证过你这样写是否可以,不过我想应该完全按照SPEC来写吧,有两点:一是在送FIRSTBYTE,以及MIDBYTE和LASTBYTE的时候,你没有SET或者CLEAR寄存器ICR-> ALDIE,还有就是在发送从机地址以后没有执行 ”Write 0b1to the ISR[ALD] bit if set.“。还有就是i2c_read_nByte这个函数始终都工作正常吗,读和写道理应该是一样的啊。。。
fujei2003
驱动牛犊
驱动牛犊
  • 注册日期2006-04-07
  • 最后登录2008-09-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望7点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2007-12-27 11:43
我再查下流程

奇怪的就是在两个位置分别调用probe,结果却不同
fujei2003
驱动牛犊
驱动牛犊
  • 注册日期2006-04-07
  • 最后登录2008-09-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望7点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2007-12-29 15:10
流程没问题的。
不知道驱动里面XXX_Init与XXX_Write的环境有什么区别,是否有其他的因素影响,
fujei2003
驱动牛犊
驱动牛犊
  • 注册日期2006-04-07
  • 最后登录2008-09-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望7点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2008-01-04 17:29
总算查出问题了,单片机被其它驱动复位了,一直处于复位状态
游客

返回顶部