Programmatically upload code - atmega32u4 - VC++

m32u4_prog_intro.jpg I had a small project that need to deliver firmware for atmega32u4 for my customers. And of course, they aren’t tech-savvy like me. It was impossible to guide them to use arduino to flash directly using source code. More importantly, I don’t want to share my source code. There is only one option for me that build an avrdude wrapper that detect atmega32u4 and run avrdude automatically. This tutorial is about uploading firmware to atmega32u4 programmatically using AVR109 app note in Visual Studio.


- Collecting a suitable version of avrdude for just atmega32u4
- Uploading hex to Pro Micro - atmega32u4
- Detect COM port that leonardo bootloader uses
- Force reset Leonardo into bootloader
- Run avrdude using system()
- Setup a file server to store fw and tools


The newest avrdude is 6.3 (465 KB) that comes with a huge configuration file avrdude.conf (480 KB). The configuration file is meant for various AVR microcontroller families and it’s big.

You can use the newest version and the full configuration file and that’s it.

For me I like to use the older avrdude which is smaller and also trim down configuration file for just atmega32u4 only. Why? Because I will put the avrdude and configuration file on my file server, so that it will be downloaded every times updater program is run. All I need is just deliver a small executable file. If I need to build new firmware for my customer, I don’t have to rebuild the updater for this matter.

You can get binary releases of avrdude here or just use the old version with trimmed configuration: avrdude_m32u4.rar


Almost all atmega32u4 boards out there, clones and originals such as sparkfun Pro Micro or Arduino Micro, can be programmed the same way, using avr109 bootloader protocol. Basically, you run a simple console command like this:

avrdude.exe -Cavrdude.conf -pm32u4 -cavr109 -D -P COM2 -b57600 -Uflash:w:firmware01.hex:i

Let assume the clones and Pro Micro use similar bootloader to arduino leonardo and arduino driver is used for this project.

If your target board has a blank chip, it will stay on bootloader and will wait for programming forever. If not, it will stop on bootloader for about 8s then proceed to main program. In this small time window, your system detects new hardware, installs driver and then you can see what COM port is used in device manager, but you have to be fast. Run that command in 8s time frame to upload code. COM2 is used as example in previous command.


This is what shows on PC without arduino drivers. The same for bootloader just with different COM port.


There are a few methods to obtain the list of COM ports:
- Try open COM port from COM1 to COM16, lets hope there aren’t so many occupied COM ports .
- Get query from WMI
- Read registry to get list of COM ports

First method is likely impossible, although I used it for update time for my Word clock and or Analog clock.

The second method is kind of complex, I don’t want to learn this kind of SQL language just to enumerate COM ports. Well, if you are passionate about programming, you can dig deeper into this WMI. Who knows if you may get a lot of crazy things.

The third method is best one IMO. Each time computer enumerates a device, it will update registry with the new connected device. The first location that looks interesting is


//In short, I will use HKLM 


Only small problem is, there is no friendly name in these list. This is useful for searching other Serial Devices as well.

But this could be improved by just reading another interesting registry location



This location contains the list of active USB serial devices which Arduino Leonardo and alike is. The previous location says 3 COM devices but this location specifically says there is only 1 serial device as indicated by by DWORD value Count. Use count id string to get the related data of these enumerated devices


Your USB VID, PID or code after may be different, but that is okay since you just copy it into the next registry query.

Then we just simply add each USB serial device found to a custom struct, USBSER.


You can use this header for that function
reg_q.h registry query to get list of USB serial device


Either you hit reset button on the little board or unplug and plug it in again to reset it into bootloader, that is how you do it when upload sketch from Arduino IDE.

Another method is open COM port with baud rate 1200 then close. This will also trigger reset of USB connection.

	HANDLE serialHandle;
	TCHAR buffer32[32];
	formatString(buffer32,L"\\\\.\\COM%d\\", PORTNO);
	//_COM_busy = TRUE;
	if (serialHandle) 
		DCB serialParams = { 0 };
		serialParams.DCBlength = sizeof(serialParams);

		GetCommState(serialHandle, &serialParams);
		serialParams.BaudRate = CBR_1200;
		serialParams.fDtrControl = DTR_CONTROL_DISABLE;
		serialParams.fRtsControl = RTS_CONTROL_ENABLE;
		SetCommState(serialHandle, &serialParams);
	CloseHandle (serialHandle);
	//_COM_busy = FALSE;

Only a small problem is different COM port is assigned to Leonardo bootloader. No worries, just call GetListUSBser() in reg_q.h to get a list of USB serial device and compare with the list before force reset. Or you can check for the friendly name Arduino Leonardo bootloader specifically, assuming Arduino driver installed.


	int ntime = 40;

	while(ntime > 0 && PROGRAM_PORT == 0)
		Sleep (250);
		USBSER us[10];

		GetListUSBser(us); 	// check port again to get any bootloader device.
		TCHAR bl= 'b';
		for (int k = 0; k < 10; k++)
			if (us[k].PORT_NO == 0) break; // there is no such COM port COM0
			if (us[k].Name[17] == bl) // if matching character 'b' in Arduino Leonardo bootloader


This step is very easy. Prepare the command, then call it using system() with PROGRAM_PORT from previous step

char cmd[1024]=0;
sprintf(cmd, "avrdude -C def.con -pm32u4 -c avr109 -D -P COM%d -b57600 -Uflash:w:firmware01.hex:i", PROGRAM_PORT);

There is a way to get message from avrdude but not needed in this project.

And finally, build a nice dialog for your upload programmer, like what I did for ac2usb



You don’t have to do this, just include avrdude.exe, libusb0.dll and avrdude.conf with your firmware updater program. But if you don’t want the customer use the fw to flash to more than 1 leonardo device as he supposes to. Well, this could be a problem. With a file server, you can control how many times customer can flash (download a firmware). Just simple php file to return the desire download that look similar to this:

// file: download.php
//calling url for download:
$cfile = $_GET["file"];
$fw_root = $_SERVER["DOCUMENT_ROOT"] . "/fw/";
$fw_avrdude = $fw_root ."avrdude.exe";

//get avrdude
if ($cfile == "avrdude")
	header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
	header("Cache-Control: public"); // needed for internet explorer
	header("Content-Type: application/zip");
	header("Content-Transfer-Encoding: Binary");
	header("Content-Disposition: attachment; filename=avrdude.exe");

You can do the same for avrdude.conf and libusb0.dll and also your firmware.

Now come to the tricky part. You want your program download these files automatically like how those online installers. With VC++, you have the option to do that quite easy using function URLDownloadToFile():

#pragma comment (lib, "urlmon.lib")  // Link to the library for compiling
#include <Urlmon.h>

#define TEXT_URL L""
//#define MAX_PATH 260

int main()
	WCHAR base_url[] = TEXT_URL;
	WCHAR file_url[256] = {0};
	swprintf(file_url, L"%s?file=avrdude", base_url); //

	GetTempPathW(MAX_PATH, avrfile); // C:\Users\ABCXYZ\AppData\Local\Temp

	WCHAR avrfile[MAX_PATH];
	swprintf(avrfile, L"%savrdude.exe", avrfile); // C:\Users\ABCXYZ\AppData\Local\Temp\avrdude.exe

	HRESULT hRes = URLDownloadToFileW(NULL, file_url, avrfile, 0, NULL);


It certainly needs more thoughts into this to be able to build your own atmega32u4 code uploader program. It’s a pity that I cannot share my code for ac2usb fw uploader. But you already have most of the bricks available. You can build one for yourself.

The codes in this entry doesn’t have a licence, you can do whatever you want with it.


Add comment

Fill out the form below to add your own comments

User data

Add your comment

[color=red] TEXT [/color]
[quote] TEXT [/quote]
[code=arduino avrasm cpp css java javascript nginx perl python] TEXT [/code]
Clear format