cancel
Showing results for 
Search instead for 
Did you mean: 

Accessing ST Dfuse DLL with C#

jonas239955
Associate II
Posted on April 12, 2012 at 10:26

To integrate firmware update functionality into a custom c♯ application I start to use ST Dfuse dll from c♯. I managed to enumerate and identify the device (UM0392 - 3.1 and 3.2) but now get stucked  while trying to erase the device. Out of the manual:

DWORD OperationCode;

PDWORD pNbAlternates;

PMAPPING pMapping;

PHANDLE pHandle;

// Programming the operation contex

lstrcpy(Context.szDevLink, DFUName);

Context.DfuGUID=GUID_DFU;

Context.AppGUID=GUID_APP;

Context.Operation=OPERATION_ERASE;

Context.bDontSendFFTransfersForUpgrade= TRUE;

STDFUPRT_CreateMappingFromDevice((LPSTR)(LPCSTR)DFUName,&pMapping, &NbAlternates);

STDFUFILES_CreateImageFromMapping(pHandle, pMapping);

STDFUFILES_FilterImageForOperation(hImage, m_pMapping+TargetSel,

OPERATION_ERASE, FALSE);

Context.hImage=hImage;

if( STDFUPRT_LaunchOperation(&Context, &OperationCode) != STDFUPRT_NOERROR)

{

Printf(�Erase error�);

}

The call of STDFUPRT_LaunchOperation() does always return a STDFUPRT_BADPARAMETER error.

Is there a way to get some more information about this error? Which parameter is bad?

The first parameter in LaunchOperation() is a pointer to the struct DFUThreadContext. I rebuilt this struct in c♯ using the information given in UM0384.pdf chapter 4.3.4. My UM0384 is revision 1 - June 2007 - wonder if that user manual is still up-to-date?!?

I did not find UM0384 on the webpage (my copy is out of the package UM0412.zip). Does anyone have a newer one?

Thanks in advance for any help

#st-dfu #st-dfuse #dfuse
52 REPLIES 52
marcoandarcia9
Associate II
Posted on June 11, 2012 at 15:21

Hi, Jonas. This is how my ThreadContext looks like. I am going to try and use your's and see what happens. 

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack=1)]

        public struct DFUThreadContext

        {

            //[FieldOffset(0)]

            public Guid DfuGUID;

            //[FieldOffset(16)]

            public Guid AppGUID;

            //[FieldOffset(32)]

            public Int16 Operation;

            public Int32 bDontSendFFTransfersForUpgrade;

            public IntPtr hImage;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string szDevLink;

            public UInt32 dwTag;

            public Byte Percent;

            public UInt16 wTransferSize;

            public DFUSTATUS LastDFUStatus;

            public Int32 CurrentRequest;

            public UInt32 CurrentNBlock;

            public UInt32 CurrentLenght;

            public UInt32 CurrentAddress;

            public UInt32 CurrentImageElement;

            public UInt32 ErrorCode;

            public IntPtr hDevice;

        }

I saw your post on the test you ran using the list and having the parameters starting in the same pointer address. I think I definitely have to fix this struct. I was thinking that maybe was my data types, so I went to the msdn and found some tables for converting unmanaged to managed but it did not work. 

This is how my erase looks like. I pretty much follow each step on the programming guide.

public void Erase()

        {

            try

            {

                UInt32 OperationCode = STDFUPRT.OPERATION_ERASE;

                UInt32 pNbAlternates = 4;

                IntPtr phandle = IntPtr.Zero;

                Context.szDevLink = DetailData.DevicePath;

                Context.DfuGUID = GUID_DFU;

                Context.AppGUID = GUID_APP;

                Context.Operation = STDFUPRT.OPERATION_ERASE;

                Context.bDontSendFFTransfersForUpgrade = 1;

                unsafe

                {

                    UInt32 error_code = STDFUPRT_CreateMappingFromDevice(Context.szDevLink, ref pumMapping, ref pNbAlternates);

                    Debug.WriteLine(''Error_Code: 0x'' + error_code.ToString(''X''));

                    Debug.WriteLine(''Erase() pNbAlternates: '' + pNbAlternates + '' Mapping Name: '' + umMapping.Name + '', NbSectors: '' + umMapping.NbSectors);

                    umMapping = *pumMapping;

                    error_code = STDFUFILES_CreateImageFromMapping(ref phandle, ref umMapping);

                    Debug.WriteLine(''Erase() error code: 0x'' + error_code.ToString(''X''));

                    Debug.WriteLine(''Erase() Name: '' + umMapping.Name + '' Sectors:'' + umMapping.NbSectors);

                    Debug.WriteLine(''Erase(): phandle: 0x'' + phandle.ToString(''X''));

                    error_code = STDFUFILES_FilterImageForOperation(phandle, ref umMapping, (uint)Context.Operation, false);

                    Debug.WriteLine(''Erase(): error_code =  0x'' + error_code.ToString(''X''));

                    Debug.WriteLine(''Device Handle: '' + Context.hDevice + '', Image Handle: '' + Context.hImage + '', Curent Status: '' + Context.CurrentRequest);

                    Context.hImage = phandle;

                    error_code = STDFUPRT_LaunchOperation(ref Context, ref OperationCode);

                    Debug.WriteLine(''Erase(): LaunchOperation: 0x'' + error_code.ToString(''X''));

                }

            }

 
marcoandarcia9
Associate II
Posted on June 11, 2012 at 15:46

With this version of the structure, it doesn't return any error, nor the access violation exception it actually returns no error 0x1234000000 for the launch operation, but it does not erase my board. 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack=1)]

        public struct DFUThreadContext

        {

            //[FieldOffset(0)]

            public Guid DfuGUID;

            //[FieldOffset(16)]

            public Guid AppGUID;

            //[FieldOffset(32)]

            public int Operation;

            public Boolean bDontSendFFTransfersForUpgrade;

            public IntPtr hImage;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string szDevLink;

            public UInt32 dwTag;

            public Byte Percent;

            public UInt16 wTransferSize;

            public DFUSTATUS LastDFUStatus;

            public Int32 CurrentRequest;

            public UInt32 CurrentNBlock;

            public UInt32 CurrentLenght;

            public UInt32 CurrentAddress;

            public UInt32 CurrentImageElement;

            public UInt32 ErrorCode;

            public IntPtr hDevice;

        }

jonas239955
Associate II
Posted on June 11, 2012 at 15:57

Did you test the addresses of the values? I doubt they are in the correct order.

I haven't been able to align them without LayoutKind.Explicit. OPERATION_RETURN does now work but ERASE still doesn't ...

marcoandarcia9
Associate II
Posted on June 11, 2012 at 16:53

I am still working on the Erase Operation. Let me know if you get it to work, right now usin the ThreadContext that I posted the LaunchOperation runs, and returns no error, but it does not erase my board, it executes super fast but does not erase the board. I wonder if I have to specify the addresses that I want to erase. 

The DFU Tester does something similar when I don't click on create from map and click erase.  it goes through the erase operation super fast but it does not erase the board. 
marcoandarcia9
Associate II
Posted on June 11, 2012 at 22:57

Hi, Jonas. 

I am still working on the erase operation, and I wanted to ask you about the FilterImageForOperation function. This is how my signature looks like. 

 [DllImport(''STDFUFILES.dll'', EntryPoint = ''STDFUFILES_CreateImageFromMapping'', CharSet = CharSet.Auto)]

public static extern UInt32 STDFUFILES_CreateImageFromMapping(ref IntPtr handle, ref STDFUPRT.UmMAPPING umMapping);

I don't know if I should pass the actual pointer for umMapping because in the example on the Programming guide they have this.

STDFUFILES_FilterImageForOperation(phandle, umMapping+tarSel,OperationCode, false); 

and they set it to zero in the source code. is tarSel the AltSet shown in the DFUTester? 

I know you use that function for the Return Operation so I imagine you got that working right. 

thanks in advance. 
jonas239955
Associate II
Posted on June 12, 2012 at 09:51

Hi Marco,

I do have exactly the same signature for the FilterImage function. Did you test with OPERATION_RETURN? I guess your version would work too.

However, if you want to have it like in the example you may use the functions like this:

[DllImport(''STDFUPRT.dll'')]

unsafe public static extern UInt32 STDFUPRT_CreateMappingFromDevice([MarshalAsAttribute(UnmanagedType.LPStr)] String szDevLink, UmMAPPING** ppMapping, ref UInt32 pNbAlternates);

[DllImport(''STDFUFiles.dll'')]

unsafe public static extern UInt32 STDFUFILES_CreateImageFromMapping(ref IntPtr pHandle, UmMAPPING* pMapping);

UmMAPPING* pUmMapping = null;

STDFUPRT_CreateMappingFromDevice(devicePath, &pUmMapping, ref pNbAlternates);

STDFUFILES_CreateImageFromMapping(ref pHandle, pUmMapping);

is tarSel the AltSet shown in the DFUTester? <-- Yes I think so. pNbAlternates returns 4 and there are 4 sets in STDFU Tester. The first one is called ''Internal Flash'' and has TarSel-Number=0. Because we want to delete the internal flash we don't need the ''+tarSel''.

------

The OPERATION_ERASE command still does not work. I do have the same behaviour like you - fast execute, no error, no erasing.

After STDFUPRT_LaunchOperation() I check the progress by calling STDFUPRT_GetOperationStatus() in a loop. Context.percent raises immediately from 0% to 100%:

My debug output:

Erase: 0% dwTag: 0 wTransfSize: 2048 DFUbStatus: 0 DFUbState: 0 DFUiStr: 0 CurrReq: 0x0 CurrNBlk: 0x0 CurrLen: 0x0 CurrAddr: 0x0 CurrImElem: 0x0 Error: 0x0 hDevice: 0x0

Erase: 0% dwTag: 2 wTransfSize: 2048 DFUbStatus: 255 DFUbState: 254 DFUiStr: 255 CurrReq: 0x13000000 CurrNBlk: 0xFFFFFFFF CurrLen: 0xFFFFFFFF CurrAddr: 0x0 CurrImElem: 0xFFFFFFFF Error: 0x12340000 hDevice: 0xBD43E08

Erase: 0% dwTag: 3 wTransfSize: 2048 DFUbStatus: 255 DFUbState: 254 DFUiStr: 255 CurrReq: 0xF000000 CurrNBlk: 0xFFFFFFFF CurrLen: 0xFFFFFFFF CurrAddr: 0x0 CurrImElem: 0xFFFFFFFF Error: 0x12340000 hDevice: 0xBD43E08

Erase: 100% dwTag: 7 wTransfSize: 2048 DFUbStatus: 0 DFUbState: 2 DFUiStr: 0 CurrReq: 0xF000000 CurrNBlk: 0xFFFFFFFF CurrLen: 0xFFFFFFFF CurrAddr: 0x0 CurrImElem: 0xFFFFFFFF Error: 0x12340000 hDevice: 0xBD43E08

Erase: 100% dwTag: 7 wTransfSize: 2048 DFUbStatus: 0 DFUbState: 2 DFUiStr: 0 CurrReq: 0xF000000 CurrNBlk: 0xFFFFFFFF CurrLen: 0xFFFFFFFF CurrAddr: 0x0 CurrImElem: 0xFFFFFFFF Error: 0x12340000 hDevice: 0xBD43E08

Erase: 100% dwTag: 7 wTransfSize: 2048 DFUbStatus: 0 DFUbState: 2 DFUiStr: 0 CurrReq: 0xF000000 CurrNBlk: 0xFFFFFFFF CurrLen: 0xFFFFFFFF CurrAddr: 0x0 CurrImElem: 0xFFFFFFFF Error: 0x12340000 hDevice: 0xBD43E08

I do not exactly know how to interpret these values and do not have any idea what else possibly could be wrong.

Hope you have more success!
marcoandarcia9
Associate II
Posted on June 12, 2012 at 17:20

Hi, Jonas

I haven't tried the Return Operation Yet, for My app I just want to be able to Erase, Download, Read/Write Protect my board. 

I am trying to use the STDFUPRT_GetOperationStatus() to obtain the progress of the Erase Operation, but is not updating the Context.progress nor context.currentaddress

[DllImport(''STDFUPRT.dll'', EntryPoint = ''STDFUPRT_GetOperationStatus'', CharSet = CharSet.Auto)]

public static extern UInt32 STDFUPRT_GetOperationStatus(UInt32 operationCode, ref STDFUPRT.DFUThreadContext context);

Start Address is 0x8000000 and sector Size is 16384 matching perfectly the first Row in the DFU Tester. I think that's why its going so fast through the operation; However is not erasing that sector. 

Also, Could I see your ThreadContext Structure? I want to change mine to explicit as you did, just to rule out that possibility. I tried to declare it explicit, but when I compile it says there is overlapping. 

for the operation I have the operation parameter in the ThreadContext structure declared as an int, when I tried to change it to Uint16 LaunchOperation gave me the wrong parameter error. Operation is definitely 4 bytes(sloppy documentation). 

this might be the reason why is not updating the context.progress when I call GetOperationStatus()

Thanks in advance. 

jonas239955
Associate II
Posted on June 13, 2012 at 09:43

Hey Marco,

Return Operation is a good test because you don't need a filtered image for that operation.

After a IMMENSE waste of time I finally got the right structure of DFUThreadContext. There are several field sizes wrong in the manual from ST.

To be honest I hesitate to share the solution here in the ST forum because they really don't care about customers. There is absolutely no help from ST - not a single answer/comment.

I'd rather paste it on an other site or send it to you by mail.

However, it may help other customers .. so here we go:

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]

public struct DFUThreadContext

{

    [FieldOffset(0)]

    public Guid DFUGUID;            

    [FieldOffset(16)]

    public Guid APPGUID;

    [FieldOffset(32)]

    public UInt32 Operation;

    [FieldOffset(36)]

    public byte bDontSendFFTransfersForUpgrade;

    [FieldOffset(40)]

    public IntPtr hImage;

    [FieldOffset(44)]

    public byte szDevLink;

    [FieldOffset(304)]

    public UInt32 dwTag;

    [FieldOffset(308)]

    public byte percent;

    [FieldOffset(309)]

    public UInt16 wTransferSize;

    [FieldOffset(311)]            

    public byte LastDfuStatus_bStatus;

    [FieldOffset(312)]

    public byte LastDfuStatus_bwPollTimeout;

    [FieldOffset(315)]

    public byte LastDfuStatus_bState;

    [FieldOffset(316)]

    public byte LastDfuStatus_iString;

    [FieldOffset(317)]

    public int CurrentRequest;

    [FieldOffset(321)]

    public uint CurrentNBlock;

    [FieldOffset(325)]

    public uint CurrentLenght;

    [FieldOffset(329)]

    public UInt32 CurrentAddress;

    [FieldOffset(333)]

    public uint CurrentImageElement;

    [FieldOffset(337)]

    public UInt32 ErrorCode;

    [FieldOffset(341)]

    public IntPtr hDevice;

}

 

You have to fill in szDevLink char by char with pointers.

OPERATION_ERASE does work if you don't use STDFUFILES_FilterImageForOperation(). Just do not filter the image.

Cheers 
marcoandarcia9
Associate II
Posted on June 13, 2012 at 15:44

Hi, Jonas

I couldn't agree more with you, I have been sending emails requesting updated documentation and asking question for technical support these past 2 weeks, and haven't got a reply yet. 

I see you defined the DFUSTATUS Structure inside the DFUThreadContext. smart. 

Thank you very much for sharing the knowledge, I have to try the erase now without the FilterImage operation. Yesterday I spent the whole day trying to figure out the ThreadContext structure, and how to make it work. 

 

marcoandarcia9
Associate II
Posted on June 14, 2012 at 21:54

Hi, Jonas

I am still trying to get the Erase operation to work properly, I am trying to call LaunchOperation without filtering the image, how do you get the  Context.transferSize?

 

Also when I call the GetOperationStatus it doesnt return error; however after like 4  iterations in the loop after LauchOperation  I get Context.ErrorCode = 0x12340005 which is ''The system cannot open the specified driver''

I think its because the Operation ended, however I never got the progress to change, nor erased anything.

For the ThreadContext.szDeviceLink it is supposed to be a byte array? or a byte? if it is a byte how to you storage the entire string in a single byte?

I was wondering if you encountered a similar issues.

Thanks in advance.