DLL problems

Post questions and issues with Concept2 PM3 SDK
Locked
Andrik
Paddler
Posts: 5
Joined: February 7th, 2012, 11:53 am

DLL problems

Post by Andrik » February 27th, 2012, 1:46 pm

Hi,

I'm working on a project where i want to use the data from a Concept2.
Though the PMSDKDemo.exe I can get data from the PM4 i'm using.

When i want to compile my version based on someone elses C# file, i get some troubles.

First of all, when i call

Code: Select all

[DllImport("PM3DDICP", CallingConvention = CallingConvention.Cdecl)]
public static extern ushort tkcmdsetDDI_init();
I get a nice 0 returned, so no errors there.
When i call :

Code: Select all

[DllImport("PM3CsafeCP", CallingConvention = CallingConvention.Cdecl)]
public static extern ushort tkcmdsetCSAFE_init_protocol(ushort timeout);
I get an error: " Unable to find an entry point named 'tkcmdsetCSAFE_init_protocol' in DLL 'PM3CsafeCP'."
though this exact file is used with the PMSDKDemo.

When i compile the same code with an older dll "RPPM3safe" it works.
The code returns no errors.

Then when i use:

Code: Select all

[DllImport("PM3DDICP", EntryPoint = "tkcmdsetDDI_discover_pm3s", CallingConvention = CallingConvention.Cdecl)]
public static extern ushort tkcmdsetDDI_discover_pm3s(
string product_name,
ushort starting_address,
ref ushort num_units);
I get the one PM4 i have connected to my PC.
When i call a Csafe command like the next:

Code: Select all

uint[] cmd_data = new uint[64];
ushort cmd_data_size;
uint[] rsp_data = new uint[64];
ushort rsp_data_size = 0;

cmd_data_size = 0;

cmd_data[cmd_data_size++] = (uint)USBErgInterfaceWrapper.CSAFE.CSAFE_GETID_CMD;
ushort errorcode = USBErgInterfaceWrapper.tkcmdsetCSAFE_command(0x01, cmd_data_size, cmd_data, ref rsp_data_size, rsp_data);
i get error "55382", or -10154: Protocol not initialized.
Though the tkcmdsetCSAFE_init_protocol() returns no error, it looks like the protocol is not setup right.

What am i doing wrong here?

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Re: DLL problems

Post by haboustak » February 27th, 2012, 3:56 pm

Looking at the header files provided with the SDK.

PM3DDICP.h

Code: Select all

#define PM3DDI_API  extern "C" __declspec(dllexport)
PM3CsafeCP.h

Code: Select all

#define PM3CSAFE_API __declspec(dllexport)
So PM3DDICP is compiled using C linker conventions and PM3CsafeCP i s compiled using C++ linker conventions. The difference in declaration results in name mangling of exports for Csafe and no name mangling of exports for DDI. DllImport doesn't automatically deal with C++ linker conventions for you, but it can be made to work via the EntryPoint parameter.

Now that you understand the issue, dumpbin (included with visual studio) is your new best friend. I also like Dependency Walker (depends.exe).

dumpbin /exports PM3CsafeCP.dll

Code: Select all

          2    1 00001AB0 ?tkcmdsetCSAFE_command@@YAFGGQAKPAG0@Z
          6    5 00001060 ?tkcmdsetCSAFE_get_dll_version@@YAGXZ
         11    A 00001270 ?tkcmdsetCSAFE_get_status@@YAEXZ
         12    B 000019C0 ?tkcmdsetCSAFE_init_protocol@@YAFG@Z
There's a partial list of your entry points in C++ name mangled form. Just drop them into your DllImport declarations as follows.

Code: Select all

[DllImport("PM3CsafeCP", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?tkcmdsetCSAFE_init_protocol@@YAFG@Z")]
public static extern short tkcmdsetCSAFE_init_protocol(ushort t);
I also want to point out that ERRCODE_T is #defined to short, not ushort.

Andrik
Paddler
Posts: 5
Joined: February 7th, 2012, 11:53 am

Re: DLL problems

Post by Andrik » February 28th, 2012, 8:54 am

Thnx for the help so far.

I'm still encountering some problems. The problem with the dll function is solved. I can now call the protocol_init function from the PM3CsafeCP.dll file.

When I call the Init function, it returns error code 0. So it looks like the init went fine.
When I call:

Code: Select all

uint[] cmd_data = new uint[64];
ushort cmd_data_size;
uint[] rsp_data = new uint[64];
ushort rsp_data_size = 0;

cmd_data_size = 0;

cmd_data[cmd_data_size++] = (uint)USBErgInterfaceWrapper.CSAFE.CSAFE_GETID_CMD;
ushort errorcode = USBErgInterfaceWrapper.tkcmdsetCSAFE_command(0x01, cmd_data_size, cmd_data, ref rsp_data_size, rsp_data);
It still returns error [-10154], protocol not initialized. Though I initialized it first.
What I do is the following:
1. tkcmdsetDDI_init (returns errorcode 0)
2. tkcmdsetDDI_discover_pm3s (returns 1 device found)
3. TKcmdsetCsafe_init_protocol (returns error 0)
4. tkcmdsetCsafe_command (try and send a simple command, like getID. This returns the protocol not initialized error)

I have tried switching step 2 and 3, but it gives the same result. Am I missing an important step here?


Also when I call the get status function:

Code: Select all

[DllImport("PM3CsafeCP", CallingConvention = CallingConvention.Cdecl, EntryPoint = "??tkcmdsetCSAFE_get_status@@YAEXZ")]
public static extern short tkcmdsetCSAFE_get_status();
I get responds: 45312, or [-20224], which I cant seem to find what it means.

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Re: DLL problems

Post by haboustak » February 28th, 2012, 11:30 am

The process you're describing in steps 1-4 is correct. I can't directly determine why you're getting the error code you're getting, but I see two issues with the code we have so far.

First, I noticed that you're using 0x01 as the unit address. Did you specify 1 as the second parameter to discover_pm3s? I typically start my addresses at 0 (again, based on what I typically use for the second parameter to discover_pm3s).

Second, the arguments to tkcmdsetCSAFE_command use a familiar output buffer pattern that's common in C. The rsp_data parameter is a pointer to a buffer allocated by the caller. To safely write to this buffer you need to know its length. The parameter rsp_data_size serves two purposes, on input the value should be the total size of the response buffer and on output the value should be the length of data placed into the response buffer. Your value of 0 here results in no response space available to the function. You should initialize rsp_data_size to 64. The documentation on pages 37/38 could be made clearer by showing rsp_data_size participating as both an Input and as an Output. Most C developers have just internalized how to make use of (char* buffer, int *buffer_size).

If problems still persist, try posting the entire contents of your 4 required dll imports and all the code used from ddi_init to csafe_command.

Andrik
Paddler
Posts: 5
Joined: February 7th, 2012, 11:53 am

Re: DLL problems

Post by Andrik » March 5th, 2012, 6:08 am

Thnx for the help so far.

I now got a program working with the dll's. With it i'm able to set up a connection and get the Csafe_command working.

The last thing i'm encountering is with most commands I send, I get an error code back:
[-166]
Name=TKFRAME_CSAFE_NO_END_CHAR_ERR
Text=CSAFE frame missing end character

is this something I need to adress, or can I ignore it? The commands seem to come though just fine. Should I supply and 'end character' with my command data, or is this something that goes wrong within the protocol itself?

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Re: DLL problems

Post by haboustak » March 5th, 2012, 11:59 am

If the device is responding to your request then I don't think it's a problem with what you're sending.

That error indicates to me that the response you get back from the device doesn't include the terminating character. Your command may have resulted in more data than what you've allocated space for, and the message may have been truncated prior to the end of the response. There are limits to what you can do in a single command. If you allocate 64 bytes and you get 64 back, that's a sign that this is what's happening.

You should also check your device firmware. I don't know if they specify a version tested with the SDK, but recent firmware is generally better.

Andrik
Paddler
Posts: 5
Joined: February 7th, 2012, 11:53 am

Re: DLL problems

Post by Andrik » March 6th, 2012, 10:30 am

The problem with the error code [-166] does not seem to be a problem i think. the commands execute just fine with it.
I can now put the PM4 into the standard 2000m rowing program.
When I want to get the time the user is rowing, I simply send the command 0xA1
When done in the PMSDKDemo.exe, it returns the time. This is to prove that the functions works with my system and dll.
it returns:

Code: Select all

000000A0H 00000003H 00000000H 00000000H 00000009H
first the command that was send (a0), then the length of the responds (03), then the responds (00 00 09) the time in hours, minutes and seconds.
The Demo program adds the first 2 bytes (a0 and 03) to the displayed value, according to the documentation it should return 3 bytes of data.

In my own program I use the following to call a command to the dll:

Code: Select all

[DllImport("PM3CsafeCP", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?tkcmdsetCSAFE_command@@YAFGGQAKPAG0@Z")]
    public static extern short tkcmdsetCSAFE_command(
       ushort unit_address,
       ushort cmd_data_size,
       uint[] cmd_data,
       ref ushort rsp_data_size,
       uint[] rsp_data);
When i call this from another object, for instance to set the standard 2000m program I use the follwing:
(this is ofcourse done after initializing and discovering and setting the Csafe protocol)

Code: Select all

public void start_2000()

    {

        uint[] cmd_data = new uint[1];

        ushort cmd_data_size;

        uint[] rsp_data = new uint[64];

        ushort rsp_data_size = 0;



        cmd_data_size = 0;

		

        // Reset.



        cmd_data[cmd_data_size++] = 0x81;

		Debug.Log("81 send");



        Debug.Log(USBErgInterfaceWrapper.tkcmdsetCSAFE_command(0, cmd_data_size, cmd_data, ref rsp_data_size, rsp_data));

    }

	public void set_distance()

    {

        uint[] cmd_data = new uint[5];

        ushort cmd_data_size;

        uint[] rsp_data = new uint[64];

        ushort rsp_data_size = 0;



        cmd_data_size = 0;



		cmd_data[cmd_data_size++] = 0x21;

		cmd_data[cmd_data_size++] = 0x03;

		cmd_data[cmd_data_size++] = 0x02;

		cmd_data[cmd_data_size++] = 0x00;

		cmd_data[cmd_data_size++] = 0x21;

		Debug.Log("Set distance");

		Debug.Log("data: " + cmd_data[0] + ":"+ cmd_data[1] + ":"+ cmd_data[2]);

        Debug.Log(USBErgInterfaceWrapper.tkcmdsetCSAFE_command(0, cmd_data_size, cmd_data, ref rsp_data_size, rsp_data));

    }

	public void set_progam()

    {

        uint[] cmd_data = new uint[4];

        ushort cmd_data_size;

        uint[] rsp_data = new uint[64];

        ushort rsp_data_size = 0;



        cmd_data_size = 0;



		cmd_data[cmd_data_size++] = 0x24;

		cmd_data[cmd_data_size++] = 0x02;

		cmd_data[cmd_data_size++] = 0x00;

		cmd_data[cmd_data_size++] = 0x00;

		Debug.Log("Set program");

        Debug.Log(USBErgInterfaceWrapper.tkcmdsetCSAFE_command(0, cmd_data_size, cmd_data, ref rsp_data_size, rsp_data));

    }

	public void go_in_use()

    {

        uint[] cmd_data = new uint[1];

        ushort cmd_data_size;

        uint[] rsp_data = new uint[64];

        ushort rsp_data_size = 0;



        cmd_data_size = 0;



		cmd_data[cmd_data_size++] = 0x85;

		Debug.Log("go in use");

        Debug.Log(USBErgInterfaceWrapper.tkcmdsetCSAFE_command(0, cmd_data_size, cmd_data, ref rsp_data_size, rsp_data));

    }
This code seems to work, and sets the PM4 into the row 200 meter program. I splited the code into 4 functions, so I can easily call the whole routine, or just a piece of it.
I only log the errorcodes, because these call dont get any data back.
The error codes returned are [253], a code I can not seem to find in the Interface Definitons (unlike the former [-166])
I dont know what this error means, but all commands seem to come through.

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Re: DLL problems

Post by haboustak » March 6th, 2012, 12:06 pm

I still think your problem is related to initializing rsp_data_size to 0. On input it should be the available size of your response buffer (64).

But if your code works then the error responses are academic. You can move on and come back to the protocol stuff when something's not doing what you expect.

User avatar
kdahlhaus
500m Poster
Posts: 95
Joined: September 17th, 2006, 2:13 pm
Contact:

Re: DLL problems

Post by kdahlhaus » October 8th, 2014, 10:05 pm

I am moving my code up to the latest version of the SDK and saw this error. Your theory is correct - setting the return buffer size to 64 fixed the problem. Thanks!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
http://powertwenty.com
'Do' or 'Do not', there is no 'Try' -Yoda

Locked