Nachfolgende Routinen funktionieren mit IOW40 V1.0.2.1R, jedoch NICHT mit Realease V1.0.3.0R, scheinbar klappt das Lesen von IIC nicht mehr.
(Unter Windows funktioniert die V1.0.3.0R ohne Probleme)
Das Problem zeigt sich u.a. mit folgenden Linuxversionen (auf x86 Hardware):
Kernel 2.6.20.15 mit IOWarrior Modul (Debian)
Kernel 2.6.35 mit IOWarrior Kernel Modul (Ubuntu)
Gelesen wird ein Datenbyte von einem EEPROM (Adresse A0/A1) Datenbyte ist 0xFF
=====================================
Hex-Log mit Chip-Release 1.0.2.1 :
Write: 02 C2 A0 00
Read : 02 02 00 0000000000
Write: 03 01 A1 0000000000
Read : 03 01 FF 0000000000
=====================================
Hex-Log mit Chip-Release 1.0.3.0
Write: 02 C2 A0 00
Read : 02 02 00 0000000000
Write: 03 01 A1 0000000000
Read : 0000000000000000
Read : 0000000000000000
Read : 0000000000000000
Read : 0000000000000000
Read : 0000000000000000
Read : 0000000000000000
...
=====================================
int IOWarrior::IICWrite(unsigned char Address, unsigned char *Command, unsigned char CommandLen)
{
int ReturnCode;
unsigned char BytesToWrite = CommandLen + 1; // Includes Address;
unsigned char DataToWrite[8];
unsigned char Result[8];
int i;
int CommandPointer=0;
DataToWrite[0] = 0x02; // IOWarrior Send IIC command
DataToWrite[1] = 0x80; // Generate Startbit
DataToWrite[2] = Address & 0xFE; // force IIC write bit
while (BytesToWrite > 0)
{
int BytesInThisPacket;
if (BytesToWrite <= 6)
{
BytesInThisPacket = BytesToWrite;
BytesToWrite = 0;
DataToWrite[1] |= 0x40; // Generate Stopbit
}
else
{
BytesInThisPacket = 6;
BytesToWrite -= 6;
}
DataToWrite[1] &= 0xF8; // Reset Counter
DataToWrite[1] += BytesInThisPacket;
for ( i = (DataToWrite[1] & 0x80) ? 1 : 0; i < BytesInThisPacket; i++)
{
DataToWrite[i+2] = Command[CommandPointer++];
}
cout << endl << "Write Command: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)DataToWrite << " ";
}
ReturnCode = ioctl(m_Handle1, IOW_WRITE, DataToWrite);
DataToWrite[1] &= 0x7F; // Reset Startbit
cout << "ReturnCode: " << ReturnCode << endl;
ReturnCode = ioctl(m_Handle1, IOW_READ, Result);
cout << "Write Answere: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)Result << " ";
}
cout << "ReturnCode: " << ReturnCode << endl;
}
return ReturnCode;
}
int IOWarrior::IICRead(unsigned char Address, unsigned char *Buffer, unsigned char BufferLen)
{
int ReturnCode;
unsigned char DataToWrite[8] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char Result[8];
int BufferPointer = 0;
int BytesToRead = BufferLen;
int i;
/*
// Can't send longer than 5 Byte commands.
if (BufferLen > 6) return -1;
*/
DataToWrite[0] = 0x03; // IOWarrior Send IIC command
DataToWrite[1] = BufferLen; // build IOWarrior IIC flags
DataToWrite[2] = Address | 1; // force IIC read bit
cout << endl << "Read Command: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)DataToWrite << " ";
}
ReturnCode = ioctl(m_Handle1, IOW_WRITE, DataToWrite);
cout << "ReturnCode: " << ReturnCode << endl;
while (BytesToRead)
{
ReturnCode = ioctl(m_Handle1, IOW_READ, Result);
for (i=2; i < 2 + ((Result[1] & 0x07)); i++)
{
Buffer[BufferPointer++] = Result;
}
BytesToRead -= Result[1] & 0x07;
cout << "Read Answere: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)Result << " ";
}
cout << "ReturnCode: " << ReturnCode << endl;
}
return ReturnCode;
}
Probleme beim IIC Lesen unter Linux mit IOW40 1.0.3.0
Moderator: Guido Körber
-
- Site Admin
- Posts: 2856
- Joined: Tue Nov 25, 2003 10:25 pm
- Location: Germany/Berlin
- Contact:
Re: Probleme beim IIC Lesen unter Linux mit IOW40 1.0.3.0
Das Verhalten haben wir bisher nirgendwo gesehen, müssen wir mal versuchen nachzuvollziehen. Regulär arbeiten wir hier unter MacOS und Windows.
- Christoph Jung
- Posts: 670
- Joined: Sun Oct 08, 2006 3:43 pm
- Location: Germany / Berlin
- Contact:
Re: Probleme beim IIC Lesen unter Linux mit IOW40 1.0.3.0
Ich hatte irgendwo gelesen, dass bei einem Update des Kernels die USB-Module geändert wurden.
Leider bin ich im moment gesundheitlich verhindert um dem Nachzugehen.
Leider bin ich im moment gesundheitlich verhindert um dem Nachzugehen.
Re: Probleme beim IIC Lesen unter Linux mit IOW40 1.0.3.0
Wir haben jetzt eine Lösung.
Und zwar haben wir die "ioctl"-Aufrufe gegen "read"/"write"-Aufrufe getauscht.
Anregung hat dazu das "IOWarriorHowTo.pdf"-Dokument gegeben.
Zu finden auf der Codemercs-Website unter: "Downloads/Software/IO-Warrior SDK Linux"
im Verzeichnes des Archivs: "LinuxSDK_01.zip\LinuxSDK\Kernel_2.6\iowkit 1.5\iowarrior-module-2.6.20.tar.gz\iowarrior-module-2.6.20.tar\iowarrior-module-2.6.20\iowarrior-2.6.20\
IOWarriorHowTo.pdf"
Am Ende des Dokument steht nämlich :
> 03/27/2007 Version 0.1.1.0
> Updates reflecting changes to the header,
> removed sections on read/write-ioctl() calls
Die Routinen haben wir wie folgt geändert, und so funktioniert es. Anscheinend ist die "ioctl"-Funktion nicht mehr (ohne weiteres) dazu geeignet mehrere Chipversionen gleichartig zu betreiben. Wer die IOWarriorfunktionen mit einem aktuellen IOWkit kapselt hat vermutlich keine Probleme.
================================================================================================
int IOWarrior::IICWrite(unsigned char Address, unsigned char *Command, unsigned char CommandLen)
{
//int ReturnCode;
unsigned char BytesToWrite = CommandLen + 1; // Includes Address;
unsigned char DataToWrite[8] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char Result[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int i;
int CommandPointer=0;
DataToWrite[0] = 0x02; // IOWarrior Send IIC command
DataToWrite[1] = 0x80; // Generate Startbit
DataToWrite[2] = Address & 0xFE; // force IIC write bit
while (BytesToWrite > 0)
{
int BytesInThisPacket;
if (BytesToWrite <= 6)
{
BytesInThisPacket = BytesToWrite;
BytesToWrite = 0;
DataToWrite[1] |= 0x40; // Generate Stopbit
}
else
{
BytesInThisPacket = 6;
BytesToWrite -= 6;
}
DataToWrite[1] &= 0xF8; // Reset Counter
DataToWrite[1] += BytesInThisPacket;
for ( i = (DataToWrite[1] & 0x80) ? 1 : 0; i < BytesInThisPacket; i++)
{
DataToWrite[i+2] = Command[CommandPointer++];
}
cout << endl << "Write Command: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)DataToWrite << " ";
}
cout << endl;
if (write(m_Handle1, DataToWrite, m_IOWReportSizeSpecialMode) != m_IOWReportSizeSpecialMode)
{
cout << "IICWrite()/write() failed!" << endl;
return -1;
}
DataToWrite[1] &= 0x7F; // Reset Startbit
if (read(m_Handle1, Result, m_IOWReportSizeSpecialMode) != m_IOWReportSizeSpecialMode)
{
cout << "IICWrite()/read() failed!" << endl;
return -2;
}
else
{
cout << "Write Answer: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)Result << " ";
}
cout << endl;
if(Result[1] >> 7)
{
cout << "IICWrite()/Errorbit set!" << endl;
return -3;
}
}
}
return 0;
}
int IOWarrior::IICRead(unsigned char Address, unsigned char *Buffer, unsigned char BufferLen)
{
//int ReturnCode;
unsigned char DataToWrite[8] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char Result[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int BufferPointer = 0;
int BytesToRead = BufferLen;
int i;
/*
// Can't send longer than 5 Byte commands.
if (BufferLen > 6) return -1;
*/
DataToWrite[0] = 0x03; // IOWarrior Send IIC command
DataToWrite[1] = BufferLen; // build IOWarrior IIC flags
DataToWrite[2] = Address | 1; // force IIC read bit
cout << endl << "Read Command: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)DataToWrite << " ";
}
cout << endl;
if (write(m_Handle1, DataToWrite, m_IOWReportSizeSpecialMode) != m_IOWReportSizeSpecialMode)
{
cout << "IICRead()/write() failed!" << endl;
return -1;
}
while (BytesToRead)
{
if (read(m_Handle1, Result, m_IOWReportSizeSpecialMode) != m_IOWReportSizeSpecialMode)
{
cout << "IICRead()/read() failed!" << endl;
return -2;
}
else
{
for (i=2; i < 2 + ((Result[1] & 0x07)); i++)
{
Buffer[BufferPointer++] = Result;
}
BytesToRead -= Result[1] & 0x07;
cout << "Read Answer: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)Result << " ";
}
cout << endl;
if(Result[1] >> 7)
{
cout << "IICRead()/Errorbit set!" << endl;
return -3;
}
}
}
return 0;
}
Und zwar haben wir die "ioctl"-Aufrufe gegen "read"/"write"-Aufrufe getauscht.
Anregung hat dazu das "IOWarriorHowTo.pdf"-Dokument gegeben.
Zu finden auf der Codemercs-Website unter: "Downloads/Software/IO-Warrior SDK Linux"
im Verzeichnes des Archivs: "LinuxSDK_01.zip\LinuxSDK\Kernel_2.6\iowkit 1.5\iowarrior-module-2.6.20.tar.gz\iowarrior-module-2.6.20.tar\iowarrior-module-2.6.20\iowarrior-2.6.20\
IOWarriorHowTo.pdf"
Am Ende des Dokument steht nämlich :
> 03/27/2007 Version 0.1.1.0
> Updates reflecting changes to the header,
> removed sections on read/write-ioctl() calls
Die Routinen haben wir wie folgt geändert, und so funktioniert es. Anscheinend ist die "ioctl"-Funktion nicht mehr (ohne weiteres) dazu geeignet mehrere Chipversionen gleichartig zu betreiben. Wer die IOWarriorfunktionen mit einem aktuellen IOWkit kapselt hat vermutlich keine Probleme.
================================================================================================
int IOWarrior::IICWrite(unsigned char Address, unsigned char *Command, unsigned char CommandLen)
{
//int ReturnCode;
unsigned char BytesToWrite = CommandLen + 1; // Includes Address;
unsigned char DataToWrite[8] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char Result[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int i;
int CommandPointer=0;
DataToWrite[0] = 0x02; // IOWarrior Send IIC command
DataToWrite[1] = 0x80; // Generate Startbit
DataToWrite[2] = Address & 0xFE; // force IIC write bit
while (BytesToWrite > 0)
{
int BytesInThisPacket;
if (BytesToWrite <= 6)
{
BytesInThisPacket = BytesToWrite;
BytesToWrite = 0;
DataToWrite[1] |= 0x40; // Generate Stopbit
}
else
{
BytesInThisPacket = 6;
BytesToWrite -= 6;
}
DataToWrite[1] &= 0xF8; // Reset Counter
DataToWrite[1] += BytesInThisPacket;
for ( i = (DataToWrite[1] & 0x80) ? 1 : 0; i < BytesInThisPacket; i++)
{
DataToWrite[i+2] = Command[CommandPointer++];
}
cout << endl << "Write Command: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)DataToWrite << " ";
}
cout << endl;
if (write(m_Handle1, DataToWrite, m_IOWReportSizeSpecialMode) != m_IOWReportSizeSpecialMode)
{
cout << "IICWrite()/write() failed!" << endl;
return -1;
}
DataToWrite[1] &= 0x7F; // Reset Startbit
if (read(m_Handle1, Result, m_IOWReportSizeSpecialMode) != m_IOWReportSizeSpecialMode)
{
cout << "IICWrite()/read() failed!" << endl;
return -2;
}
else
{
cout << "Write Answer: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)Result << " ";
}
cout << endl;
if(Result[1] >> 7)
{
cout << "IICWrite()/Errorbit set!" << endl;
return -3;
}
}
}
return 0;
}
int IOWarrior::IICRead(unsigned char Address, unsigned char *Buffer, unsigned char BufferLen)
{
//int ReturnCode;
unsigned char DataToWrite[8] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char Result[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int BufferPointer = 0;
int BytesToRead = BufferLen;
int i;
/*
// Can't send longer than 5 Byte commands.
if (BufferLen > 6) return -1;
*/
DataToWrite[0] = 0x03; // IOWarrior Send IIC command
DataToWrite[1] = BufferLen; // build IOWarrior IIC flags
DataToWrite[2] = Address | 1; // force IIC read bit
cout << endl << "Read Command: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)DataToWrite << " ";
}
cout << endl;
if (write(m_Handle1, DataToWrite, m_IOWReportSizeSpecialMode) != m_IOWReportSizeSpecialMode)
{
cout << "IICRead()/write() failed!" << endl;
return -1;
}
while (BytesToRead)
{
if (read(m_Handle1, Result, m_IOWReportSizeSpecialMode) != m_IOWReportSizeSpecialMode)
{
cout << "IICRead()/read() failed!" << endl;
return -2;
}
else
{
for (i=2; i < 2 + ((Result[1] & 0x07)); i++)
{
Buffer[BufferPointer++] = Result;
}
BytesToRead -= Result[1] & 0x07;
cout << "Read Answer: ";
for (i=0; i < 8; i++)
{
cout << "0x" << hex << cout.width(2) << (int)Result << " ";
}
cout << endl;
if(Result[1] >> 7)
{
cout << "IICRead()/Errorbit set!" << endl;
return -3;
}
}
}
return 0;
}