platformio / platform-atmelavr

Atmel AVR: development platform for PlatformIO
https://registry.platformio.org/platforms/platformio/atmelavr
Apache License 2.0
136 stars 104 forks source link

Unable to upload to Arduino Uno using USBasp #254

Open manuelbl opened 3 years ago

manuelbl commented 3 years ago

Uploading the firmware to an Arduino Uno using USBasp fails when verifying the upload firmware:

Uploading .pio/build/uno/firmware.hex

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file ".pio/build/uno/firmware.hex"
avrdude: writing flash (922 bytes):

Writing | ################################################## | 100% 0.72s

avrdude: 922 bytes of flash written
avrdude: verifying flash memory against .pio/build/uno/firmware.hex:
avrdude: load data flash data from input file .pio/build/uno/firmware.hex:
avrdude: input file .pio/build/uno/firmware.hex contains 922 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.51s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x01d2
         0x80 != 0x84
avrdude: verification error; content mismatch

avrdude: safemode: Fuses OK (E:FD, H:D6, L:FF)

avrdude done.  Thank you.

*** [upload] Error 1

platformio.ini is a simple as it gets:

[env:uno]
platform = atmelavr
board = uno
framework = arduino
upload_protocol = usbasp

The executed upload command is:

avrdude -v -p atmega328p -C /Users/xxx/.platformio/packages/tool-avrdude/avrdude.conf -c usbasp -D -U flash:w:.pio/build/uno/firmware.hex:i

The problem is the flag -D (it disables erasing the flash before writing). Without the flag, the firmware can be uploaded successfully with the above command.

A workaround is to specify the additional upload flag -e in platformio.ini (for erasing the flash). But it is a lucky coincident with the current avrdude implementation that -e overrides -D even though it specified first.

MCUdude commented 3 years ago

Using an external programmer with PlatformIO + Avrdude usually a bit tricky.

If you'd like to try MiniCore, you can easily switch between uploading using the bootloader and a programmer by using different environments.

Below is the default platformio.ini template, I provide that fits the needs of most users. You can read more about the PlatformIO + MiniCore implementation, and MiniCore in general, here: https://github.com/MCUdude/MiniCore/blob/master/PlatformIO.md

; PlatformIO Project Configuration File for MiniCore
; https://github.com/MCUdude/MiniCore/
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed, and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options
; https://github.com/MCUdude/MiniCore/blob/master/PlatformIO.md
; https://docs.platformio.org/page/projectconf.html

[platformio]
default_envs = Upload_UART ; Default build target

; Common settings for all environments
[env]
platform = atmelavr
framework = arduino

; TARGET SETTINGS
; Chip in use
board = ATmega328P
; Clock frequency in [Hz]
board_build.f_cpu = 16000000L

; BUILD OPTIONS
; Comment out to enable LTO (this line unflags it)
build_unflags = -flto
; Extra build flags
build_flags = 

; SERIAL MONITOR OPTIONS
; Serial monitor port defined in the Upload_UART environment
monitor_port = ${env:Upload_UART.upload_port}
; Serial monitor baud rate
monitor_speed = 9600

; Run the following command to upload with this environment
; pio run -e Upload_UART -t upload
[env:Upload_UART]
;  Serial bootloader protocol
upload_protocol = arduino
; Serial upload port
upload_port = /dev/cu.usbserial*
; Get upload baud rate defined in the fuses_bootloader environment
board_upload.speed = ${env:fuses_bootloader.board_bootloader.speed}

; Run the following command to upload with this environment
; pio run -e Upload_ISP -t upload
[env:Upload_ISP]
; Custom upload procedure
upload_protocol = custom
; Avrdude upload flags
upload_flags =
  -C$PROJECT_PACKAGES_DIR/tool-avrdude/avrdude.conf
  -p$BOARD_MCU
  -PUSB
  -cusbasp
; Avrdude upload command
upload_command = avrdude $UPLOAD_FLAGS -U flash:w:$SOURCE:i

; Run the following command to set fuses
; pio run -e fuses_bootloader -t fuses
; Run the following command to set fuses + burn bootloader
; pio run -e fuses_bootloader -t bootloader
[env:fuses_bootloader]
board_hardware.oscillator = external ; Oscillator type
board_hardware.uart = uart0          ; Set UART to use for serial upload
board_bootloader.speed = 115200      ; Set bootloader baud rate
board_hardware.bod = 2.7v            ; Set brown-out detection
board_hardware.eesave = yes          ; Preserve EEPROM when uploading using programmer
upload_protocol = usbasp             ; Use the USBasp as programmer
upload_flags =                       ; Select USB as upload port and divide the SPI clock by 8
  -PUSB
  -B8
manuelbl commented 3 years ago

@MCUdude I'm not looking for a workaround but a fix of the underlying problem: the flag -D needs to be removed.

MCUdude commented 3 years ago

It's not a workaround, it's the proper way of doing it. I've complained about the -D flag in the past. Surprisingly, there's no easy fix without breaking uploads for other boards. I'm sure @valeros can confirm.

marshfolx commented 2 years ago

@MCUdude 'upload_unflags' option may be a better solution. And I think in the board.json file there is a BUG on 'upload.extra_flags'. The extra_flags will be passed with a pair of quotes, and it seems avrdude can't parse it properly. The case I encountered is that "-B 12" can't set the SCK frequency while it does the job without the quotes.