Skip to content

Commit

Permalink
Update support for fuses and bootloader programming
Browse files Browse the repository at this point in the history
  • Loading branch information
valeros committed Oct 30, 2020
1 parent 7bd226c commit 504315f
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 92 deletions.
6 changes: 3 additions & 3 deletions boards/nano_every.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
"variant": "nona4809"
},
"fuses": {
"SYSCFG0": "0xC9",
"BOOTEND": "0x00",
"OSCCFG": "0x01"
"syscfg0": "0xc9",
"bootend": "0x00",
"osccfg": "0x01"
},
"frameworks": [
"arduino"
Expand Down
6 changes: 3 additions & 3 deletions boards/uno_wifi_rev2.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
"bootloader": {
"file": "atmega4809_uart_bl.hex",
"fuses_file": "fuses_4809.bin",
"BOOTEND": "0x02",
"SYSCFG0": "0xC9",
"OSCCFG": "0x01"
"bootend": "0x02",
"syscfg0": "0xc9",
"osccfg": "0x01"
},
"frameworks": [
"arduino"
Expand Down
90 changes: 33 additions & 57 deletions builder/bootloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import sys
import os

from SCons.Script import ARGUMENTS, Import, Return
from SCons.Script import Import, Return

Import("env")

Expand All @@ -40,14 +40,6 @@ def get_suitable_optiboot_binary(framework_dir, board_config):
return bootloader_path


AVRDUDE_PATH = platform.get_package_dir("tool-avrdude-megaavr") or ""

common_cmd = [
"avrdude", "-p", "$BOARD_MCU", "-e", "-C",
'"%s"' % os.path.join(AVRDUDE_PATH, "avrdude.conf"),
"-c", "$UPLOAD_PROTOCOL", "$UPLOAD_FLAGS"
]

framework_dir = ""
if env.get("PIOFRAMEWORK", []):
framework_dir = platform.get_package_dir(platform.frameworks[env.get(
Expand All @@ -62,9 +54,8 @@ def get_suitable_optiboot_binary(framework_dir, board_config):
if not os.path.isfile(bootloader_path):
bootloader_path = get_suitable_optiboot_binary(framework_dir, board)
else:
if not isfile(bootloader_path):
bootloader_path = join(
framework_dir, "bootloaders", bootloader_path)
if not os.path.isfile(bootloader_path):
bootloader_path = os.path.join(framework_dir, "bootloaders", bootloader_path)

if not board.get("bootloader", {}):
sys.stderr.write("Error: missing bootloader configuration!\n")
Expand All @@ -73,61 +64,46 @@ def get_suitable_optiboot_binary(framework_dir, board_config):
if not os.path.isfile(bootloader_path):
bootloader_path = os.path.join(framework_dir, "bootloaders", bootloader_path)

if not os.path.isfile(bootloader_path):
if not os.path.isfile(bootloader_path) and "BOOTFLAGS" not in env:
sys.stderr.write("Error: Couldn't find bootloader image\n")
env.Exit(1)

bootloader_flags = ['-Uflash:w:"%s":i' % bootloader_path]

#
# Fuses processing
#

fuses_action = None
if core == "MegaCoreX":
fuses_action = env.SConscript("fuses.py", exports="env")
env.Append(
BOOTUPLOADER="avrdude",
BOOTUPLOADERFLAGS=[
"-p",
"$BOARD_MCU",
"-C",
'"%s"'
% os.path.join(env.PioPlatform().get_package_dir(
"tool-avrdude-megaavr") or "", "avrdude.conf"),
],
BOOTFLAGS=['-Uflash:w:"%s":i' % bootloader_path],
UPLOADBOOTCMD="$BOOTUPLOADER $BOOTUPLOADERFLAGS $UPLOAD_FLAGS $BOOTFLAGS",
)

if not env.BoardConfig().get("upload", {}).get("require_upload_port", False):
# upload methods via USB
env.Append(BOOTUPLOADERFLAGS=["-P", "usb"])
else:
bootloader_fuses = board.get("bootloader", {})
if not bootloader_fuses:
sys.stderr.write("Error: missing bootloader configuration!\n")
env.Exit(1)
env.AutodetectUploadPort()
env.Append(FUSESUPLOADERFLAGS=["-P", '"$UPLOAD_PORT"'])

# Note: the index represents the fuse number
fuses = (
bootloader_fuses.get("WDTCFG", ""),
bootloader_fuses.get("BODCFG", ""),
bootloader_fuses.get("OSCCFG", ""),
"", # Reserved
bootloader_fuses.get("TCD0CFG", ""),
bootloader_fuses.get("SYSCFG0", ""),
bootloader_fuses.get("SYSCFG1", ""),
bootloader_fuses.get("APPEND", ""),
bootloader_fuses.get("BOOTEND", ""),
if env.subst("$UPLOAD_PROTOCOL") != "custom":
env.Append(BOOTUPLOADERFLAGS=["-c", "$UPLOAD_PROTOCOL"])
else:
print(
"Warning: The `custom` upload protocol is used! The upload and fuse flags may "
"conflict!\nMore information: "
"https://docs.platformio.org/en/latest/platforms/atmelavr.html"
"#overriding-default-bootloader-command\n"
)

lock_fuse = bootloader_fuses.get("LOCKBIT", "")

fuses_cmd = [
"avrdude", "-p", "$BOARD_MCU", "-C",
'"%s"' % os.path.join(AVRDUDE_PATH, "avrdude.conf"),
"-c", "$UPLOAD_PROTOCOL", "$UPLOAD_FLAGS"
]

if int(ARGUMENTS.get("PIOVERBOSE", 0)):
fuses_cmd.append("-v")

for idx, value in enumerate(fuses):
if value:
fuses_cmd.append("-Ufuse%d:w:%s:m" % (idx, value))

if lock_fuse:
fuses_cmd.append("-Ulock:w:%s:m" % lock_fuse)

fuses_action = env.VerboseAction(" ".join(fuses_cmd), "Setting fuses")
fuses_action = env.SConscript("fuses.py", exports="env")

bootloader_actions = [
fuses_action,
env.VerboseAction(" ".join(common_cmd + bootloader_flags), "Uploading bootloader")
env.VerboseAction("$UPLOADBOOTCMD", "Uploading bootloader"),
]

Return("bootloader_actions")
82 changes: 55 additions & 27 deletions builder/fuses.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import sys
import os

from SCons.Script import ARGUMENTS, Import, Return
from SCons.Script import ARGUMENTS, COMMAND_LINE_TARGETS, Import, Return

Import("env")

Expand All @@ -15,49 +15,77 @@ def print_fuses_info(fuses, lock_fuse):
print("lock = %s" % lock_fuse)



board = env.BoardConfig()
platform = env.PioPlatform()

board_fuses = board.get("fuses", {})
if not board_fuses:
fuses_section = "fuses"
if "bootloader" in COMMAND_LINE_TARGETS or "UPLOADBOOTCMD" in env:
fuses_section = "bootloader"

board_fuses = board.get(fuses_section, {})
if not board_fuses and "FUSESFLAGS" not in env:
sys.stderr.write("Error: No fuse values specified!\n")
env.Exit(1)

# Note: the index represents the fuse number
fuses = (
board_fuses.get("WDTCFG", ""),
board_fuses.get("BODCFG", ""),
board_fuses.get("OSCCFG", ""),
"", # Reserved
board_fuses.get("TCD0CFG", ""),
board_fuses.get("SYSCFG0", ""),
board_fuses.get("SYSCFG1", ""),
board_fuses.get("APPEND", ""),
board_fuses.get("BOOTEND", ""),
board_fuses.get("wdtcfg", ""),
board_fuses.get("bodcfg", ""),
board_fuses.get("osccfg", ""),
"", # reserved
board_fuses.get("tcd0cfg", ""),
board_fuses.get("syscfg0", ""),
board_fuses.get("syscfg1", ""),
board_fuses.get("append", ""),
board_fuses.get("bootend", ""),
)

lock_fuse = board_fuses.get("LOCKBIT", "")

fuses_cmd = [
"avrdude", "-p", "$BOARD_MCU", "-C",
'"%s"' % os.path.join(platform.get_package_dir(
"tool-avrdude-megaavr") or "", "avrdude.conf"),
"-c", "$UPLOAD_PROTOCOL", "$UPLOAD_FLAGS"
]

if int(ARGUMENTS.get("PIOVERBOSE", 0)):
fuses_cmd.append("-v")
env.Append(
FUSESUPLOADER="avrdude",
FUSESUPLOADERFLAGS=[
"-p",
"$BOARD_MCU",
"-C",
'"%s"'
% os.path.join(env.PioPlatform().get_package_dir(
"tool-avrdude-megaavr") or "", "avrdude.conf"),
],
SETFUSESCMD="$FUSESUPLOADER $FUSESUPLOADERFLAGS $UPLOAD_FLAGS $FUSESFLAGS",
)

for idx, value in enumerate(fuses):
if value:
fuses_cmd.append("-Ufuse%d:w:%s:m" % (idx, value))
env.Append(
FUSESFLAGS=[
"-Ufuse%d:w:%s:m" % (idx, value) for idx, value in enumerate(fuses) if value
]
)

if lock_fuse:
fuses_cmd.append("-Ulock:w:%s:m" % lock_fuse)
env.Append(FUSESFLAGS=["-Ulock:w:%s:m" % lock_fuse])

if int(ARGUMENTS.get("PIOVERBOSE", 0)):
env.Append(FUSESUPLOADERFLAGS=["-v"])

if not env.BoardConfig().get("upload", {}).get("require_upload_port", False):
# upload methods via USB
env.Append(FUSESUPLOADERFLAGS=["-P", "usb"])
else:
env.AutodetectUploadPort()
env.Append(FUSESUPLOADERFLAGS=["-P", '"$UPLOAD_PORT"'])

if env.subst("$UPLOAD_PROTOCOL") != "custom":
env.Append(FUSESUPLOADERFLAGS=["-c", "$UPLOAD_PROTOCOL"])
else:
print(
"Warning: The `custom` upload protocol is used! The upload and fuse flags may "
"conflict!\nMore information: "
"https://docs.platformio.org/en/latest/platforms/atmelavr.html"
"#overriding-default-fuses-command\n"
)

print_fuses_info(fuses, lock_fuse)

fuses_action = env.VerboseAction(" ".join(fuses_cmd), "Setting fuses")
fuses_action = env.VerboseAction("$SETFUSESCMD", "Setting fuses")

Return("fuses_action")
4 changes: 2 additions & 2 deletions builder/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621
if "upload" in COMMAND_LINE_TARGETS and "arduino" in env.subst("$PIOFRAMEWORK"):
if board == "uno_wifi_rev2":
# uno_wifi_rev2 requires bootloader to be uploaded in any case
upload_actions = env.SConscript(
"bootloader.py", exports="env") + upload_actions
upload_actions += env.SConscript("bootloader.py", exports="env")

elif board == "nano_every":
# Program fuses after programming flash
upload_actions.append(env.SConscript("fuses.py", exports="env"))
Expand Down

0 comments on commit 504315f

Please sign in to comment.