October 31, 2020

Olimexino-STM32 - loading software

My previous experience with STM32F103 boards has been with the "blue pill" boards from China. I have always used an ST-Link device to attach to the four SWD pins at the end of these boards and have brazenly overwritten any kind of boot loader in flash memory.

The Olimexino (and Maple r5) would seem to be best worked with using the USB cable and the "Maple boot loader" in flash memory. This page is my experimentation figuring out how to work with that.

Loading Software

The typical user was expected to use the Arduino-like Maple IDE. This is something I would never do without a gun to my head.

The board comes with the Maple IDE bootloader. This lives in flash and works to download user code over USB. The following excellent note is part of the amazing Maple documents. The STM32duino text discusses changes subsequent to Maple abandoning this whole business, and makes interesting reading.

Allegedly the Maple bootloader works with the DFU-util software, but I have had no luck so far. The problem is the race to get DFU-util running while the board is still in DFU bootloader mode. Then I ran across the following instructions in some of the old Maple docs.

Perpetual Bootloader mode

In this mode, Maple stays a DFU device and does not jump to user code until the next reset. This is useful for guaranteeing that your Maple will be available for reprogramming.

To put your Maple (or other Maple board) into perpetual bootloader mode:

Plug your board into the USB port. Hit the reset button (it’s the button labeled RESET). Notice that your board blinks quickly 6 times, then blinks slowly a few more times.

Hit reset again, and this time push and hold the other button during the 6 fast blinks (the normal button is labeled BUT). You can release it once the slow blinks start.

Once I do this, I can run "dfu-util -l" as root and see:

Found DFU: [1eaf:0003] ver=0200, devnum=119, cfg=1, intf=0, path="1-1.3", alt=1, name="DFU Program FLASH 0x08005000", serial="LLM 003"
Found DFU: [1eaf:0003] ver=0200, devnum=119, cfg=1, intf=0, path="1-1.3", alt=0, name="DFU Pro", serial="LLM 003"
This is progress. So how does the Arduino GUI work with the brief bootloader business? It must be able to trigger a reset and then jump on things during the interval when the bootloader runs. This would be handy code to have outside of the arduino GUI environment.

Python reset script

I grub around in Arduino_STM32 sources, and in particular in Arduino_STM32/STM32F1.

The first thing of interest (searching for "1EAF" is system/support/scripts/reset.py. it toggles DTR and RTS and then sends the 4 characters "1EAF". This expects to be talking to the Maple USB Serial module, which would be part of any application built using maple. The USB Serial module has special code that watches for this sequence and resets the device when it sees it. This causes the Maple loader to run for the a brief period we have learned about. The python script does not download any code though, something else must do that.

There is another file: system/support/stm32loader.py. This fools with RTS and DTR, but never sends the 1EAF sequence, nor does it invoke the reset.py script. This had me confused for a while, but what this is for is connecting to the serial port and talking to the serial bootloader built into the chip. This would be a way to install a USB loader into flash.

The Makefile shows these interesting lines:

DFU      ?= dfu-util

# Target upload commands
BOARD_USB_VENDOR_ID  := 1EAF
BOARD_USB_PRODUCT_ID := 0003

ifeq ($(BOOTLOADER),maple)
UPLOAD_flash := $(SUPPORT_PATH)/scripts/reset.py && \
                sleep 1                  && \
                $(DFU) -a1 -d $(BOARD_USB_VENDOR_ID):$(BOARD_USB_PRODUCT_ID) -D $(BUILD_PATH)/$(BOARD).bin -R
endif
So, what about these dfu-util options?
-a1 specifies an "alt setting" of the DFU device, whatever that means
-d specifes the target device by USB vendor and product number
-D says to download the following bin file
-R says to do a USB reset after the download
I am using dfu-util 0.9, which is the latest release (and is from 2016, so dfu-util is not under active development).

Trouble

I try to upload and keep getting the error:
dfu-util: Could not read name, sscanf returned 0
dfu-util: Failed to parse memory layout
Having learned a bit more about dfu-util since getting this error, I will note that I had the -s switch on my command and that puts dfu-util into "dfuse" mode rather than "dfu" mode. Not that I understand all of this -- and I get errors even when I ditch the -s option and try an upload.

Whatever the case, I was curious about this error. The dfu-util program is kind of a shabby thrown together thing that works well when it works, but if it doesn't, the errors you get are worthless.

I get the dfu-util source, build it, and track this down to the file dfuse_mem.c. It is trying to parse the following string with sscanf as follows:

DFU Program FLASH 0x08005000
sscanf(intf_desc, "@%[^/]%n", name, &scanned);
The comments refer to ST document UM0424 section 4.3.2 This is an 85 page PDF -- the relevant section is 10.3.2 not 4.3.2 and a typical descriptor string discussed in this document looks like:
@Internal Flash /0x08000000/12*001 Ka,116*001 Kg
To start with, I hate sscanf and avoid it like the plague, but let's see if we can figure out how it would have handled the string from the ST document.

We start with an @ symbol, which is promising. The next thing is a scanf "character class", which here seems to be matching any character than is NOT a slash -- so it would extract "Internal Flash " into the variable name. Then the mysterious %n gadget actually tells scanf to report the number of characters that have been scanned thus far.

Plug it in

I use a mini-USB cable, and see the following when I plug it into my linux system
Nov  1 08:58:42 trona kernel: usb 1-1.3: new full-speed USB device number 97 using ehci-pci
Nov  1 08:58:42 trona kernel: usb 1-1.3: New USB device found, idVendor=1eaf, idProduct=0003, bcdDevice= 2.00
Nov  1 08:58:42 trona kernel: usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Nov  1 08:58:42 trona kernel: usb 1-1.3: Product: Maple 003
Nov  1 08:58:42 trona kernel: usb 1-1.3: Manufacturer: LeafLabs
Nov  1 08:58:42 trona kernel: usb 1-1.3: SerialNumber: LLM 003

Nov  1 08:58:44 trona kernel: usb 1-1.3: new full-speed USB device number 98 using ehci-pci
Nov  1 08:58:44 trona kernel: usb 1-1.3: New USB device found, idVendor=1eaf, idProduct=0004, bcdDevice= 2.00
Nov  1 08:58:44 trona kernel: usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
Nov  1 08:58:44 trona kernel: usb 1-1.3: Product: Maple R3
Nov  1 08:58:44 trona kernel: usb 1-1.3: Manufacturer: LeafLabs
Nov  1 08:58:44 trona kernel: cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device
Indeed it seems to connect twice changing the product number from 3 to 4. My interpretation is that the first connect is the boot loader, which runs briefly, then user code is run, which performs a disconnect and reidentifies itself as a USB serial device.

What I see when I connect the device or press reset is a rapidly blinking green LED for not quite a second, then a slow blinking green LED, then the green LED goes out and a yellow LED begins to blink.

I will note that I also have Maple r5 boards and I see exactly the same LED pattern and USB chatter when I connect them.


Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org