{"id":3817,"date":"2023-06-05T14:05:53","date_gmt":"2023-06-05T13:05:53","guid":{"rendered":"https:\/\/pmortensen.eu\/world2\/?p=3817"},"modified":"2026-06-15T17:25:20","modified_gmt":"2026-06-15T16:25:20","slug":"dfu-util-gotcha-always-use-a-0","status":"publish","type":"post","link":"https:\/\/pmortensen.eu\/world2\/2023\/06\/05\/dfu-util-gotcha-always-use-a-0\/","title":{"rendered":"Flash utility &#8216;dfu-util&#8217; gotcha: Always use option &#8216;-a 0&#8217;"},"content":{"rendered":"<p><a href=\"https:\/\/man.archlinux.org\/man\/dfu-util.1.en\">dfu-util<\/a> can be used to both read off and to flash (update) firmware on embedded devices, say for the firmware on a <a href=\"https:\/\/docs.qmk.fm\/#\/faq_general?id=what-is-qmk\">QMK<\/a>-based keyboard like the <a href=\"https:\/\/www.keychron.com\/products\/keychron-v5-qmk-custom-mechanical-keyboard-iso-layout-collection\">Keychron V5<\/a> (about 50&nbsp;KB). But it is very poorly documented. In most cases, the option &#8220;-a 0&#8221; must be included.<\/p>\n<h2>The problem<\/h2>\n<p>An unintrusive first try is to read off the firmware:<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\ndfu-util -U someKeychronV5firmwareVersion.bin\r\n<\/pre>\n<p>But this results in:<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\ndfu-util: More than one DFU capable USB device\r\nfound! Try `--list' and specify the serial\r\nnumber or disconnect all but one device\r\n<\/pre>\n<p>But this is a <strong><em>totally misleading error message<\/em><\/strong>&#8230; There is only one DFU device connected (and in DFU mode). This is confirmed by using the <strong><em>-l<\/em><\/strong> parameter to discover the DFU devices:<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\ndfu-util -l\r\n<\/pre>\n<p>Output:<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\ndfu-util 0.9\r\n\r\nFound DFU: [0483:df11] ver=2200, devnum=7, cfg=1, intf=0, path=&quot;3-1&quot;, alt=3, name=&quot;@Device Feature\/0xFFFF0000\/01*004 e&quot;, serial=&quot;205C32845242&quot;\r\nFound DFU: [0483:df11] ver=2200, devnum=7, cfg=1, intf=0, path=&quot;3-1&quot;, alt=2, name=&quot;@OTP Memory \/0x1FFF7000\/01*0001Ke&quot;, serial=&quot;205C32845242&quot;\r\nFound DFU: [0483:df11] ver=2200, devnum=7, cfg=1, intf=0, path=&quot;3-1&quot;, alt=1, name=&quot;@Option Bytes  \/0x1FFF7800\/01*040 e&quot;, serial=&quot;205C32845242&quot;\r\nFound DFU: [0483:df11] ver=2200, devnum=7, cfg=1, intf=0, path=&quot;3-1&quot;, alt=0, name=&quot;@Internal Flash  \/0x08000000\/0128*0002Kg&quot;, serial=&quot;205C32845242&quot;\r\n<\/pre>\n<p>The serial number, 205C32845242, is exactly the same for all four lines. The four are (directly from the output):<\/p>\n<table id=\"someTable\">\n<tr>\n<th>Area<\/th>\n<th class=\"rightAlign\">Start address<\/th>\n<th>Size<\/th>\n<th>Alt<\/th>\n<\/tr>\n<p>    <!-- Template\n    \n\n<tr> \n\n<td>XX<\/td>\n\n \n\n<td>XX<\/td>\n\n \n\n<td>XX<\/td>\n\n \n\n<td>XX<\/td>\n\n <\/tr>\n\n\n    --><\/p>\n<tr>\n<td>Device Feature<\/td>\n<td>0xFFFF0000<\/td>\n<td>01*004 e<\/td>\n<td>alt=3<\/td>\n<\/tr>\n<tr>\n<td>OTP Memory<\/td>\n<td>0x1FFF7000<\/td>\n<td>01*0001Ke<\/td>\n<td>alt=2<\/td>\n<\/tr>\n<tr>\n<td>Option Bytes<\/td>\n<td>0x1FFF7800<\/td>\n<td>01*040 e<\/td>\n<td>alt=1<\/td>\n<\/tr>\n<tr>\n<td>Internal Flash<\/td>\n<td>0x08000000<\/td>\n<td>0128*0002Kg<\/td>\n<td>alt=0<\/td>\n<\/tr>\n<p>    <!-- Template\n    \n\n<tr> \n\n<td>1<\/td>\n\n \n\n<td class=\"rightAlign\">0.6<\/td>\n\n \n\n<td>FAT32<\/td>\n\n \n\n<td>\/boot\/efi<\/td>\n\n \n\n<td>boot<\/td>\n\n \n\n<td><\/td>\n\n \n\n<td>\/dev\/nvme0n1p1<\/td>\n\n <\/tr>\n\n\n    --><\/p>\n<\/table>\n<p><!-- Template\nDevice Feature    0xFFFF0000\/01*004 e\nOTP Memory        0x1FFF7000\/01*0001Ke\nOption Bytes      0x1FFF7800\/01*040 e\nInternal Flash    0x08000000\/0128*0002Kg\n--><\/p>\n<p>The size is in a cryptic format. In this case, it is known the microcontroller is <a href=\"https:\/\/www.keychron.com\/products\/keychron-v5-qmk-custom-mechanical-keyboard?variant=40293230674009\">STM32L432<\/a> and the flash size is 128&nbsp;KB (output as &#8220;0128*0002Kg&#8221;).<\/p>\n<p>A distinguishing field is the &#8220;alt&#8221; field.<\/p>\n<p>The documentation is in the usual cryptic style: &#8220;Specify the altsetting of the DFU interface by name or by number.&#8221;<\/p>\n<h2>The solution<\/h2>\n<p>It is not documented (or at least very indirectly and cryptically), but the &#8220;-a&#8221; option must be used. In this case, &#8220;-a 0&#8221; as the flash part has &#8220;alt=0&#8221; (the &#8220;alt&#8221; in the output correspond). <\/p>\n<p>For reading off the firmware:<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\ndfu-util -a 0 -s 0x08000000:0x20000 -U someKeychronV5firmwareVersion.bin\r\n<\/pre>\n<p>For flashing:<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\ndfu-util -a 0 --dfuse-address 0x08000000 -D keychron_v5_iso_encoder_keychron_standardMacros.bin\r\n<\/pre>\n<p>Output, respectively (note that &#8220;upload&#8221; is using the convention from embedded devices where it is seen from the device&#8217;s perspective &#8211; upload from the device to host (computer) for reading off the flash memory):<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\ndfu-util 0.9\r\n\r\nOpening DFU capable USB device...\r\nID 0483:df11\r\nRun-time device DFU version 011a\r\nClaiming USB DFU Interface...\r\nSetting Alternate Setting #0 ...\r\nDetermining device status: state = dfuERROR, status = 10\r\ndfuERROR, clearing status\r\nDetermining device status: state = dfuIDLE, status = 0\r\ndfuIDLE, continuing\r\nDFU mode device DFU version 011a\r\nDevice returned transfer size 2048\r\nLimiting default upload to 16384 bytes\r\nUpload\t[=========================] 100%        16384 bytes\r\nUpload done.\r\n<\/pre>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\ndfu-util 0.11\r\n\r\nMatch vendor ID from file: 0483\r\nMatch product ID from file: df11\r\nOpening DFU capable USB device...\r\nDevice ID 0483:df11\r\nDevice DFU version 011a\r\nClaiming USB DFU Interface...\r\nSetting Alternate Interface #0 ...\r\nDetermining device status...\r\nDFU state(10) = dfuERROR, status(10) = Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations\r\nClearing status\r\nDetermining device status...\r\nDFU state(2) = dfuIDLE, status(0) = No error condition is present\r\nDFU mode device DFU version 011a\r\nDevice returned transfer size 2048\r\nDfuSe interface name: &quot;Internal Flash  &quot;\r\nDownloading element to address = 0x08000000, size = 48076\r\nErase   \t[=========================] 100%        48076 bytes\r\nErase    done.\r\nDownload\t[=========================] 100%        48076 bytes\r\nDownload done.\r\nFile downloaded successfully\r\n<\/pre>\n<h2>A bonus: Relieve strain on the USB cables&#8230;<\/h2>\n<p>By default, dfu-util will leave the device in bootloader mode after flashing. To avoid having to power cycle the device, use modifier &#8220;:leave&#8221; in the argument for &#8211;dfuse-address:<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\ndfu-util -a 0 --dfuse-address 0x08000000:leave -D keychron_v5_iso_encoder_keychron_standardMacros.bin\r\n<\/pre>\n<h2 id=\"dfu-util_install\">Installing dfu-util<\/h2>\n<p>dfu-util has probably been installed as part of installing QMK (it is part of <a href=\"https:\/\/github.com\/samhocevar-forks\/qmk-firmware\/blob\/master\/docs\/getting_started_build_tools.md\">the dependencies for it<\/a>), but on a pristine system, it can installed by:<\/p>\n<p><!-- \n    It is a fork. Where is it in QMK proper?\n    <https:\/\/github.com\/samhocevar-forks>    \n--><\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\nsudo apt-get install dfu-util\r\n<\/pre>\n<p>It can also be <a href=\"https:\/\/hackrf.readthedocs.io\/en\/latest\/updating_firmware.html\">installed from source<\/a> (near <em>&#8220;without a dfu-util package&#8221;<\/em>).<\/p>\n<p><!-- T H E   E N D . . . --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>dfu-util can be used to both read off and to flash (update) firmware on embedded devices, say for the firmware on a QMK-based keyboard like the Keychron V5 (about 50&nbsp;KB). But it is very poorly documented. In most cases, the &hellip;<\/p>\n<p class=\"read-more\"> <a class=\"more-link\" href=\"https:\/\/pmortensen.eu\/world2\/2023\/06\/05\/dfu-util-gotcha-always-use-a-0\/\"> <span class=\"screen-reader-text\">Flash utility &#8216;dfu-util&#8217; gotcha: Always use option &#8216;-a 0&#8217;<\/span> Read More &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4,23,28,26,35,46],"tags":[],"_links":{"self":[{"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/posts\/3817"}],"collection":[{"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/comments?post=3817"}],"version-history":[{"count":37,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/posts\/3817\/revisions"}],"predecessor-version":[{"id":4977,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/posts\/3817\/revisions\/4977"}],"wp:attachment":[{"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/media?parent=3817"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/categories?post=3817"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/tags?post=3817"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}