Upload to Adafruit Feather M0 (SAMD21) does not work

Hi, I’m having trouble uploading to Feather M0, despite it works fine with Arduino IDE. The problem as I can see is that PIO forcing reset the device and wait for new comport to appear, whereas the board is expecting no reset since resetting results in not being in the bootloader mode (bootloader needs double click reset button).

UPDATE: Just found Arduino IDE does force reset as well, see log below. After force reset, the upload port actually reappears, and the difference between PlatformIO and Arduino IDE is that PIO does not think the port that reappeared is the one it’s looking for, so it stops using it.

Any workaround?

Log from the upload terminal:

Executing task in folder keyboard_mouse: platformio run --target upload

Processing adafruit_feather_m0 (platform: https://github.com/platformio/platform-atmelsam.git; board: adafruit_feather_m0; framework: arduino)
----------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/adafruit_feather_m0.html
PLATFORM: Atmel SAM 3.8.0 #916cc6f > Adafruit Feather M0
HARDWARE: SAMD21G18A 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink)
PACKAGES: toolchain-gccarmnoneeabi 1.70201.0 (7.2.1), framework-arduinosam 4.3.190711, tool-bossac 1.10900.0 (1.9.0)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 34 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <Keyboard> 1.0.2
|   |-- <HID> 1.0
Checking size .pio/build/adafruit_feather_m0/firmware.elf
Memory Usage -> http://bit.ly/pio-memory-usage
DATA:    [=         ]   9.2% (used 3020 bytes from 32768 bytes)
PROGRAM: [=         ]   5.1% (used 13268 bytes from 262144 bytes)
Configuring upload protocol...
AVAILABLE: atmel-ice, blackmagic, jlink, sam-ba
CURRENT: upload_protocol = sam-ba
Looking for upload port...
Auto-detected: /dev/cu.usbmodem1451101
Forcing reset using 1200bps open/close on port /dev/cu.usbmodem1451101
Waiting for the new upload port...
Uploading .pio/build/adafruit_feather_m0/firmware.bin
bossac: extra arguments found
Try 'bossac -h' or 'bossac --help' for more information
*** [upload] Error 1

Compare to terminal command input from Arduino IDE:

Sketch uses 15772 bytes (6%) of program storage space. Maximum is 262144 bytes.
Forcing reset using 1200bps open/close on port /dev/cu.usbmodem1451101
Found upload port: /dev/cu.usbmodem1451101
Library/Arduino15/packages/arduino/tools/bossac/1.7.0/bossac -i -d --port=cu.usbmodem1451101 -U true -i -e -w -v KeyboardMessage.ino.bin -R 
Set binary mode
readWord(addr=0)=0x20002dd8
readWord(addr=0xe000ed00)=0x410cc601
readWord(addr=0x41002018)=0x10010305
version()=v1.1 [Arduino:XYZ] May 12 2018 18:17:10
chipId=0x10010005
Connected at 921600 baud
readWord(addr=0)=0x20002dd8
readWord(addr=0xe000ed00)=0x410cc601
readWord(addr=0x41002018)=0x10010305
Atmel SMART device 0x10010005 found
write(addr=0x20004000,size=0x34)
writeWord(addr=0x20004030,value=0x10)
writeWord(addr=0x20004020,value=0x20008000)
Device       : ATSAMD21G18A
readWord(addr=0)=0x20002dd8
readWord(addr=0xe000ed00)=0x410cc601
readWord(addr=0x41002018)=0x10010305
Chip ID      : 10010005
version()=v1.1 [Arduino:XYZ] May 12 2018 18:17:10
Version      : v1.1 [Arduino:XYZ] May 12 2018 18:17:10
Address      : 8192
Pages        : 3968
Page Size    : 64 bytes
Total Size   : 248KB
Planes       : 1
Lock Regions : 16
Locked       : readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
readWord(addr=0x41004020)=0xffff
none
readWord(addr=0x41004018)=0
Security     : false
Boot Flash   : true
readWord(addr=0x40000834)=0x7000a
BOD          : true
readWord(addr=0x40000834)=0x7000a
BOR          : true
Arduino      : FAST_CHIP_ERASE
Arduino      : FAST_MULTI_PAGE_WRITE
Arduino      : CAN_CHECKSUM_MEMORY_BUFFER
Erase flash
chipErase(addr=0x2000)
done in 1.064 seconds

Write 16044 bytes to flash (251 pages)
write(addr=0x20005000,size=0x1000)
writeBuffer(scr_addr=0x20005000, dst_addr=0x2000, size=0x1000)

[=======                       ] 25% (64/251 pages)write(addr=0x20005000,size=0x1000)
writeBuffer(scr_addr=0x20005000, dst_addr=0x3000, size=0x1000)

[===============               ] 50% (128/251 pages)write(addr=0x20005000,size=0x1000)
writeBuffer(scr_addr=0x20005000, dst_addr=0x4000, size=0x1000)

[======================        ] 76% (192/251 pages)write(addr=0x20005000,size=0xec0)
writeBuffer(scr_addr=0x20005000, dst_addr=0x5000, size=0xec0)

[==============================] 100% (251/251 pages)
done in 0.099 seconds

Verify 16044 bytes of flash with checksum.
checksumBuffer(start_addr=0x2000, size=0x1000) = 7d9e
checksumBuffer(start_addr=0x3000, size=0x1000) = 1086
checksumBuffer(start_addr=0x4000, size=0x1000) = 2ca2
checksumBuffer(start_addr=0x5000, size=0xeac) = 6b36
Verify successful
done in 0.022 seconds
CPU reset.
readWord(addr=0)=0x20002dd8
readWord(addr=0xe000ed00)=0x410cc601
readWord(addr=0x41002018)=0x10010305
writeWord(addr=0xe000ed0c,value=0x5fa0004)

Try doing a verbose upload in both, and see what differences there are in the upload command used, and the versions of the tools (if stated).

PlatformIO:

Arduino IDE:
Change the setting, and then upload as normal.
XnFPkMEg9E

Nope, opening the serial port at 1200 baud will also cause it to enter bootloader mode, which is what bossac is using, see thread here.

1 Like

I’m hoping provision of further logs will indicate why the PlatformIO log fails with:

bossac: extra arguments found 
Try 'bossac -h' or 'bossac --help' for more information

Thank you @pfeerick, I did verbose upload on both Arduino IDE and PlatformIO, the difference I can see is:
Arduino IDE, using bossac 1.7.0:

bossac -i -d --port=cu.usbmodem1451101 -U true -i -e -w -v firmware.bin -R

vs PlatformIO, using bossac 1.9.1:

bossac --info --debug --port "cu.usbmodem1451101" --write --verify --reset --erase -U true firmware.bin

So the first difference is that the version of Bossac is different. I tried to run 1.9.1 separately and it shows the same error. However after I changed -U true to --usb-port=TRUE the process can process. Although the upload process didn’t finish successfully, when all 100% is done and verified, it shows:

Verify failed
Page errors: 128
Byte errors: 7855

Can you tell why?

Ok thanks @maxgerhardt , I can see both are doing the same so yeah you’re right, this is not the cause.

Also a slightly independent question regarding bossac, in PlatformIO IDE by default the integrated terminal cannot find bossac binary, I tried both on MacOS and Windows10 in a VM. I had to manually install bossac and link it into /usr/local/bin

Is it just on my computer?

PlatformIO doesn’t throw any binaries in your normal user path. The binary is PlatformiO’s package directory, see /home/<user>/.platformio/packages/tool-bossac

1 Like

OK, yeah I found out that, just got confused when asked to “Try ‘bossac -h’ or ‘bossac --help’ for more information” then I did and the integrated terminal couldn’t find the binary. I’m not sure where am I supposed to try “bossac -h” from PlatformIO’s point of view.

Could you try in your platformio.ini

upload_flags = --usb-port=TRUE

please? This should add the upload flag (while keeping the old one which is hopefully ignored)

Just gave it a try, the new command is in, but the old one is not overridden, so the result is the same. how to override the old parameter setting?

Verbose:

bossac --usb-port=TRUE --info --debug --port "cu.usbmodem1451101" --write --verify --reset --erase -U true .pio/build/adafruit_feather_m0/firmware.bin

BTW, my platformio.ini setting, I had to use “board_build.core = samd” since I’m using the Arduino Keyboard library, which throws a lot of error if I don’t force it to use the samd core. Not sure if this makes things go bad:

[env:adafruit_feather_m0]
platform = atmelsam
board = adafruit_feather_m0
framework = arduino
board_build.core = samd

monitor_speed = 115200

upload_flags = --usb-port=TRUE

Alright we might have a hit with this issue: Flashing fails with this compiled version while 1.7 is doing fine. · Issue #96 · shumatech/BOSSA · GitHub

So according to that we need --usb-port=true and maybe the offset -o 0x2000.

Could you please go into your PlatformIO’s home directory and go to the file ~/.platformio/platforms/atmelsam/builder/main.py. At line 214 there should be

    else:
        env.Append(UPLOADERFLAGS=[
            "--erase",
            "-U", "true"
            if env.BoardConfig().get("upload.native_usb", False) else "false"
        ])

Replace this piece of code with

    else:
        env.Append(UPLOADERFLAGS=[
            "--erase",
            "--usb-port", "TRUE"
            if env.BoardConfig().get("upload.native_usb", False) else "FALSE"
        ])

And remove the previously added upload_flags line from the platformio.ini.

Does it upload now?

It’s getting quite complicated, but the short answer is no, it didn’t upload.

The first thing I need to mention is that the “board_build.core = samd” line in “platformio.ini” does do something to the upload process. Without this line we’re to line 210 in main.py, “if board.get("build.core") == "adafruit":”. And with the overriden core setting we’re in the part of the code you asked me to change.

What worked

What worked for me eventually was to keep board_build.core = samd line in platformio.ini, while change main.py from:

elif upload_protocol == "sam-ba":
    env.Replace(
        UPLOADER="bossac",

to

elif upload_protocol == "sam-ba":
    env.Replace(
        UPLOADER="/Users/tao/Library/Arduino15/packages/arduino/tools/bossac/1.7.0/bossac",

By doing this I’m basically using the same bossac as Arduino IDE is using.

What didn’t work

I also tried to make it work for the scenario where there’s no overriding line in platformio.ini, but I didn’t have much luck doing that.

I tried to change main.py at line 210 from:

    if board.get("build.core") == "adafruit":
        env.Append(
            UPLOADERFLAGS=["-U", "--offset",
                           board.get("upload.offset_address")])

to

    if board.get("build.core") == "adafruit":
        env.Append(
            UPLOADERFLAGS=["--usb-port=TRUE",
                            "--offset=" + board.get("upload.offset_address")])

to fix the offset command issue, although the change makes the upload process go a little further, I still didn’t see the end of the tunnel. I got this error message:

Forcing reset using 1200bps open/close on port /dev/cu.usbmodem1451101
Waiting for the new upload port...
bossac --info --debug --port=cu.usbmodem1451101 --write --verify --reset --usb-port=TRUE --offset=0x2000 .pio/build/adafruit_feather_m0/firmware.bin

Send auto-baud
Set binary mode
SAM-BA operation failed
version()=v1.1 [Arduino:XYZ] May 12 2018 18:17:10
Connected at 115200 baud
readWord(addr=0)=0x20002dd8
readWord(addr=0xe000ed00)=0x410cc601
readWord(addr=0x41002018)=0x10010305
write(addr=0x20004000,size=0x34)
*** [upload] Error 1

I can see some difference between a good upload process using 1.7.0 vs failed process using 1.9.1. For example, the detected baud rate is different, 1.7.0 detects 921600 while 1.9.1 detects 115200.

/Users/tao/Library/Arduino15/packages/arduino/tools/bossac/1.7.0/bossac --info --debug --port=cu.usbmodem1451101 --write --verify --reset --erase -U true .pio/build/adafruit_feather_m0/firmware.bin
Set binary mode
readWord(addr=0)=0x20002dd8
readWord(addr=0xe000ed00)=0x410cc601
readWord(addr=0x41002018)=0x10010305
version()=v1.1 [Arduino:XYZ] May 12 2018 18:17:10
chipId=0x10010005
Connected at 921600 baud
readWord(addr=0)=0x20002dd8
readWord(addr=0xe000ed00)=0x410cc601
readWord(addr=0x41002018)=0x10010305
Atmel SMART device 0x10010005 found
write(addr=0x20004000,size=0x34)
writeWord(addr=0x20004030,value=0x10)
writeWord(addr=0x20004020,value=0x20008000)
Device       : ATSAMD21G18A
readWord(addr=0)=0x20002dd8
readWord(addr=0xe000ed00)=0x410cc601
readWord(addr=0x41002018)=0x10010305
Chip ID      : 10010005
version()=v1.1 [Arduino:XYZ] May 12 2018 18:17:10
Version      : v1.1 [Arduino:XYZ] May 12 2018 18:17:10
Address      : 8192
Pages        : 3968
Page Size    : 64 bytes
Total Size   : 248KB
Planes       : 1
Lock Regions : 16
Locked       : readWord(addr=0x41004020)=0xffff

Not sure where else has gone wrong.

Hm, okay. I’ll try to get a hold of a Feather M0 and reproduce this. Not sure what more flags to change right now.

Yes that’s the best, thanks @maxgerhardt !

Ok, I did one more experiment, and use bossac 1.7.0 regardless of board_build.core setting. and It worked by changing main.py to:

elif upload_protocol == "sam-ba":
    env.Replace(
        UPLOADER="/Users/tao/Library/Arduino15/packages/arduino/tools/bossac/1.7.0/bossac",
        UPLOADERFLAGS=[
            "--port=$UPLOAD_PORT",
            "--write",
            "--verify",
            "--reset"
        ],
        UPLOADCMD="$UPLOADER $UPLOADERFLAGS $SOURCES"
    )
    if board.get("build.core") == "adafruit":
        env.Append(
            UPLOADERFLAGS=[
                "--erase",
                "-U", "true"
                ])
    else:
        env.Append(UPLOADERFLAGS=[
            "--erase",
            "-U", "true"
            if env.BoardConfig().get("upload.native_usb", False) else "false"
        ])

Basically use the Arduino IDE bossac and do exactly as it does. Before we find a good solution for bossac 1.9.0/1, this will be the working setting for me.

Hey, I got myself an Adafruit Feather M0 and can successfully upload code using the following python modification:

elif upload_protocol == "sam-ba":
    env.Replace(
        UPLOADER="bossac",
        UPLOADERFLAGS=[
            "--port", '"$UPLOAD_PORT"',
            "--write",
            "--verify",
            "--reset"
        ],
        UPLOADCMD="$UPLOADER $UPLOADERFLAGS $SOURCES"
    )
    if board.get("build.core") == "adafruit":
        env.Append(
            UPLOADERFLAGS=["-U", "--offset",
                           board.get("upload.offset_address")])
    else:
        env.Append(UPLOADERFLAGS=[
            "--erase",
            "-U"
            if env.BoardConfig().get("upload.native_usb", False) else "",
            "--offset", board.get("upload.offset_address", 0x2000)
        ])

Will trigger an invocation like

bossac --info --debug --port "COM5" --write --verify --reset --erase -U --offset 0x2000 .pio\build\adafruit_feather_m0\firmware.bin
Set binary mode
version()=v2.0 [Arduino:XYZ] Mar  5 2016 17:46:52
Connected at 921600 baud
readWord(addr=0)=0x20007ffc
readWord(addr=0xe000ed00)=0x410cc601
readWord(addr=0x41002018)=0x10010305
write(addr=0x20004000,size=0x34)
writeWord(addr=0x20004030,value=0x10)
writeWord(addr=0x20004020,value=0x20008000)
version()=v2.0 [Arduino:XYZ] Mar  5 2016 17:46:52
readWord(addr=0x41004018)=0
readByte(addr=0x804001)=0xc7
readByte(addr=0x804001)=0xc7
readByte(addr=0x804006)=0xff
readByte(addr=0x804007)=0xff
Device       : ATSAMD21x18
Version      : v2.0 [Arduino:XYZ] Mar  5 2016 17:46:52
Address      : 0x0
Pages        : 4096
Page Size    : 64 bytes
Total Size   : 256KB
Planes       : 1
Lock Regions : 16
Locked       : none
Security     : false
BOD          : true
BOR          : true
Erase flash
chipErase(addr=0x2000)

Done in 0.831 seconds
Write 11676 bytes to flash (183 pages)
[                              ] 0% (0/183 pages)write(addr=0x20004034,size=0x1000)
writeBuffer(scr_addr=0x20004034, dst_addr=0x2000, size=0x1000)
[==========                    ] 34% (64/183 pages)write(addr=0x20004034,size=0x1000)
writeBuffer(scr_addr=0x20004034, dst_addr=0x3000, size=0x1000)
[====================          ] 69% (128/183 pages)write(addr=0x20004034,size=0xdc0)
writeBuffer(scr_addr=0x20004034, dst_addr=0x4000, size=0xdc0)
[==============================] 100% (183/183 pages)
...
[==============================] 100% (183/183 pages)
Verify successful
Done in 0.739 seconds
writeWord(addr=0xe000ed0c,value=0x5fa0004)

Could you try that?

Hi @maxgerhardt Yes it works flawlessly, regardless of what settings in “board_build.core = samd”, fantastic!

Should we make these changes in official repository?

@ivankravets As far as I see this is a generic solution to a common issue.

1 Like

Does the latest upstream version work for you Atmel SAM — PlatformIO latest documentation ?