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 27, 2012 at 22:42

Hi, Arthur

I tried to do it without Unsafe code, but the thing is that the structure has a pointer to a pointer, for the mapping sector, I have no clue how to do it without pointers, plus the documentation isawful. The Alternate is for Internal Flash, Option Bytes, etc etc .. it goes from 0 to 4. Here is how you can create the mapping.

#region DLL Imports
[DllImport(
''STDFUPRT.dll''
, EntryPoint = 
''STDFUPRT_CreateMappingFromDevice''
, CharSet = CharSet.Auto)]
unsafe
public
static
extern
UInt32 STDFUPRT_CreateMappingArrayFromDevice([MarshalAs(UnmanagedType.LPStr)]
string
DFUNAME, 
ref
STDFUPRT.UmMAPPING*[] pumMapping, 
ref
UInt32 pNbAlternates);
#endregion
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public
struct
MAPPINGSECTOR
{
public
UInt32 dwStartAddress;
public
UInt32 dwAliasedAddress;
public
UInt32 dwSectorIndex;
public
UInt32 dwSectorSize;
public
byte
bSectorType;
public
byte
UseForOperation;
}
[StructLayout(LayoutKind.Explicit, Pack = 1, CharSet = CharSet.Auto)]
public
unsafe
struct
UmMAPPING
{
[FieldOffset(0)]
public
byte
nAlternate;
[FieldOffset(1)]
public
char
Name;
[FieldOffset(261)]
public
UInt32 NbSectors;
[FieldOffset(265)]
public
MAPPINGSECTOR* pSectors;
}

The arrays indexes give you option bytes etc etc, please let me know if you can get it to work without the unsafe code. Good Luck.
marcoandarcia9
Associate II
Posted on June 27, 2012 at 22:43

Hi, Arthur

I tried to do it without Unsafe code, but the thing is that the structure has a pointer to a pointer, for the mapping sector, I have no clue how to do it without pointers, plus the documentation isawful. The Alternate is for Internal Flash, Option Bytes, etc etc .. it goes from 0 to 4. Here is how you can create the mapping.

#region DLL Imports
[DllImport(

''STDFUPRT.dll''

, EntryPoint =

''STDFUPRT_CreateMappingFromDevice''

, CharSet = CharSet.Auto)]
unsafe
public
static
extern

UInt32 STDFUPRT_CreateMappingArrayFromDevice([MarshalAs(UnmanagedType.LPStr)]

string

DFUNAME,

ref

STDFUPRT.UmMAPPING*[] pumMapping,

ref

UInt32 pNbAlternates);
#endregion
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public
struct

MAPPINGSECTOR
{
public

UInt32 dwStartAddress;
public

UInt32 dwAliasedAddress;
public

UInt32 dwSectorIndex;
public

UInt32 dwSectorSize;
public
byte

bSectorType;
public
byte

UseForOperation;
}
[StructLayout(LayoutKind.Explicit, Pack = 1, CharSet = CharSet.Auto)]
public
unsafe
struct

UmMAPPING
{
[FieldOffset(0)]
public
byte

nAlternate;
[FieldOffset(1)]
public
char

Name;
[FieldOffset(261)]
public

UInt32 NbSectors;
[FieldOffset(265)]
public

MAPPINGSECTOR* pSectors;
}

The arrays indexes give you option bytes etc etc, please let me know if you can get it to work without the unsafe code. Good Luck. PS: I got the Image from hex file to work, my DLLS were outdated
kaczart
Associate II
Posted on June 29, 2012 at 11:05

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6b9&d=%2Fa%2F0X0000000brS%2FobrDCuqpuAr_uZce66l5XqvJFH5UzAk3o9J2G2idvOc&asPdf=false
marcoandarcia9
Associate II
Posted on June 29, 2012 at 15:29

Hi, Arthur

Did you pass the device handle to the Thread_Context? The divide by zero exception usually means there is something missing in the thread context struct. Also the filter image for operation was giving me troubles. I managed to get all my operation to work without the filterImage 
kaczart
Associate II
Posted on June 29, 2012 at 21:08

Hi Marco,

I thought that passing devPath is enough. I've just tried to pass device handle to Context but still the same error.

I've tested also without passing image handle (hImage) and exception doesn't appear, but there's also no operation result (running without stdfu errors, but nothing happen).

I'm thinking what I'm doing wrong.. I can get corretly filled MAPPING structure and MAPPINGSECTOR sub-structure so conclusion is that devPath is also ok, am I right?

CreateImageFromMapping function returns success also, but I think that sth is wrong with image handle - when I passing it to Context structure there's exception (divide by zero). Tried with filtering and without filtering - no difference.

Have you got another idea? Could you paste me your return or erase functions with declarations (dll imports), please? 

Thanks for helping!

greetings

Arthur

kaczart
Associate II
Posted on July 02, 2012 at 12:24

after 3 days finally get it worked! Return operation works fine.

Solution: In DFU_THREAD_CONTEXT structure shouldn't use ''Boolean'' type inbDontSendFFTransfersForUpgrade - just ''byte'' type: // division by zero exception in LaunchOperation

.....
[FieldOffset(36)]
public
Boolean bDontSendFFTransfersForUpgrade;
.....

// correct one

.....
[FieldOffset(36)]
public
byte
bDontSendFFTransfersForUpgrade;
.....

So 'small' mistake and so big waste of time -unbelievable... Thanks for helping! keep in touch
marcoandarcia9
Associate II
Posted on July 03, 2012 at 21:42

Has anybody been able to make it work with safe code? I am trying to rewrite my code to use only safe code but I am having a hard time to make work the createimage from mapping .

jonas239955
Associate II
Posted on July 04, 2012 at 09:49

Hey Marco,

I have been busy with other projects and did not work on this topic in past (and the notification function of this board doesn't really work).

A solution without unsafe code would be great. I will follow the discussion and help if possible.

At the moment I do have problems with the internal bootloader.

kaczart
Associate II
Posted on July 04, 2012 at 10:40

I've tried with safe code but without success. Some says, that it's possible - but there's much ''cleaner'' with unsafe code. 

Finally did erase and upgrade operation on .dfu files. Now working on hex files hard coded in application (I don't want to share .hex file to user).

ps. filter image is working, but you need to declare bool as Int32  (4 byte) in dll import.
marcoandarcia9
Associate II
Posted on July 09, 2012 at 18:30

Hi, I am trying to rewrite some of my code to make it safer, without having to write it in C++(which I hate) or do any major rewrites that I am not sure is gonna work and waste another week trying so.

this is a small part I want to rewrite.

m_CurrentFunction = 
''Erasing...''
;
STDFUPRT.DFUThreadContextP ContextP = 
new
STDFUPRT.DFUThreadContextP();
STDFUPRT.UmMAPPING umMapping = 
new
STDFUPRT.UmMAPPING();
STDFUPRT.MAPPINGSECTOR mapinfo = 
new
STDFUPRT.MAPPINGSECTOR();
UInt32 OperationCode = 0; 
// initialize operation code to random value to be rewritten later. 
UInt32 pNbAlternates = 0;
IntPtr Imagehandle = IntPtr.Zero;
ContextP.hDevice = info;
ContextP.DFUGUID = GUID_DFU;
ContextP.APPGUID = GUID_APP;
unsafe
{
byte
* pointer;
char
[] devicePath = DetailData.DevicePath.ToCharArray();
Debug.WriteLine(devicePath[0]);
pointer = &ContextP.szDevLink;
Debug.WriteLine((
int
)pointer);
for
(
byte
loop = 0; loop <= DetailData.DevicePath.Length - 1; loop++)
{
*pointer = (
byte
)devicePath[loop];
pointer++;
}
pointer = 
null
;
}

I want to pin ContextP and prevent the Garbage Collector from relocating that memory. However I have been trying to do it with no success. I was wondering if any of you guys managed to pin this memory or know how to do it. Thanks in advance.