diff --git a/boards/AVR16DD20.json b/boards/AVR16DD20.json new file mode 100644 index 0000000..7b5af32 --- /dev/null +++ b/boards/AVR16DD20.json @@ -0,0 +1,24 @@ +{ + "build": { + "core": "dxcore", + "extra_flags": "-DARDUINO_AVR_AVR16DD20 -DARDUINO_avrdd", + "f_cpu": "24000000L", + "mcu": "avr16dd20", + "variant": "20pin-ddseries" + }, + "hardware": { + "oscillator": "internal" + }, + "frameworks": [ + "arduino" + ], + "name": "AVR16DD20", + "upload": { + "maximum_ram_size": 2048, + "maximum_size": 16384, + "protocol": "jtag2updi", + "speed": 115200 + }, + "url": "https://www.microchip.com/wwwproducts/en/AVR16DD20", + "vendor": "Microchip" +} diff --git a/boards/AVR16DD32.json b/boards/AVR16DD32.json new file mode 100644 index 0000000..a606def --- /dev/null +++ b/boards/AVR16DD32.json @@ -0,0 +1,24 @@ +{ + "build": { + "core": "dxcore", + "extra_flags": "-DARDUINO_AVR_AVR16DD32 -DARDUINO_avrdd", + "f_cpu": "24000000L", + "mcu": "avr16dd32", + "variant": "32pin-ddseries" + }, + "hardware": { + "oscillator": "internal" + }, + "frameworks": [ + "arduino" + ], + "name": "AVR16DD32", + "upload": { + "maximum_ram_size": 2048, + "maximum_size": 16384, + "protocol": "jtag2updi", + "speed": 115200 + }, + "url": "https://www.microchip.com/wwwproducts/en/AVR16DD32", + "vendor": "Microchip" +} diff --git a/builder/fuses.py b/builder/fuses.py index edda251..b09b126 100644 --- a/builder/fuses.py +++ b/builder/fuses.py @@ -10,18 +10,58 @@ def get_wdtcfg_fuse(): return 0x00 -def get_bodcfg_fuse(bod): +def is_dxcore_dd_target(): + return core == "dxcore" and "dd" in board.get("build.mcu").lower() + + +def get_dxcore_bodcfg_fuse(bod, bodmode): + bod = bod.lower() + bodmode = bodmode.lower() + + bodlev_bits = { + "1.9v": 0b000, + "1v9": 0b000, + "2.45v": 0b001, + "2v45": 0b001, + "2.7v": 0b010, + "2.70v": 0b010, + "2v7": 0b010, + "2v70": 0b010, + "2.85v": 0b011, + "2v85": 0b011, + } + + bodmode_bits = { + "disabled": None, + "enabled": 0b00101, + "ensampfast": 0b00110, + "ensampslow": 0b10110, + "samplefast": 0b01010, + "sampledfast": 0b01010, + "sampleslow": 0b11010, + "sampledslow": 0b11010, + "sampdisfast": 0b01000, + "sampdisslow": 0b11000, + "endisholdwake": 0b01100, + } + + if bodmode not in bodmode_bits: + sys.stderr.write("Error: Unsupported DxCore BOD mode '%s' for %s\n" % (bodmode, target)) + env.Exit(1) + + if bodmode_bits[bodmode] is None: + return 0x00 + + if bod not in bodlev_bits: + sys.stderr.write("Error: Unsupported DxCore BOD level '%s' for %s\n" % (bod, target)) + env.Exit(1) + + return (bodlev_bits[bod] << 5) | bodmode_bits[bodmode] + + +def get_bodcfg_fuse(bod, bodmode="disabled"): if core == "dxcore": - if bod == "2.85v": - return 0x74 - elif bod == "2.7v": - return 0x54 - elif bod == "2.45v": - return 0x34 - elif bod == "1.9v": - return 0x14 - else: # bod disabled - return 0x00 + return get_dxcore_bodcfg_fuse(bod, bodmode) elif core in ("MegaCoreX", "megatinycore"): if bod == "4.3v": return 0xF4 @@ -45,11 +85,23 @@ def get_osccfg_fuse(f_cpu, oscillator): def get_tcd0cfg_fuse(): + if core == "dxcore": + # DxCore's own bootloader/fuse flows do not write TCD0CFG. + return None return 0x00 def get_syscfg0_fuse(eesave, pin, uart): eesave_bit = 1 if eesave == "yes" else 0 + if is_dxcore_dd_target(): + if pin == "gpio" and uart == "no_bootloader": + resetpin_bits = 0b01 + else: + # PlatformIO currently exposes only reset/gpio, so map these to the + # safe AVR-DD defaults: RESET+UPDI when reset is selected or a + # bootloader is in use. + resetpin_bits = 0b11 + return 0xC0 | (resetpin_bits << 3) | eesave_bit if core in ("MegaCoreX", "dxcore"): if pin == "gpio": if uart == "no_bootloader": @@ -75,6 +127,20 @@ def get_syscfg0_fuse(eesave, pin, uart): # Handle AVR-DB's differently since these has MVIO pins def get_syscfg1_fuse(mvio): + if is_dxcore_dd_target(): + startuptime = str(board.get("hardware.startuptime", "8")).lower().replace("ms", "") + sut_bits = { + "0": 0b000, + "1": 0b001, + "2": 0b010, + "4": 0b011, + "8": 0b100, + "16": 0b101, + "32": 0b110, + "64": 0b111, + }.get(startuptime, 0b100) + mvio_bits = 0b01 if mvio == "yes" else 0b10 + return (mvio_bits << 3) | sut_bits if core == "dxcore" and ("db" in board.get("build.mcu").lower()): if(mvio == "yes"): return 0x0E @@ -110,7 +176,8 @@ def get_lockbit_fuse(): if core in ("arduino", "MegaCoreX", "megatinycore"): return 0xC5 elif core == "dxcore": - return 0x5CC5C55C + # DxCore's bootloader/fuse flows do not write lockbits by default. + return None else: sys.stderr.write("Error: Couldn't calculate lockbit for %s\n" % target) env.Exit(1) @@ -129,10 +196,17 @@ def print_fuses_info(fuse_values, fuse_names, lock_fuse): print("-------------------------\n") +def format_fuse_value(value): + if value is None: + return "" + return "0x%.2X" % value + + def calculate_fuses(board_config, predefined_fuses): f_cpu = board_config.get("build.f_cpu", "16000000L").upper() oscillator = board_config.get("hardware.oscillator", "internal").lower() bod = board_config.get("hardware.bod", "2.6v").lower() + bodmode = board_config.get("hardware.bodmode", "disabled").lower() uart = board_config.get("hardware.uart", "no_bootloader").lower() eesave = board_config.get("hardware.eesave", "yes").lower() mvio = board_config.get("hardware.mvio_enable", "no").lower() @@ -151,6 +225,8 @@ def calculate_fuses(board_config, predefined_fuses): print("Clock speed = %s" % f_cpu) print("Oscillator = %s" % oscillator) print("BOD level = %s" % bod) + if core == "dxcore": + print("BOD mode = %s" % bodmode) print("Save EEPROM = %s" % eesave) if core == "dxcore" and "db" in board.get("build.mcu").lower(): print("MVIO enable = %s" % mvio) @@ -159,15 +235,15 @@ def calculate_fuses(board_config, predefined_fuses): print("-------------------------") return ( - predefined_fuses[0] or "0x%.2X" % get_wdtcfg_fuse(), - predefined_fuses[1] or "0x%.2X" % get_bodcfg_fuse(bod), - predefined_fuses[2] or "0x%.2X" % get_osccfg_fuse(f_cpu, oscillator), + predefined_fuses[0] or format_fuse_value(get_wdtcfg_fuse()), + predefined_fuses[1] or format_fuse_value(get_bodcfg_fuse(bod, bodmode)), + predefined_fuses[2] or format_fuse_value(get_osccfg_fuse(f_cpu, oscillator)), "", # reserved - predefined_fuses[4] or "0x%.2X" % get_tcd0cfg_fuse(), - predefined_fuses[5] or "0x%.2X" % get_syscfg0_fuse(eesave, pin, uart), - predefined_fuses[6] or "0x%.2X" % get_syscfg1_fuse(mvio), - predefined_fuses[7] or "0x%.2X" % get_append_fuse(), - predefined_fuses[8] or "0x%.2X" % get_bootend_fuse(uart), + predefined_fuses[4] or format_fuse_value(get_tcd0cfg_fuse()), + predefined_fuses[5] or format_fuse_value(get_syscfg0_fuse(eesave, pin, uart)), + predefined_fuses[6] or format_fuse_value(get_syscfg1_fuse(mvio)), + predefined_fuses[7] or format_fuse_value(get_append_fuse()), + predefined_fuses[8] or format_fuse_value(get_bootend_fuse(uart)), ) @@ -211,7 +287,7 @@ def calculate_fuses(board_config, predefined_fuses): env.Exit(1) fuse_values = [board_fuses.get(fname, "") for fname in fuse_names] -lock_fuse = board_fuses.get("lockbit", "0x%.2X" % get_lockbit_fuse()) +lock_fuse = board_fuses.get("lockbit", format_fuse_value(get_lockbit_fuse())) if core in ("MegaCoreX", "megatinycore", "dxcore"): fuse_values = calculate_fuses(board, fuse_values)