wince +6410 IIC 驱动问题
最近调试6410的IIC驱动,要求上层将数据写入eeprom永久保存,开始由于bsp包里的camera驱动里,有操作IIC的示例,自然就参考camera驱动里依葫芦画瓢就行了,
// Initialize IIC1
hI2C = CreateFile(_T("IIC0:"), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if(INVALID_HANDLE_VALUE == hI2C)
{
MessageBox(L"无法打开I2C");
dwErr = GetLastError();
return FALSE;
}
if (!DeviceIoControl(hI2C,
IOCTL_IIC_SET_CLOCK,
&IICClock, sizeof(UINT32),
NULL, 0,
&bytes, NULL) )
{
dwErr = GetLastError();
MessageBox(L"无法设置I2C clock");
return FALSE;
}
uiIICDelay = 0;
if ( !DeviceIoControl(hI2C,
IOCTL_IIC_SET_DELAY,
&uiIICDelay, sizeof(UINT32),
NULL, 0,
&bytes, NULL) )
{
dwErr = GetLastError();
MessageBox(L"无法设置I2C delay");
return FALSE;
}
打开iic 没有问题,设置时钟 和延时时间就出问题了,iic压根就没反应,后打开调试信息,发现进入IIC_IOControl 后,到
if (GetDirectCallerProcessId() != GetCurrentProcessId()){
RETAILMSG(1, (TEXT(" mao IIC_IOControl 1: \r\n"))); //add mao
return ERROR_ACCESS_DENIED;
}
就没往下走了,
后来网上查资料才知道本身驱动不支持应用程序调用,是给其他驱动程序调用的。因为在IIC_IOControl前面添加了个判断
if (GetDirectCallerProcessId() != GetCurrentProcessId()){
RETAILMSG(1, (TEXT(" mao IIC_IOControl 1: \r\n"))); //add mao
return ERROR_ACCESS_DENIED;
}
应用程序调用时需要将上面的判断注释掉,注释掉后,可以读写了,可有好几次 连续读数据时就报错,
Exception 'Data Abort' (4): Thread-Id=01970006(pth=8617c2ec), Proc-Id=00400002(pprc=82ab9308) 'NK.EXE', VM-active=058b0006(pprc=84954618) 'explorer.exe'
PC=c0e32b98(s3c6410_iic.dll+0x00002b98) RA=c0e32b10(s3c6410_iic.dll+0x00002b10) SP=d285fe64, BVA=001aeee8
一直纳闷,查源代码没找出根本原因,无意中看到一文章,说可能是IIC_IO_DESC这个参数里面包括指针,需要进行指针的映射,如下:
BOOL HW_Read (PHW_OPEN_INFO pOpenContext, PIIC_IO_DESC pInData ,PIIC_IO_DESC pOutData)
{
HRESULT hr; //add mao for iic
BOOL retVal = TRUE; // Initialize to success
PBYTE MappedEmbedded;
PBYTE Marshalled;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+HW_Read(0x%X)\r\n"),
pOpenContext));
HW_SetRegister(pOpenContext);
HW_Write(pOpenContext, pInData);
ResetEvent(g_hTransferDone);
// Wait until IIC bus is free.
if(!WaitForReg((PVOID)&(g_pIICReg->IICSTAT), (1<<5), 0x0, TIMEOUT_MS_RX))
{
DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]IIS BUS is busy.\r\n")));
retVal = FALSE;
goto CleanUp;
}
// 内核地址映射
hr = CeOpenCallerBuffer((PVOID*) &MappedEmbedded, pOutData->Data, pOutData->Count, ARG_O_PTR, FALSE);
hr = CeAllocAsynchronousBuffer((PVOID*) &Marshalled, MappedEmbedded, pOutData->Count, ARG_O_PTR);
g_pcIIC_BUFFER = Marshalled;//pOutData->Data;
g_uIIC_PT = 0;
g_uIIC_DATALEN = pOutData->Count;
g_pIICReg->IICCON |= (1<<7); // Ack generation Enable
g_pIICReg->IICDS = pInData->SlaveAddress;
g_pIICReg->IICSTAT = MRX_START;
// RETAILMSG(1,(TEXT("mao g_pIICReg->IICDS Slave Address is 0x%02X\n"),pInData->SlaveAddress)); //add mao
if(WaitForSingleObject(g_hTransferDone, TIMEOUT_MS_RX) == WAIT_TIMEOUT)
{
DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]RX Time out.\r\n")));
retVal = FALSE;
}
// 内核地址释放
hr = CeFreeAsynchronousBuffer((PVOID)Marshalled, MappedEmbedded, pOutData->Count, ARG_O_PTR);
hr = CeCloseCallerBuffer((PVOID) MappedEmbedded, pOutData->Data, pOutData->Count, ARG_O_PTR);
CleanUp:
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+HW_Read(0x%X)\r\n"),
pOpenContext));
return retVal;
}
BOOL HW_Write (PHW_OPEN_INFO pOpenContext, PIIC_IO_DESC pInData)
{
BOOL retVal = TRUE; // Initialize to success
PBYTE MappedEmbedded;
PBYTE Marshalled;
HRESULT hr; //add mao for iic
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+HW_Write(0x%X)\r\n"),
pOpenContext));
HW_SetRegister(pOpenContext);
ResetEvent(g_hTransferDone);
// Wait until IIC bus is free.
if(!WaitForReg((PVOID)&(g_pIICReg->IICSTAT), (1<<5), 0x0, TIMEOUT_MS_TX))
{
DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]IIC BUS is busy.\r\n")));
return FALSE;
}
// add mao
hr = CeOpenCallerBuffer((PVOID*) &MappedEmbedded, pInData->Data, pInData->Count, ARG_I_PTR, FALSE);
hr = CeAllocAsynchronousBuffer((PVOID*) &Marshalled, MappedEmbedded, pInData->Count, ARG_I_PTR);
g_pcIIC_BUFFER = Marshalled;;//pInData->Data;
g_uIIC_PT = 0;
g_uIIC_DATALEN = pInData->Count;
g_pIICReg->IICCON |= (1<<7); // Ack generation Enable
g_pIICReg->IICDS = pInData->SlaveAddress;
// RETAILMSG(1,(TEXT("mao [IIC TX]Slave Address is 0x%02X\n"),pInData->SlaveAddress)); //add mao
DEBUGMSG(ZONE_INFO,(TEXT("[IIC TX]Slave Address is 0x%02X\n"),pInData->SlaveAddress));
g_pIICReg->IICSTAT = MTX_START;
if(WaitForSingleObject(g_hTransferDone, 500) == WAIT_TIMEOUT)
{
DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]TX Time out.\r\n")));
retVal = FALSE;
}
hr = CeFreeAsynchronousBuffer((PVOID)Marshalled, MappedEmbedded, pInData->Count, ARG_I_PTR);
hr = CeCloseCallerBuffer((PVOID) MappedEmbedded, pInData->Data, pInData->Count, ARG_I_PTR);
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-HW_Write(0x%X)\r\n"),
pOpenContext));
return retVal;
}
重新编译后,读写正常了。
参考文章:http://bbs.csdn.net/topics/310115283
http://blog.csdn.net/knock/article/details/4770325