HighTechTalks DotNet Forums  

Mangaged to Unmanaged code I2C device access violation issue

Dotnet Framework (Interop) microsoft.public.dotnet.framework.interop


Discuss Mangaged to Unmanaged code I2C device access violation issue in the Dotnet Framework (Interop) forum.



Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old   
=?Utf-8?B?VG9ub2ZpdA==?=
 
Posts: n/a

Default Mangaged to Unmanaged code I2C device access violation issue - 06-08-2007 , 07:55 PM






I'm doing a IO Control function call to set a I2C device's frequency as the
first part of a sequence of other IO calls. I'm getting an access violation
in unmanged code in passing PBYTE pBufIn in the function below's signature.
I've included a description of the comments for the driver function call and
the application user code I wrote.

Can someone tell me what I didn't do or tell me how to code this correctly
so it passs the PBYTE pBufin argument that represents the frequency value.
It is defined as a 4 byte array and the driver code casts this to a DWORD.
The frequency value is not being set

--Device Code ---
//
// Function: I2C_IOControl
//
// This function sends a command to a device.
//
// Parameters:
// hOpenContext
// [in] Handle to the open context of the device. The XXX_Open
// function creates and returns this identifier.
// dwCode
// [in] I/O control operation to perform. These codes are
// device-specific and are usually exposed to developers
through
// a header file.
// pBufIn
// [in] Pointer to the buffer containing data to transfer to the
// device.
// dwLenIn
// [in] Number of bytes of data in the buffer specified for pBufIn.
//
// pBufOut
// [out] Pointer to the buffer used to transfer the output data
// from the device.
// dwLenOut
// [in] Maximum number of bytes in the buffer specified by pBufOut.
//
// pdwActualOut
// [out] Pointer to the DWORD buffer that this function uses to
// return the actual number of bytes received from the
device.
//
// Returns:
// The new data pointer for the device indicates success. A value of -1
// indicates failure.


BOOL I2C_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
PDWORD pdwActualOut)
{
BOOL bRet = FALSE;

// hOpenContext is a pointer to I2CClass instance!
I2CClass* pI2C = (I2CClass*) hOpenContext;

DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION, (TEXT("I2C_IOControl:
+hOpenContext=0x%x\r\n"),hOpenContext));

if (pI2C != NULL)
{
switch (dwCode)
{
case I2C_IOCTL_SET_FREQUENCY:
{
if (dwLenIn != sizeof(DWORD))
return FALSE;

PDWORD pdwFrequency = (PDWORD) MapCallerPtr(pBufIn,
sizeof(DWORD));
DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION,
(TEXT("I2C_IOControl:SET_FREQUENCY + ValIn=0x%x\r\n"), *pdwFrequency));
WORD wClkRate = BSPCalculateClkRateDiv(*pdwFrequency);
pI2C->SetClockRateDivider(wClkRate);
bRet = TRUE;
break;
}
default:
{
bRet = FALSE;
break;
}
}
}




---Application User Code----



//
// IOCTL codes
//
public static uint CTL_CODE(uint DeviceType, uint Function, uint
Method, uint Access)
{
return(((DeviceType) << 16) | ((Access) << 14) | ((Function) <<
2) | (Method));
}
//
// Set the Frequency of I2C device
//

Byte[] freq = new Byte[4];
Byte[] ba = BitConverter.GetBytes(i2CBus.I2C_SCLK_FREQ);
freq[0] = ba[3];
freq[1] = ba[2];
freq[2] = ba[1];
freq[3] = ba[0];

GCHandle handle = GCHandle.Alloc(freq, GCHandleType.Pinned);
IntPtr p = handle.AddrOfPinnedObject();
uint objectsize = freq.Length;

bool val = I2C.I2CIOControl(m_hI2c,
i2CBus.CTL_CODE(i2CBus.FILE_DEVICE_BUS_EXTENDER,
i2CBus.I2C_IOCTL_SET_FREQUENCY, i2CBus.METHOD_BUFFERED,
i2CBus.FILE_ANY_ACCESS), p, objectsize, IntPtr.Zero, 0, IntPtr.Zero);

Marshal.FreeHGlobal(p);

Reply With Quote
  #2  
Old   
Ben Voigt [C++ MVP]
 
Posts: n/a

Default Re: Mangaged to Unmanaged code I2C device access violation issue - 06-09-2007 , 01:32 PM







"Tonofit" <Tonofit (AT) discussions (DOT) microsoft.com> wrote

Quote:
I'm doing a IO Control function call to set a I2C device's frequency as
the
first part of a sequence of other IO calls. I'm getting an access
violation
in unmanged code in passing PBYTE pBufIn in the function below's
signature.
I've included a description of the comments for the driver function call
and
the application user code I wrote.

Can someone tell me what I didn't do or tell me how to code this correctly
so it passs the PBYTE pBufin argument that represents the frequency value.
It is defined as a 4 byte array and the driver code casts this to a DWORD.
The frequency value is not being set
Then you should declare the argument as "ref uint", which is the C#
equivalent to DWORD.

For low-level interaction with device drivers, though, I've always found
that C++/CLI is far superior to C#.

Just something like:

#include <winnt.h>

ref class PWM
{
public:
property uint Frequency
{
void set(uint value);
}
};

void PWM::Frequency::set(uint value)
{
if (!I2CIOControl(m_hI2c, I2C_IOCTL_SET_FREQUENCY, &value, sizeof value,
nullptr, 0, nullptr))
throw gcnew IOException("Failed to set PWM frequency to " +
value.ToString());
}

Quote:
--Device Code ---
//
// Function: I2C_IOControl
//
// This function sends a command to a device.
//
// Parameters:
// hOpenContext
// [in] Handle to the open context of the device. The XXX_Open
// function creates and returns this identifier.
// dwCode
// [in] I/O control operation to perform. These codes are
// device-specific and are usually exposed to developers
through
// a header file.
// pBufIn
// [in] Pointer to the buffer containing data to transfer to the
// device.
// dwLenIn
// [in] Number of bytes of data in the buffer specified for
pBufIn.
//
// pBufOut
// [out] Pointer to the buffer used to transfer the output data
// from the device.
// dwLenOut
// [in] Maximum number of bytes in the buffer specified by
pBufOut.
//
// pdwActualOut
// [out] Pointer to the DWORD buffer that this function uses to
// return the actual number of bytes received from the
device.
//
// Returns:
// The new data pointer for the device indicates success. A value
of -1
// indicates failure.


BOOL I2C_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
PDWORD pdwActualOut)
{
BOOL bRet = FALSE;

// hOpenContext is a pointer to I2CClass instance!
I2CClass* pI2C = (I2CClass*) hOpenContext;

DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION, (TEXT("I2C_IOControl:
+hOpenContext=0x%x\r\n"),hOpenContext));

if (pI2C != NULL)
{
switch (dwCode)
{
case I2C_IOCTL_SET_FREQUENCY:
{
if (dwLenIn != sizeof(DWORD))
return FALSE;

PDWORD pdwFrequency = (PDWORD) MapCallerPtr(pBufIn,
sizeof(DWORD));
DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION,
(TEXT("I2C_IOControl:SET_FREQUENCY + ValIn=0x%x\r\n"), *pdwFrequency));
WORD wClkRate = BSPCalculateClkRateDiv(*pdwFrequency);
pI2C->SetClockRateDivider(wClkRate);
bRet = TRUE;
break;
}
default:
{
bRet = FALSE;
break;
}
}
}




---Application User Code----



//
// IOCTL codes
//
public static uint CTL_CODE(uint DeviceType, uint Function, uint
Method, uint Access)
{
return(((DeviceType) << 16) | ((Access) << 14) | ((Function)
2) | (Method));
}
//
// Set the Frequency of I2C device
//

Byte[] freq = new Byte[4];
Byte[] ba = BitConverter.GetBytes(i2CBus.I2C_SCLK_FREQ);
freq[0] = ba[3];
freq[1] = ba[2];
freq[2] = ba[1];
freq[3] = ba[0];

GCHandle handle = GCHandle.Alloc(freq, GCHandleType.Pinned);
IntPtr p = handle.AddrOfPinnedObject();
uint objectsize = freq.Length;

bool val = I2C.I2CIOControl(m_hI2c,
i2CBus.CTL_CODE(i2CBus.FILE_DEVICE_BUS_EXTENDER,
i2CBus.I2C_IOCTL_SET_FREQUENCY, i2CBus.METHOD_BUFFERED,
i2CBus.FILE_ANY_ACCESS), p, objectsize, IntPtr.Zero, 0, IntPtr.Zero);

Marshal.FreeHGlobal(p);


Reply With Quote
  #3  
Old   
Ben Voigt [C++ MVP]
 
Posts: n/a

Default Re: Mangaged to Unmanaged code I2C device access violation issue - 06-09-2007 , 01:47 PM




"Ben Voigt [C++ MVP]" <rbv (AT) nospam (DOT) nospam> wrote

Quote:
"Tonofit" <Tonofit (AT) discussions (DOT) microsoft.com> wrote in message
news:141A3D2E-00B8-458A-BE50-ADB6F43E9A7C (AT) microsoft (DOT) com...
I'm doing a IO Control function call to set a I2C device's frequency as
the
first part of a sequence of other IO calls. I'm getting an access
violation
in unmanged code in passing PBYTE pBufIn in the function below's
signature.
I've included a description of the comments for the driver function call
and
the application user code I wrote.

Can someone tell me what I didn't do or tell me how to code this
correctly
so it passs the PBYTE pBufin argument that represents the frequency
value.
It is defined as a 4 byte array and the driver code casts this to a
DWORD.
The frequency value is not being set

Then you should declare the argument as "ref uint", which is the C#
equivalent to DWORD.

For low-level interaction with device drivers, though, I've always found
that C++/CLI is far superior to C#.

Just something like:

#include <winnt.h

ref class PWM
{
public:
property uint Frequency
{
void set(uint value);
}
};
Of course you should connect to the driver in the PWM constructor, and
implement a destructor that closes it properly (C++ will translate your
destructor into an implementation of IDisposable).

Quote:
void PWM::Frequency::set(uint value)
{
if (!I2CIOControl(m_hI2c, I2C_IOCTL_SET_FREQUENCY, &value, sizeof
value, nullptr, 0, nullptr))
throw gcnew IOException("Failed to set PWM frequency to " +
value.ToString());
}


--Device Code ---
//
// Function: I2C_IOControl
//
// This function sends a command to a device.
//
// Parameters:
// hOpenContext
// [in] Handle to the open context of the device. The XXX_Open
// function creates and returns this identifier.
// dwCode
// [in] I/O control operation to perform. These codes are
// device-specific and are usually exposed to developers
through
// a header file.
// pBufIn
// [in] Pointer to the buffer containing data to transfer to the
// device.
// dwLenIn
// [in] Number of bytes of data in the buffer specified for
pBufIn.
//
// pBufOut
// [out] Pointer to the buffer used to transfer the output data
// from the device.
// dwLenOut
// [in] Maximum number of bytes in the buffer specified by
pBufOut.
//
// pdwActualOut
// [out] Pointer to the DWORD buffer that this function uses to
// return the actual number of bytes received from the
device.
//
// Returns:
// The new data pointer for the device indicates success. A value
of -1
// indicates failure.


BOOL I2C_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
PDWORD pdwActualOut)
{
BOOL bRet = FALSE;

// hOpenContext is a pointer to I2CClass instance!
I2CClass* pI2C = (I2CClass*) hOpenContext;

DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION, (TEXT("I2C_IOControl:
+hOpenContext=0x%x\r\n"),hOpenContext));

if (pI2C != NULL)
{
switch (dwCode)
{
case I2C_IOCTL_SET_FREQUENCY:
{
if (dwLenIn != sizeof(DWORD))
return FALSE;

PDWORD pdwFrequency = (PDWORD) MapCallerPtr(pBufIn,
sizeof(DWORD));
DEBUGMSG (ZONE_IOCTL|ZONE_FUNCTION,
(TEXT("I2C_IOControl:SET_FREQUENCY + ValIn=0x%x\r\n"), *pdwFrequency));
WORD wClkRate = BSPCalculateClkRateDiv(*pdwFrequency);
pI2C->SetClockRateDivider(wClkRate);
bRet = TRUE;
break;
}
default:
{
bRet = FALSE;
break;
}
}
}




---Application User Code----



//
// IOCTL codes
//
public static uint CTL_CODE(uint DeviceType, uint Function, uint
Method, uint Access)
{
return(((DeviceType) << 16) | ((Access) << 14) | ((Function)

2) | (Method));
}
//
// Set the Frequency of I2C device
//

Byte[] freq = new Byte[4];
Byte[] ba = BitConverter.GetBytes(i2CBus.I2C_SCLK_FREQ);
freq[0] = ba[3];
freq[1] = ba[2];
freq[2] = ba[1];
freq[3] = ba[0];

GCHandle handle = GCHandle.Alloc(freq, GCHandleType.Pinned);
IntPtr p = handle.AddrOfPinnedObject();
uint objectsize = freq.Length;

bool val = I2C.I2CIOControl(m_hI2c,
i2CBus.CTL_CODE(i2CBus.FILE_DEVICE_BUS_EXTENDER,
i2CBus.I2C_IOCTL_SET_FREQUENCY, i2CBus.METHOD_BUFFERED,
i2CBus.FILE_ANY_ACCESS), p, objectsize, IntPtr.Zero, 0, IntPtr.Zero);

Marshal.FreeHGlobal(p);



Reply With Quote
Reply




Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.