|
Ok I did add this to verify the downloaded code:
for (int nIdxElem = 0; nIdxElem < dfuTarBurn.aelements.Length; ++nIdxElem)
{
DFUElement dfuElem = dfuTarBurn.aelements[nIdxElem];
for (UInt32 BlockNumber = 0; BlockNumber <= (uint)dfuElem.abyData.Length / MaxWriteBlockSize; BlockNumber++)
{
if (OnFirmwareUpdateProgress != null) OnFirmwareUpdateProgress(this,
new FirmwareUpdateProgressEventArgs(10 + (80 * BlockNumber * MaxWriteBlockSize / dfuElem.abyData.Length),
"Verify block " + BlockNumber.ToString(), false));
byte[] Block = dfuElem.abyData.Skip((int)(MaxWriteBlockSize * BlockNumber)).Take((int)MaxWriteBlockSize).ToArray();
int BLen = Block.Length;
if (Block.Length < MaxWriteBlockSize)
{
i = Block.Length;
Array.Resize(ref Block, (int)MaxWriteBlockSize);
for (; i < MaxWriteBlockSize; i++)
{
Block[i] = 0xFF;
}
}
CheckBlock(hDevice, dfuElem.dwAddr, Block, BlockNumber, BLen);
System.Threading.Thread.Sleep(20);
}
and here is the chechblock function:
private void CheckBlock(IntPtr hDevice, UInt32 Address, byte[] Data, UInt32 BlockNumber, int BlockLen)
{
byte[] Command = new byte[5];
byte[] ReadData=new byte[10000];
DFU_Status dfuStatus = new DFU_Status();
if (Data.Length > MaxWriteBlockSize)
{
throw new Exception("Block size too big (" + Data.Length.ToString() + ")");
}
if (0 == BlockNumber)
{
SetAddressPointer(hDevice, Address);
}
STDFU_GetStatus(ref hDevice, ref dfuStatus);
while (dfuStatus.bState != STATE_DFU_IDLE)
{
STDFU_ClrStatus(ref hDevice);
STDFU_GetStatus(ref hDevice, ref dfuStatus);
}
STDFU_Upload(ref hDevice, ReadData, (UInt32)Data.Length, (UInt16)(BlockNumber + 2));
for(int i=0;i<BlockLen;i++)
{
if(Data[i] != ReadData[i])
{
throw new Exception("Verification error at: (" + BlockNumber.ToString() + ")");
}
}
STDFU_GetStatus(ref hDevice, ref dfuStatus);
while (dfuStatus.bState != STATE_DFU_IDLE)
{
STDFU_ClrStatus(ref hDevice);
STDFU_GetStatus(ref hDevice, ref dfuStatus);
}
}
remember to add the upload:
[DllImport("STDFU.dll", EntryPoint = "STDFU_Upload", CharSet = CharSet.Ansi)]
public static extern UInt32 STDFU_Upload(ref IntPtr hDevice, [MarshalAs(UnmanagedType.LPArray)]byte[] pBuffer, UInt32 nBytes, UInt16 nBlocks);
|
|
|
|
|
Thank you so much for these source codes!
|
|
|
|
|
Hi Mark:
Thanks a lot for the very useful program, I'm so lucky to find this thread as this is the what I really need. I'm actually wants to make a very simple flash programmer for my personal project using STM32F030K6 chip via USB.
I'm a novice and still learning in programming and I hope to get some advice and tips from the experts like you.
I have some questions:
- Do you have some example picture of USB cable connection to the IC or board?
- Our firmware is in BIN file, do you think its possible to convert it to DFU or any advice?
- Can I use UART to connect between USB and this chip?
Thanks a lot and waiting for your reply.
Denzil
|
|
|
|
|
Maybe a good features can be a method for set/reset the read protection bit register.
|
|
|
|
|
Hi,
I need to perform the file conversion activity in my application only. I will have to use the dll from the C++ application(from DfeSe demo application). i can able to refer these dll's in my application. But i could not able to call the methods successfully. application got closed without any errors or exceptions. can anyone help me out in writing this application in C#.
thanks
|
|
|
|
|
|
Hi, have a stupid question! I don't use Visual Studio, but seems like it is required to build this project. Is there a free version I can use to build this project? I see there are many different free and community versions of visual studio available.
|
|
|
|
|
I had a quick look at his source - I don't think there's anything in there that wont compile with a Visual Studio Express version - so grab Visual Studio 2013 Express and give it a go
|
|
|
|
|
Hi, thanks for quick reply! On top of the visual studio express page there is a large link to the new "Visual Studio Community 2013". I don't know either. They are quite large to download. Seems like they recommend "Visual Studio Community 2013". Will this also compile with that?
|
|
|
|
|
Thank you for the project, works like a dream!
If somebody'd like to have a built-in converter functionality just add the following lines:
[DllImport("STDFUFiles.dll", EntryPoint = "STDFUFILES_ImageFromFile", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 STDFUFILES_ImageFromFile([MarshalAs(UnmanagedType.LPStr)]string pPathFile, ref IntPtr pImage, byte nAlternate);
[DllImport("STDFUFiles.dll", EntryPoint = "STDFUFILES_SetImageName", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 STDFUFILES_SetImageName(IntPtr PImage, [MarshalAs(UnmanagedType.LPStr)]string dfufilename);
[DllImport("STDFUFiles.dll", EntryPoint = "STDFUFILES_CreateNewDFUFile", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 STDFUFILES_CreateNewDFUFile([MarshalAs(UnmanagedType.LPStr)]string dfufilename,ref IntPtr handle,UInt32 Vid,UInt32 Pid, UInt32 Bcd);
[DllImport("STDFUFiles.dll", EntryPoint = "STDFUFILES_AppendImageToDFUFile", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 STDFUFILES_AppendImageToDFUFile(IntPtr dfuhandle,IntPtr image);
[DllImport("STDFUFiles.dll", EntryPoint = "STDFUFILES_CloseDFUFile", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 STDFUFILES_CloseDFUFile(IntPtr dfufile);
[DllImport("STDFUFiles.dll", EntryPoint = "STDFUFILES_DestroyImage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 STDFUFILES_DestroyImage(ref IntPtr image);
public enum DFUResult : int
{
STDFU_NOERROR = 0x12340000
};
Calling order: (dummy variables!)
UInt32 vid = 0x0483;
UInt32 pid = 0;
IntPtr dfuhandler = IntPtr.Zero;
if ((uint)DFUResult.STDFU_NOERROR == STDFUFILES_ImageFromFile(hexname, ref handler, arr))
{
result = STDFUFILES_SetImageName(handler, "name");
}
result = STDFUFILES_CreateNewDFUFile(dfuname, ref dfuhandler, vid, pid, pid);
result = STDFUFILES_AppendImageToDFUFile(dfuhandler, handler);
result = STDFUFILES_CloseDFUFile(dfuhandler);
STDFUFILES_DestroyImage(ref handler);
|
|
|
|
|
Well done and very useful example for those who develop for ST Micro's DfuSe firmware update capabilities.
|
|
|
|
|
Hi Mark,
Started going over the code this morning. Compiled fine. Modified the Guid's, VID and PID for my application. Here's something I noticed. When my device is in HID mode and connected, I click on the Program button, select the *.dfu file (which the program likes), then the FindDevice() method does indeed find my device, but when the call to HidD_SetFeature(_ParentHandle, Feature, 65) is made (to kick the HID device from HID to DFU mode, _ParentHandle hasn't been set yet to an opened HID device.
Thought you might like to know. See suggested fixes below. Only the FirmwareUpdate.cs file is affected. Please do a diff to see changes. Sorry, I untabbed and outdented to make it more readable.
Best to you,
Jeff
====== Updates to FirmwareUpdates.cs ==========================
/// <summary>
/// Look for a HID device with the expected VID and PID, if found, send the detach message
/// </summary>
private void FindAndDetachHID()
{
int i;
string hidPath;
// If we are connected to a device with the expected VID and PID, send the detach message
if (FindDevice(HID_VID, HID_PID, out hidPath))
{
_ParentHandle = CreateFile(hidPath, (GENERIC_READ | GENERIC_WRITE), 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
// Assign a buffer in unmananged memory
IntPtr Feature = Marshal.AllocHGlobal(65);
Marshal.WriteByte(Feature, 0, HID_DETACH_REPORT_ID);
Marshal.WriteByte(Feature, 1, USAGE_DETACH);
for (i = 2; i < 65; i++)
{
Marshal.WriteByte(Feature, i, 0);
}
if (HidD_SetFeature(_ParentHandle, Feature, 65))
{
if (OnFirmwareUpdateProgress != null) OnFirmwareUpdateProgress(this, new FirmwareUpdateProgressEventArgs(1, "HID detach success", false));
}
else
{
// SensiPOD usually replies to this with 31, ERROR_GEN_FAILURE, but it still works...
if (OnFirmwareUpdateProgress != null) OnFirmwareUpdateProgress(this, new FirmwareUpdateProgressEventArgs(1, "HID detach error = " + (Marshal.GetLastWin32Error()).ToString(), false));
//throw (new Exception("HID detach failed"));
}
Marshal.FreeHGlobal(Feature);
_ParentHandle.Close();
System.Threading.Thread.Sleep(5000);
}
}
/// <summary>
/// Function to find a device with a given VID and PID
/// </summary>
/// <param name="nVid">VID to search for</param>
/// <param name="nPid">PID to search for</param>
/// <param name="sPath">Path to device if found</param>
/// <returns>True if matching device is found</returns>
public bool FindDevice(UInt16 nVid, UInt16 nPid, out string sPath)
{
String strDevicePath;
string strPath = string.Empty;
string strSearch = string.Format("vid_{0:x4}&pid_{1:x4}", nVid, nPid); // first, build the path search string
Guid gHid;
sPath = ""; // For the case of no device.
HidD_GetHidGuid(out gHid); // next, get the GUID from Windows that it uses to represent the HID USB interface
IntPtr hInfoSet = SetupDiGetClassDevs(ref gHid, null, IntPtr.Zero, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); // this gets a list of all HID devices currently connected to the computer (InfoSet)
try
{
DeviceInterfaceData oInterface = new DeviceInterfaceData(); // build up a device interface data block
oInterface.Size = Marshal.SizeOf(oInterface); // 28 in 32bit or 32 in 64bit mode,
// Now iterate through the InfoSet memory block assigned within Windows in the call to SetupDiGetClassDevs
// to get device details for each device connected
int nIndex = 0;
while (SetupDiEnumDeviceInterfaces(hInfoSet, 0, ref gHid, (uint)nIndex, ref oInterface)) // this gets the device interface information for a device at index 'nIndex' in the memory block
{
strDevicePath = GetDevicePath(hInfoSet, ref oInterface); // get the device path (see helper method 'GetDevicePath')
if (strDevicePath.IndexOf(strSearch) >= 0) // do a string search, if we find the VID/PID string then we found our device!
{
sPath = strDevicePath; // save the path to our device.
return true;
}
nIndex++; // if we get here, we didn't find our device. So move on to the next one.
}
if (0 != Marshal.GetLastWin32Error())
{
if (ERROR_NO_MORE_ITEMS == Marshal.GetLastWin32Error())
{
// Do nothing, this just means the ARM_Board wasn't found
}
else if (ERROR_INVALID_USER_BUFFER == Marshal.GetLastWin32Error())
{
throw new Exception("Size member of hInfoSet is not set correctly (5 for 32bit or 8 for 64bit)");
}
else
{
throw new Exception("SetupDiEnumDeviceInterfaces returned error " + Marshal.GetLastWin32Error().ToString());
}
}
}
finally
{
// Before we go, we have to free up the InfoSet memory reserved by SetupDiGetClassDevs
SetupDiDestroyDeviceInfoList(hInfoSet);
}
return false; // oops, didn't find our device
}
|
|
|
|
|
Hi Jeff,
Fair comment. In my application of which this is a part, the main application connects to the HID device and opens the ParentHandle before doing anything else. It uses the HID interface to talk to the device and firmware update is just a side show. But of course the code I've posted doesn't include that bit.
Thanks for the stars,
Mark
|
|
|
|
|
I'll should have time to take a peek at this tomorrow.
|
|
|
|
|
Very explanatory and well done. Exactly what I was looking for.
|
|
|
|
|
Hi Mark,
This article is just what I've been looking for! I was gearing up to start from scratch and ran across your fine work!
How do I go about downloading the zip file? Is there a way? I'm new to codeproject.
Also, have you built any HID devices that have the DFUse interface defined? I've been attempting many things in the device descriptor and configuration, all based on ST articles, and I can't get windows to recognize the composite device. It connects but fails when windows attempts to select Configuration 1. Any tips? I think it may have to do with the device driver.
I can get the pure HID device to work just fine, but when I expand bNumInterfaces from 1 to 2 and add the DFUse interface, I can't get it to work.
### UPDATED ###
Right after I wrote this, I noticed I had the interface subclass set to BOOT=1 for the DFU interface. Set it to zero and wha-la Windows likes it!
Best regards,
Jeff
modified 1-Mar-13 13:24pm.
|
|
|
|
|
It looks almost as though the zip file isn't showing because the change with the zip file attached hasn't been approved yet.
|
|
|
|
|
I would also very much like the library and source code for this.
Oh, and great work by Mark McLean!
|
|
|
|
|
Hi,
I've updated the tip to include a link to the zip file. Sorry about that.
Thanks for the great feedback,
Mark
|
|
|
|
|