Wishing you all a Happy and Prosperous New Year 2009


Nov 25, 2008

Agilent Technologies Announces USB 3.0 SuperSpeed Physical Layer Compliance Test Application

Agilent Technologies Inc today announced Super Speed USB 3.0 comprehensive test equipment. This solution will mainly help in testing and making USB devices compliant with USB-IF requirements.

Agilent demonstrated their solution at the First USB 3.0 Developers Conference in San Jose, CA. 

The Super Speed USB or USB 3.0 can deliver upto 10 times speeds as compared with USB 2.0 and makes power usage more efficient. SuperSpeed USB will be necessary for data-storage devices transferring more than 25 Gbps.

-- Infiniium DSO/DSA91304A 13-GHz oscilloscope for transmitter testing;
-- Agilent USB 3.0 transmitter compliance test application;
-- Agilent USB 3.0 test fixtures;
-- J-BERT N4903A, a high-performance serial BERT with complete jitter tolerance test for characterizing USB 3.0 SuperSpeed serial communication links;
-- Agilent ADS simulation software for creating and analyzing USB 3.0 channels;
-- Agilent VNA/PNA network analyzer N5230C-245 for measuring and analyzing USB 3.0 channels.
Additional information about Agilent's USB compliance test solution is available at www.agilent.com/find/N5416A.
For other USB Analyzers that can be used with USB 2.0 click here.




Nov 24, 2008

Using MPUSBAPI.CPP directly instead of MPUSBAPI.DLL

Related Links
1. For learning how to Usie MPUSBAPI.DLL with VC++ 6.0 click here
2. For main.c file used in this example click here.

1. Introduction

All the time, we are trying to use the MPUSBAPI.DLL in various development environments. We tried to use the .DLL in Load-time Linking and Run-time Linking methods. Even Microchip provided samples that show how to use the .DLL in both methods.

After trying few things I realized that the _mpusbapi.cpp file can be added to the project directly. The two important pointes to be noted are:
   - When using along with Borland C++ Builder, _mpusbapi.cpp can be used without modifications.
   - When using with other environments few changes are required.

The project is created in Visual C++ 6.0. But almost the same steps/concepts can be adopted while developing your project in other C++ environments also. 

2. Steps to use the _mpusbapi.cpp instead of mpusbapi.dll in Visual C++ 6.0

  1. Create a Win32 Console application as an Empty Project.
  2. Create main.cpp file and add it to the project.
  3. Now, using Windows Explorer copy the files _mpusbapi.cpp, _mpusbapi.h and Ioctls.h files into your project folder. These files are available in C:\MCHPFSUSB\Pc\Mpusbapi\Dll\Borland_C\Source folder.
  4. Go back to VC++ environment, and add the files to the newly created project. For this select the FileView tab in Workspace window. This window provides options to add the files in 3 sections. Source Files (.CPP) and Header Files(.H) and Resource Files(.RES). In our example we do not have .RES files. Add _mpusbapi.cpp under Source Files section and _mpusbapi.h & _Ioctls.h in Header Files Section.
    NOTE: If you compile the project at this point, it will throw errors. We havn't added any code in main.cpp. And some libraries are missing in the project settings at this point of time.
    Errors:
          Compiling...
          main.cpp
          _mpusbapi.cpp
          C:\VCExamples\test\_mpusbapi.cpp(53) : warning C4068: unknown pragma
          Linking...
             Creating library Debug/test.lib and object Debug/test.exp
          _mpusbapi.obj : error LNK2001: unresolved external symbol __imp__SetupDiGetDeviceInterfaceDetailA@24
          _mpusbapi.obj : error LNK2001: unresolved external symbol __imp__SetupDiEnumDeviceInterfaces@20
          _mpusbapi.obj : error LNK2001: unresolved external symbol __imp__SetupDiDestroyDeviceInfoList@4
          _mpusbapi.obj : error LNK2001: unresolved external symbol __imp__SetupDiGetClassDevsA@16
          LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
          Debug/test.exe : fatal error LNK1120: 5 unresolved externals
          Error executing link.exe.

          test.exe - 6 error(s), 1 warning(s)
  5. The next step is fixing these errors.
       - unknown pragma : This warning comes because the file is originally built for Borland C++ and Borland C++ prgrams can not be understood by VC++. So remove the line #pragma argsused from _mpusbapi.cpp file.

       - error LNK2001: unresolved external symbol : This error came because we need to add setupapi.lib file to the libararies list in the project settings. The functions missing are from this library. So, goto << Project menu->Settings (Alt+F7)->Link Tab >>. Under Object/Library Modules add setupapi.lib and click on ok.

       - error LNK2001: unresolved external symbol _main : This error came as we did not add any code to main.cpp. We will do that at the end.

  6. The next step is setting the byte alignment to 1 byte. For this goto << Project menu->Settings (Alt+F7)->C/C++ Tab >>. Under Category List box select Code Generation. Selecting this displays four more list boxes. Under Struct member alignment select 1 byte.

    Then from same tab, this time from Category List box select Precompiled Headers. Then select Not using precompiled headers and click on OK. If you create some other type of project, then make sure if the precompiled headers agree for 1-byte struct alignment. Normally the compiler throws a warning in case of any differences. If not change the setting to "Not using precompiled headers".
  7. Now open to main.cpp file by selecting it from << Workspace Window->FileView tab>>.
    Copy&Paste the content from C:\MCHPFSUSB\Pc\Mpusbapi\Example Applications\Borland_C\Example 01 - Load-time Linking\console.cpp.
    Dont forget to remove the pragma "#pragma argsused" from this file also.

    NOTE:I added some more code to main.c used in this article. The link to the file is available in the resources box(top-right hand side of screen).
  8. Connect your demo board in the usual way and build and run this application.


In _MPUSBAPI.CPP file there is a DllEntryPoint entry function. To my knowledge the compiler will consider this function as a normal function rather than an entry point as we are not building a DLL here. For exe files main() is the entry point.

If get into trouble because of this function, then you can remove it. Other functions can be called straight away like how we do in Load-time linking.

To use the functions like MPUSBOpen, MPUSBRead etc.. you can follow the same syntax as Load-time linking. All then you need to do is writing a #include "_mpusbapi.h" on top of your source code. Before that you also need to include windows.h. 
   
         

Interacting with Microchip Full Speed USB Demo board using Visual Basic.NET

Source Files
1. Download the Visual Basic.NET Example with _cdecl.
2. Download the Visual Basic.NET Example with _stdcall.


1. What you need to know.


VB 6.0 allows to invoke functions from DLLs with _stdcall only. But VB.NET allows to invoke functions _cdecl calling convention also.

In this article I provided 2 project files for interacting with the Microchip Full Speed USB Demo Board. These projects interact with the Microchip general purpose USB Driver. MPUSBAPI.DLL with _cdecl can be downloaded from Microchip directly. The other example uses _stdcall calling convention. For this the MPUSBAPI.DLL need to be rebuilt with _stdcall convention. Also refer to the previous article for more information on how to use the _stdcall DLL in VB 6.0. Also previous articles gives an idea from where to download the files.

NOTE: The _cdecl DLL contains underscore(_) prefixed to the funtion names. Where as the _stdcall DLL will not contain the underscore(_) prefixed.

To interact with Microchip USB demo board from a PC MPUSBAPI.DLL need to be used.

2. How Visual Basic.NET and Visual Basic 6.0 access DLLs, differences:

Visual Basic.NET is a complete new development environment that is based on the .NET framework. The VB.NET is a complete Object Oriented Programming language and it supports modernization of code extensively. Most of the basic keywords remained same, but there are many additional keywords. Being a full object oriented language, VB.NET supports features like inheritance, polymorphism, abstraction, and encapsulation. As far as declaring the functions to access functions in .DLL file is same as VB 6.0 syntax. The major difference with respect to VB 6.0 version of the example code is in place of VarPtr the member functions of System.Runtime.InteropServices.Marshal need to be used. Marshaling is a mechanism used for converting/representing data between various platforms or environments in way that the content will never be lost. The System.Runtime.InteropServices.Marshal is a .NET class that is used for this purpose.

The UnsafeAddrOfPinnedArrayElement is used for obtaining the base address of the buffer that is used in MPUSBRead and MPUSBWrite function calls.

The other differences are language and environment specific differences. From the VB 6.0 example, .BAS file and .FRM files are converted to their respective .VB files.

3. VBMPUSBAPI.vb:

This file also provides the same set of functions which provided in the previous example.
  • Initialize: Used for initializing the variables.
  • OpenMPUSBDevice: Used for opening the data pipes of the Demo application.
  • CloseMPUSBDevice: Used for closing the opened data pipes.
  • SendReceivePacket: Used for performing the complete Demo application transfer. You can observe that SendData and ReceiveData are passed as Byte arrays. Inside the function the address of the first elements of the Byte arrays are passed to the Read and Write functions in the DLL.


4. VB6PICUSBDemo.vb:

This is the source code file that is generated when VB6PICUSBDemo.frm is ported to VB.NET. This file contains the actual example code on how to use the above functions. This ends the 3 article series on Visual Studio.NET. There is already one article available at www.piccoder.co.uk. So I am not touching the C# aspect.

Interacting with Microchip Full-Speed USB Demo Board using Visual Basic

This is MPUSBAPI Visual Basic 6.0 Example.

Source Code available here.

Modified _stdcall MPUSBAPI.DLL Files available here.


The previous article shows how to connect to the PICDEM FS Demo Board using Visual C++ and Win32 API. The previous article also explains from where to get the required files. So, take a look at it if you are starting from scratch. And this article uses an example application with similar functionality and User Interface as application written in VC++ in the previous article. 

In this article I will explain, how this can be done in Visual Basic 6.0. The Visual Basic.NET takes a different approach which I will explain in the next article. 

The MPUSBAPI.DLL that is provided along with package MCHPFSUSB.ZIP is a dynamic-link library(DLL) that provides a set of public functions for communicating with the Demo Board with the custom driver. And both Visual Basic 6.0 and Visual Basic.NET provides mechanisms to access the Win32 DLL directly even though there is no .LIB file available. For using a DLL in VB one does not need to use the LoadLibrary() API function set. 

But there is a catch. The DLL functions can only be used in VB provided they are implemented using the Standard Calling convention. i.e functions declared with _stdcall. This places a limitation on the usage of a number DLLs in Visual Basic that are developed using Visual C++ or Borland C++ tools if the _cdecl or any other calling convention methods are used while declaring or defining the functions. 

Please refer to http://support.microsoft.com/default.aspx?scid=kb;en-us;Q153586 for more information on how DLL need to build for using in Visual Basic. 

The DLL provided by Microchip is implemented using the _cdecl calling convention. This may be for achieving higher performance. So, we can not use it directly in Visual Basic. The DLL Source project need to be re-compiled by changing the declarations of the exported function to _stdcall. The modified source code of the MPUSBAPI.DLL can be downloaded here. Download this source code and re-build it using Borland C++ Builder tools. 

NOTE
The DLL need to be recompiled by adding _stdcall in place of _cdecl to all exported functions. 

Ok, lets move on now.


First things first, Visual Basic 6.0 does not support pointers. Which means that it is not supporting HANDLEs. HANDLEs are used in Win32 API to access system level objects. The HANDLEs in VC++ are represented as pointers. When it comes to VB, there is no way to declare pointers. But pointer is nothing but a variable that stores in address. An address is a numeric value of 32 bit length in WIN32 Operating Systems. That means variables of type Long datatype can be used for representing HANDLEs in VB. 

Similarly corresponding VB data types which can hold the data need to be identified for each argument and return types of the functions in the DLL. 

For more information on how these functions work, take a look at the previous article. 

Now the task at hand is creating a .BAS file which will hold references to the above listed functions in the syntax that is followed in VB 6.0. 

Ok, it is time to learn some theory.

Next step is creating .BAS file in the Visual Basic with the list of exported (public) functions in the DLL. The MPUSBAPI.DLL has following functions(This DLL is created with the _stdcall and notice that the underscores prefix of the functions are gone.)


  • DWORD MPUSBGetDLLVersion(void)
  • DWORD MPUSBGetDeviceCount(PCHAR pVID_PID)
  • HANDLE MPUSBOpen(/*Input */ DWORD instance, /* Input */ PCHAR pVID_PID, /* Input */ PCHAR pEP, /*Input*/ DWORD dwDir, /*Input*/ DWORD dwReserved);
  • DWORD MPUSBRead(/*Input*/ HANDLE handle, /*Output*/ PVOID pData, /* Input */DWORD dwLen, /* Output */PDWORD pLength, /*Input*/ DWORD dwMilliseconds);
  • DWORD MPUSBWrite(/*Input*/ HANDLE handle, /*Input*/ PVOID pData, /*Input*/ DWORD dwLen, /*Output*/ PDWORD pLength, /*Input*/ DWORD dwMilliseconds);
  • DWORD MPUSBReadInt(/*Input*/ HANDLE handle, /*Output*/ PVOID pData, /* Input */DWORD dwLen, /* Output */PDWORD pLength, /*Input*/ DWORD dwMilliseconds);
  • DWORD MPUSBClose(/*Input*/ HANDLE handle);

  • Keywords used in VB 6.0 for declaring API functions: 

    1. Public:  This keyword is used to indicate that the function declared is public function which can accessed through out the VB program.
    2. Declare:  Used at module level to declare references to external procedures in a dynamic-link library (DLL).
    3. Function/Sub:  Function indicates that the procedure returns a value that can be used in an expression. Sub indicates that the procedure does not return a value.
    4. Lib:  Indicates that a DLL or code resource contains the procedure being declared. The Lib clause is required for all declarations when using a DLL.
    5. Alias:  Indicates that the procedure being called has another name in the DLL. This is useful when the external procedure name is the same as a keyword. You can also use Alias when a DLL procedure has the same name as a public variable, constant, or any other procedure in the same scope. Alias is also useful if any characters in the DLL procedure name are not allowed by the DLL naming convention.

    Syntax used in VB 6.0 for declaring API functions:

    Public | PrivateDeclare { Sub | Function } name Lib "libname" [ Alias "aliasname] [(arglist])] [ As type 

    Example: 
    Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" ( ByVal lpLibFileName As String ) As Long 

    The example shows the LoadLibrary function which we used extensively in previous article when used in VB 6.0. The "kernel32" represents the KERNEL32.DLLfile which is a system Win32 API file and one of the core DLLs of the operating system. Actually the function LoadLibraryA is implemented in this DLL. But we are using the Alias keyword to change the name to LoadLibrary

    This API function takes 1 argument and returns a value. So it is declared as function in VB. As it takes a string as argument, the datatype of the argument is declared as String. As it returns a HANDLE as return value, the return value data type is selected as Long. Similarly public exported functions available in other Windows System DLLs as well as User DLLs can be accessed. If the function name to be used in Visual Basic is same as the function name in the DLL the use ofAlias is not required. 

    The MPUSBAPI.DLL functions looks in the following manner when declared in Visual Basic 6.0. When these declarations are made, make sure that the DLL is in a directory which is listed in the system path. 

    • Public Declare Function MPUSBGetDLLVersion Lib "mpusbapi" () As Long
    • Public Declare Function MPUSBGetDeviceCount Lib "mpusbapi" (ByVal pVID_PID As String) As Long
    • Public Declare Function MPUSBOpen Lib "mpusbapi" (ByVal instance As Long, ByVal pVID_PID As String, ByVal pEP As String, ByVal dwDir As Long, ByVal dwReserved As Long) As Long
    • Public Declare Function MPUSBRead Lib "mpusbapi" (ByVal handle As Long, ByVal pData As Long, ByVal dwLen As Long, ByRef pLength As Long, ByVal dwMilliseconds As Long) As Long
    • Public Declare Function MPUSBWrite Lib "mpusbapi" (ByVal handle As Long, ByVal pData As Long, ByVal dwLen As Long, ByRef pLength As Long, ByVal dwMilliseconds As Long) As Long
    • Public Declare Function MPUSBReadInt Lib "mpusbapi"(ByVal handle As Long, ByVal pData As Long, ByVal dwLen As Long, ByRef pLength As Long, ByVal dwMilliseconds As Long) As Long
    • Public Declare Function MPUSBClose Lib "mpusbapi"(ByVal handle As Long)As Long


    When we take a look at the above declarations which are used in Visual Basic, one can observe that the data types of the arguments in each function almost match the data types of their C language prototypes. But, few are not matching. Out of these one important argument is pData which is originally an array of bytes. But here in VB it is declared as Long. The reason for this declaration is when the data is passed from VB, we are actually passing the address of first element in the array. As we know, the address is an unsigned numerical value, which can be represented in VB with Long type. Once the address is available to a function, the function can do any with the data available in that address. When see the source code files provided along with this project, you can observe that the address of first byte is passed from a Byte array. 

    The VB 6.0 Example code can be downloaded from here

    The (VBMPUSBAPI.BAS) contains all the code related to MPUSBAPI.DLL and also additional functions and data definitions required to communicate with the demo firmware that comes with the demo board. 

    It implements following functions:
    • Initialize: Used for initializing the variables.
    • OpenMPUSBDevice: Used for opening the data pipes of the Demo application.
    • CloseMPUSBDevice: Used for closing the opened data pipes.
    • SendReceivePacket: Used for performing the complete Demo application transfer. You can observe that SendData and ReceiveData are passed as Byte arrays. Inside the function the address of the first elements of the Byte arrays are passed to the Read and Write functions in the DLL.


    The (VB6PICUSBDemo.frm) is VB Form file, which contains the event handles for two check boxes and one command button. These function in-turn calls the functions declared in the .BAS file as per the requirement. The section 7.2 in the previous article shows how the sequence is to be followed. The event handles in this file also follows similar sequence.

        Private Sub Check1_Click()
          [Step A - Declarations]
          Dim send_buf(0 To 64) As Byte
          Dim receive_buf(0 To 64) As Byte
          Dim RecvLength As Long

          [Step B- Open the USB End-points]
          OpenMPUSBDevice

          [Step C- Check the Handles of the End-points to see if the are opened properly]
          If myOutPipe <> INVALID_HANDLE_VALUE And myInPipe <> INVALID_HANDLE_VALUE Then 

              [Step D- Initialize the command to be transmitted to demo firmware]
              RecvLength = 1
              send_buf(0) = 50 '0x32 - SET_LED 
              send_buf(1) = 3 ' LED Number
              'Set LED value based on the check box state
              If Check1.Value = 1 Then
                send_buf(2) = 1
              ElseIf Check1.Value = 0 Then
                send_buf(2) = 0
              End If

              [Step E- Call SendReceivePacket to send the command and to receive the response ]
              If (SendReceivePacket(send_buf, 3, receive_buf, RecvLength, 1000, 1000) = 1) Then

                [Step F- The received data confirms that the command is executed properly ]
                If (RecvLength <> 1 Or receive_buf(0) <> 50) Then
                  MsgBox "Failed to update LED"
                End If

              End If

          End If

          [Step G- Once the operation is completed, close all the open handles ]
          CloseMPUSBDevice

        End Sub

    In the next article I will explain how to use the Visual Basic .NET.