⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iic.cpp

📁 IIC WINCE5.0 流接口驱动程序及测试
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    if (WAIT_OBJECT_0 != SyncIst(pI2C, TX_TIMEOUT))
	{
        DEBUGMSG(ZONE_WRITE|ZONE_ERR,(TEXT("TX_TIMEOUT.1\r\n")));
        goto _done;
    }

    // get ACK
    while(1)
    {
        pI2C->State  = WRITE_ACK;
        pI2C->Status = INVALID_IICSTAT;
        
        rIICDS   = (UCHAR)SlaveAddr;
        rIICSTAT = MTX_START;
        rIICCON  = RESUME_ACK;

        while ( pI2C->Status == INVALID_IICSTAT ) 
		{
			Sleep(20);
            if (WAIT_OBJECT_0 != SyncIst(pI2C, TX_TIMEOUT)) //等待超时,否则容易死机
			{
                DEBUGMSG(ZONE_WRITE|ZONE_ERR,(TEXT("TX_TIMEOUT.2\r\n")));
                break;
            }
        }

        // done when ACK received
        if ( !(pI2C->Status & 0x1))
            break; 
    }

_done:
    rIICSTAT = MTX_STOP;     
    rIICCON  = RESUME_ACK;  

    pI2C->State = IDLE;
    pI2C->pData  = NULL;
    pI2C->DataCount = INVALID_DATA_COUNT;

    dwErr = pI2C->LastError;
    LeaveCriticalSection(&pI2C->RegCS);
    DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("-I2C_Write: %u \r\n"), dwErr));
    return dwErr;
}
//--------------------------------------------------------------------------------------------
// When you execute code in kernel mode, in contrast to user mode, you must have access 
// to the entire physical memory. Because an interrupt service thread (IST) runs in user 
// mode and could need access to a block of physical memory to communicate with a device,
// you must map this block of memory to the address space in which the IST runs.
// If a device driver creates a thread, and in that thread you call MapPtrToProcess, you 
// must use GetCurrentPermissions and SetProcPermissions to retrieve and reset process 
// permissions.
//--------------------------------------------------------------------------------------------
static DWORD I2C_IST(LPVOID Context)
{
    PI2C_CONTEXT pI2C = (PI2C_CONTEXT)Context;
    DWORD i2cSt,dwRight;
    BOOL bDone = FALSE;
   	volatile int i,j = 0;

    if ( !pI2C )
	{
        TEST_TRAP;
        return ERROR_INVALID_PARAMETER;
    }
    do 
	{
        if (pI2C->Mode == INTERRUPT)	//中断处理方式
		{
            DWORD we;
            bDone = FALSE;
            
            we = WaitForSingleObject(pI2C->ISTEvent, INFINITE);	//等中断到来

            // clear the interrupt here because we re-arm another below
            InterruptDone(gIntrIIC);

            // Ensure correct state initiated by Read/Write
            //DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("I2C_IST[%u, %d] \r\n"), pI2C->State, pI2C->DataCount));

            switch(pI2C->State)
            {
                case OFF:
                    //DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("I2C_IST: ExitThread \r\n")));
                    ExitThread(ERROR_SUCCESS);
                    break;

                case IDLE:
                    //DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("I2C_IST: IDLE \r\n")));
                    continue;
                    break;

                default:
                    if (pI2C->State != WRITE_ACK && 
                        pI2C->State != RESUME &&
                        pI2C->DataCount == INVALID_DATA_COUNT) 
					{
                        //DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("I2C_IST: INVALID_DATA_COUNT\r\n")));
                        continue;
                    }
                    break;
            }
        }
        //EnterCriticalSection(&pI2C->RegCS);
        i2cSt = rIICSTAT; 
        if (i2cSt & 0x8)	//总线仲裁失败
        {
			//DEBUGMSG(ZONE_ERR,(TEXT("I2C_IST[%u, %d]: bus arbitration failed \r\n"), pI2C->State, pI2C->DataCount));
		}
        if (i2cSt & 0x4)	//地址不相符
		{
            //DEBUGMSG(ZONE_ERR,(TEXT("I2C_IST[%u, %d]: slave address matches IICADD \r\n"), pI2C->State, pI2C->DataCount));
		}
        if (i2cSt & 0x2)	//接收到0地址
		{
            //DEBUGMSG(ZONE_ERR,(TEXT("I2C_IST[%u, %d]: received slave address 0x0 \r\n"),pI2C->State, pI2C->DataCount));
		}
        if (i2cSt & 0x1)	//ACK没有接收到
		{
            //DEBUGMSG(ZONE_READ|ZONE_WRITE,(TEXT("I2C_IST[%u, %d]: ACK NOT received \r\n"), pI2C->State, pI2C->DataCount));
		}

        __try 
		{
            switch(pI2C->State)
            {
                case IDLE:
                case SUSPEND:
                    continue;
                    break;
                    
                case RESUME:
                    //DEBUGMSG(ZONE_WRN, (TEXT("I2C_IST: RESUME \r\n")));
                    InitRegs(pI2C);
                    pI2C->LastError = ERROR_OPERATION_ABORTED;
                    SetEvent(pI2C->DoneEvent);
                    break;

                case SET_READ_ADDR:
                    if ( (pI2C->DataCount--) == 0 )
                    {
                        //DEBUGMSG(ZONE_READ|ZONE_TRACE, (TEXT("A2[%d] \r\n"),pI2C->DataCount ));
                        bDone = TRUE;
                        break;
                    }

                    //DEBUGMSG(ZONE_READ|ZONE_TRACE, (TEXT("A1[%d]: 0x%X \r\n"), pI2C->DataCount, pI2C->WordAddr));
                    // write word address
                    // For setup time of SDA before SCL rising edge, rIICDS must be written 
                    // before clearing the interrupt pending bit.
                    if (pI2C->Flags.WordAddr) 
					{
                        rIICDS = pI2C->WordAddr;
			            for(i=0;i<10;i++);        //For setup time until rising edge of IICSCL
                        // clear interrupt pending bit (resume)
                        rIICCON = RESUME_ACK;
                        pI2C->Flags.WordAddr = FALSE;
                    }
                    break;
                case READ_DATA:                    
                    ASSERT(pI2C->pData);
                    dwRight=GetCurrentPermissions();	//获得当前进程的权限
					SetProcPermissions(0xFFFFFFFF);		//设置当前的权限为最高权限
					if ( (pI2C->DataCount--) == 0 )		//if reciver over data
                    {
                        bDone = TRUE;
                        *pI2C->pData = (UCHAR)rIICDS;
                        pI2C->pData++;
                        
                        rIICSTAT = MRX_STOP;    
                        rIICCON  = RESUME_ACK;  // resume operation.
						//Sleep(100);				//for setup time until rising edge of IICSCL
                        //The pending bit will not be set after issuing stop condition.
						SetProcPermissions(dwRight);	//恢复原来的权限
                        break;    
                    }
                    //接收随机读返回的器件地址
					// Drop the returned Slave WordAddr?
                    if ( pI2C->Flags.DropRxAddr )
                    {
                        pI2C->RxRetAddr = (UCHAR)rIICDS;
                        pI2C->Flags.DropRxAddr = FALSE;
                        //DEBUGMSG(ZONE_READ|ZONE_TRACE,(TEXT("Drop: 0x%X \r\n"), pI2C->RxRetAddr));
                    } 
					else 
					{
						*pI2C->pData = (UCHAR)rIICDS;
                        pI2C->pData++;
                    }
			
                    // The last data is read with no ack.
                    if ( pI2C->DataCount == 0 ) 
                        rIICCON = RESUME_NO_ACK;    // resume operation with NOACK.  
					else 
                        rIICCON = RESUME_ACK;       // resume operation with ACK
					SetProcPermissions(dwRight);
                    break;

                case WRITE_DATA:                        
                    ASSERT(pI2C->pData);
                    dwRight=GetCurrentPermissions();	//获得当前进程的权限
					SetProcPermissions(0xFFFFFFFF);		//设置当前的权限为最高权限
					if ( (pI2C->DataCount--) == 0 )
                    {
                        //DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W3[%d] \r\n"), pI2C->DataCount));
                        bDone = TRUE;
                        rIICSTAT = MTX_STOP;    
                        rIICCON  = RESUME_ACK;  // resume operation.
						//Sleep(100);				//for setup time until rising edge of IICSCL
                        //The pending bit will not be set after issuing stop condition.
						SetProcPermissions(dwRight);	//恢复原来的权限
                        break;    
                    }
                    
                    if (pI2C->Flags.WordAddr) 
					{
                        rIICDS = pI2C->WordAddr;
                        //DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W1[%d]: 0x%X \r\n"),pI2C->DataCount, pI2C->WordAddr));
                        pI2C->Flags.WordAddr = FALSE;
                    } 
					else 
					{
                        //DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W2[%d]: 0x%X \r\n"),pI2C->DataCount, *pI2C->pData));
                        rIICDS = (UCHAR)*pI2C->pData;
                        pI2C->pData++;
                    }
		            for(i=0;i<10;i++);        //For setup time until rising edge of IICSCL
                    rIICCON = RESUME_ACK;   // resume operation.
					SetProcPermissions(dwRight);	//恢复原来的权限
					break;

                case WRITE_ACK:
                    //DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("WRITE_ACK \r\n") ));
                    pI2C->Status = i2cSt;
                    bDone = TRUE;
                    break;

                case IO_COMPLETE:
                    //DEBUGMSG(ZONE_IST, (TEXT("IO_COMPLETE \r\n")));
                    bDone = TRUE;
                    break;

                case IO_ABANDONED:
                    //DEBUGMSG(ZONE_ERR|ZONE_WRN,(TEXT("IO_ABANDONED \r\n") ));
                    bDone = TRUE;
                    break;

                default:
                    //DEBUGMSG(ZONE_ERR,(TEXT("!!! I2C_IST ERROR: Invalid State: %u !!!\r\n"), pI2C->State));
                    bDone = TRUE;
                    break;    
            }
        
        }
		_except(EXCEPTION_EXECUTE_HANDLER) 
		{
            
            rIICSTAT = (pI2C->State == READ_DATA) ? MRX_STOP : MTX_STOP;
            rIICCON  = RESUME_ACK;
            pI2C->DataCount = INVALID_DATA_COUNT;
            pI2C->LastError = GetExceptionCode();
      		SetProcPermissions(dwRight);
		}
            
        if (bDone) 
		{
			pI2C->pData=(LPBYTE)UnMapPtr(pI2C->pData);
            //DEBUGMSG(ZONE_IST, (TEXT("SetEvent DONE\r\n")));
            SetEvent(pI2C->DoneEvent);
        }            
        //LeaveCriticalSection(&pI2C->RegCS);
    } while (pI2C->Mode == INTERRUPT);
    return ERROR_SUCCESS;
}


BOOL HW_PowerUp(PI2C_CONTEXT pI2C)
{
    pI2C->State = RESUME;
	InitRegs(pI2C);
    return TRUE;
}


BOOL HW_PowerDown(PI2C_CONTEXT pI2C)
{
    // set idle
    rIICSTAT = M_IDLE;
    pI2C->State = SUSPEND;
    return TRUE;
}


/*BOOL HW_PowerCapabilities(PI2C_CONTEXT pI2C,PPOWER_CAPABILITIES ppc)
{
    memset(ppc, 0, sizeof(*ppc));

    //
    // SPECIAL CASE: support D0 only. 
    // If we power off outside of system state Suspend then the PCF50606 
    // will no longer work, which means the whole system could be forced off 
    // by an internal PCF transition. The Battery driver would not work either.
    //
    // If we knew we did not have to support the PCF50606,
    // or didn't know what I2C Client drivers we could have,
    // then we should support D0 and D4. In this case you would use
    // RegisterPowerRelationship and serve as the Bus driver (parent/proxy)
    // to forward power transitions to all the I2C Client drivers.
    //
    ppc->DeviceDx = 0x1;    // D0

    // no wake
    // no inrush

    // Report our power consumption in uAmps rather than mWatts. 
//    ppc->Flags = POWER_CAP_PREFIX_MICRO | POWER_CAP_UNIT_AMPS;
    ppc->Power[D0] = 600;   // 0.6 mA or 600 uA @ 200 MHz

    // no latency issues

    return TRUE;
}


BOOL HW_PowerSet(PI2C_CONTEXT pI2C,PCEDEVICE_POWER_STATE pDx)
{   
    CEDEVICE_POWER_STATE NewDx = *pDx;

    if ( VALID_DX(NewDx) ) 
    {
        // We only support D0, so do nothing.
        // Just return current state.
        pI2C->Dx = *pDx = D0;

        DEBUGMSG(ZONE_POWER, (TEXT("I2C: IOCTL_POWER_SET: D%u => D%u \r\n"),
            NewDx, pI2C->Dx));

        return TRUE;
    }

    return FALSE;
}


BOOL HW_PowerGet(PI2C_CONTEXT pI2C,PCEDEVICE_POWER_STATE pDx)
{   
    // return our Current Dx value
    *pDx = pI2C->Dx;

    DEBUGMSG(ZONE_POWER, (TEXT("I2C: IOCTL_POWER_GET: D%u \r\n"), pI2C->Dx));

    return TRUE;
}
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -