platformio / platform-atmelavr

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

Extra script for setting fuses and burning bootloader #153

Closed MCUdude closed 4 years ago

MCUdude commented 5 years ago

Hi!

As a developer working with AVRs I feel like the last thing missing from PlatformIO now is the ability to set the correct fuse bits and burn the correct bootloader based on the information given in platformio.ini.

MightyCore, MiniCore, and MegaCore (all supported by PlatformIO) comes with a bunch of pre-compiled bootloaders where all shares the same file names rules.

As long as board, board_build.f_cpu, and board_upload.speed is present in platformio.ini Is it possible for a script to figure out the correct fuse bits and load the correct bootloader hex file.

Preferably there should be three flags, one to only set the fuse bits, one to only burn the bootloader and one for doing both. Since the name and path of the bootloader are so extensive, we can check if the user entered a valid board_build.f_cpu, and board_upload.speed by checking if a bootloader with these values exists.

A bootloader for a >=64kB device is named like this:

bootloaders/atmega1284p/16000000L/optiboot_flash_atmega1284p_UART0_1000000_16000000L_BIGBOOT.hex

A bootloader for a <=32kB device is named like this:

bootloaders/atmega328p/16000000L/optiboot_flash_atmega328p_UART0_115200_16000000L.hex

By adding a new parameter to platformio.ini (board_upload.uart_port maybe?) we can specify if UART0, UART1 or UARTn should be used for uploading. Again, this decides what bootloader hex file is loaded.

Another fuse related feature is the ability to set the brownout detection level. This is possible in Arduino IDE through a separate menu option. Something like board_fuses.bod = 2.7V?

The last option should be to manually set fuses and override everything. My idea here would be to check if board_fuses.high, board_fuses.low and board_fuses.extended is present. If one or more is present, then this fuse is overridden by whatever value the particular boards_fuses fields holds

I have very little experience with python, but I think this should be doable, even for me if someone points me in the right direction. I also haven't worked with PlatformIO advanced scripting before, so forgive me if some of the following questions are silly to some.

EDIT: It seems like boards_mightycore.txt boards_minicore.txt and boards_megacore.txt already exist in my .platformio folder. Maybe these files can be parsed to make this job a little easier?

valeros commented 4 years ago

I've updated scripts for fuses and bootloader. efuse is now optional (maybe other fuses should be also?). Here are some configuration examples:

; Only program fuses (MiniCore family)
[env: ATmega328P_with_custom_fuses]
platform = atmelavr
framework = arduino
board = ATmega328P
upload_protocol = stk500v1
upload_speed = 19200
; Custom fuses
board_fuses.low_fuses = 0xAA
board_fuses.high_fuses = 0xBB
board_fuses.extended_fuses = 0xCC

; Fuses and bootloader selected dynamically
[env: ATmega328P_dynamic_boot_fuses]
platform = atmelavr
framework = arduino
board = ATmega328P
upload_protocol = stk500v1
upload_speed = 19200

[env: uno_dev_board_with_custom_boot]
platform = atmelavr
framework = arduino
board = uno
upload_protocol = stk500v1
upload_speed = 19200
; Bootloader configuration (bootloader image from framework package)
board_bootloader.file = optiboot/optiboot_atmega328.hex
board_bootloader.low_fuses = 0xAA
board_bootloader.high_fuses = 0xBB
board_bootloader.extended_fuses = 0xCC

At the moment, the logic assumes that your bootloaders are located here framework-arduinoavr\bootloaders\optiboot_flash

Am I missing something critical? Would be happy to hear your thoughts on this implementation. Thanks!

MCUdude commented 4 years ago

efuse is now optional (maybe other fuses should be also?).

All AVRs have a high fuse and a low fuse (well, except the new megaavr-0 series, such as ATmega4809, but that's another story 😉), so no need to make other exceptions.

I'd like to test it to see if the generated fuse values are correct. Is there an easy way to install this "version" of pio core? And how do I run the script? With pio run -t fuses and pio run -t bootloader?

MCUdude commented 4 years ago

I think I managed to install this version. When I run pio run -t fuses I get the following error:

Scanning dependencies...
No dependencies
Target configuration:
Clock speed = 16000000L, Oscillator = external, BOD level = 2.7v, UART port = uart0, Save EEPROM = yes
Selected fuses: [lfuse = 0xf7, hfuse = 0xd4, efuse = 0xfd]
Looking for upload port...
Error: Please specify `upload_port` for environment or use global `--upload-port` option.
For some development platforms it can be a USB flash drive (i.e. /media/<user>/<device name>)
*** [fuses] Explicit exit, status 1

upload_port is not needed when setting fuses and burning bootloader.

MCUdude commented 4 years ago

Something isn't right. The script is able to get the specified F_CPU, but not hardware.uart board_upload.speed, hardware.oscillator, hardware.bod and hardware.eesave.

No matter what I type in platformio.ini, is always uses the default values defined in the script.

valeros commented 4 years ago

Something isn't right. The script is able to get the specified F_CPU, but not hardware.uart board_upload.speed, hardware.oscillator, hardware.bod and hardware.eesave

Strange, but I can't reproduce this behavior, this config works for me:

board_hardware.bod = 3.5V
board_hardware.uart = UART1
board_hardware.eesave = no

upload_port is not needed when setting fuses and burning bootloader.

Wow, that's interesting, I just tried to reproduce the same logic as in Arduino IDE. How does avrdude decide what device to program? What happens if two boards are connected simultaneously?

MCUdude commented 4 years ago

aha! I forgot the board_ prefix. It does work now!

Wow, that's interesting, I just tried to reproduce the same logic as in Arduino IDE. How does avrdude decide what device to program? What happens if two boards are connected simultaneously?

If you want to use a programmer that shows up as a serial port, you'll have to specify it under upload_flags otherwise, Avrdude just searches for a specific USB VID and PID. In my case it's the USBasp.

MCUdude commented 4 years ago

Actually, this has been a problem before too. Not long ago I reported issue #158, and @ivankravets provided a fix. Maybe he can provide an elegant solution to this as well?

valeros commented 4 years ago

Thanks, I removed the dependency on upload port. Does it work better now?

MCUdude commented 4 years ago

No, I'm still having issues:

[env:my_environment]
platform = atmelavr
framework = arduino

board = ATmega1284P
board_build.f_cpu = 8000000L
board_hardware.uart = uart0
board_upload.speed = 115200
board_hardware.oscillator = external
board_hardware.bod = 4.3v
board_hardware.eesave = no
upload_protocol = usbasp
upload_flags = -P usb
;upload_port = /dev/tty.Bluetooth-Incoming-Port
Target configuration:
Clock speed = 8000000L, Oscillator = external, BOD level = 4.3v, UART port = uart0, Save EEPROM = no
Selected fuses: [lfuse = 0xf7, hfuse = 0xdc, efuse = 0xfc]
Setting fuses

avrdude: no port has been specified on the command line or the config file
         Specify a port using the -P option and try again

*** [fuses] Error 1
========================================================== [FAILED] Took 0.83 seconds ==========================================================
Hanss-MacBook-Pro-2:pio-script hans$ 

BTW it would be great if the target (in this case, ATmega1284P) could be printed before Clock speed = 8000000L. Like this

Target configuration:
Target = ATmega1284P, Clock speed = 8000000L, Oscillator = external, BOD level = 4.3v, UART port = uart0, Save EEPROM = no

If someone is ever experiencing issues, the generated output alone contains enough information for a developer to figure out what's going on.

valeros commented 4 years ago

I see where the issue is. What flags should be enabled by default? Will it be OK if we leave only -C avrdude.conf -c protocol -p target and everything else user'll need to specify in upload_flags (including -e)?

upload_flags = -PCOM5 -b19200 -e
MCUdude commented 4 years ago

For reference, here is the avrdude command used when setting fuses with MightyCore in Arduino IDE. I suggest having -C{avrdude.conf} -p{target} -c{protocol}, and moving all extra flags to upload_flags. Is it OK for you if the fuses command doesn't have -e, while the bootloader command has it?

valeros commented 4 years ago

Is it OK for you if the fuses command doesn't have -e, while the bootloader command has it?

I think that's fine, anyway it's possible to add -e in upload flags. I've updated scripts, could you please retest? Thanks!

MCUdude commented 4 years ago

Awesome, we're almost there! Fuses works perfectly now 🎉 However, bootloader was not able to find the correct file for ATmega1284P.

Target configuration:
Target = atmega1284p, Clock speed = 8000000L, Oscillator = internal, BOD level = 4.3v, UART port = uart0, Save EEPROM = no
Selected fuses: [lfuse = 0xe2, hfuse = 0xde, efuse = 0xfc]
Error: Couldn't find file /Users/hans/.platformio/packages/framework-arduinoavr/bootloaders/optiboot_flash/bootloaders/atmega1284p/8000000L/optiboot_flash_atmega1284p_UART0_115200_8000000L.hex

The reason for this is that chips with 64kB flash or more (+ AT90CAN32) have the smallest bootloader section of 1024 bytes. Since Optiboot occupies less than 512 bytes, it means that there's more space to play with. These targets are therefore compiled with extra features and called BIGBOOT. Most noticebly, it allows the user to upload content directly to the EEPROM using the bootloader.

Anyways, this means that some target names looks like this:

optiboot_flash/bootloaders/atmega328p/8000000L/optiboot_flash_atmega328p_UART0_115200_8000000L.hex

while others look like this:

optiboot_flash/bootloaders/atmega1284p/8000000L/optiboot_flash_atmega1284p_UART0_115200_8000000L_BIGBOOT.hex

note that for a particular target, both will not exist. Maybe the script can figure it out? In a terminal I'd just type optiboot_flash_atmega1284p_UART0_115200_8000000L and hit the tab key to get the entire file name.

MCUdude commented 4 years ago

Another thing I just found out. neither the fuses.py or the bootloader.py script is able to retrieve upload_flags. I tried adding some extra flags, but it was not picked up.

valeros commented 4 years ago

Hm, works fine on my machine:

upload_flags =
    -PCOM15
    -b19200

How do you add extra flags?

MCUdude commented 4 years ago

I got a content mismatch error when I burned the bootloader, since the -e flag isn't built into the script (it should be). I tried adding -e to upload_flags, but noting happened when I tried to set the fuses again. It looks like this:

upload_flags = -Pusb -e
MCUdude commented 4 years ago

is there a way to show the actual executed Avrdude command? That may help us troubleshoot

valeros commented 4 years ago

You can try --verbose

MCUdude commented 4 years ago

Oh, yeah! Here's the problem!

avrdude "-Pusb -e" -v -p atmega1284p -C /Users/hans/.platformio/packages/tool-avrdude/avrdude.conf -c usbasp -Ulock:w:0x3f:m -Uhfuse:w:0xde:m -Ulfuse:w:0xe2:m -Uefuse:w:0xfc:m

Note the quotes. They shouldn't be there. Also, it's common practice to add extra flags right after -c[programmer], and before the fuses.

Here's the absolute preferred order (used by Arduino IDE for instance)

fuses:

avrdude -C{avrdude.conf} -p{build.mcu} -c{programmer} {extra_flags} -e -Ulock:w:{unlock_fuse}:m -Uefuse:w:{extended_fuse}:m -Uhfuse:w:{high_fuses}:m -Ulfuse:w:{low_fuse}:m 

bootloader:

avrdude -C{avrdude.conf} -p{build.mcu} -c{programmer} {extra_flags} -Uflash:w:{bootloader_file}:i" -Ulock:w:{lock_fuse}:m
valeros commented 4 years ago

Also, it's common practice to add extra flags right after -c[programmer], and before the fuses.

Thanks, updated, now should look better.

Oh, yeah! Here's the problem!

So the solution here is to place each new flag in a new line:

upload_flags =
  -Pusb
  -e
MCUdude commented 4 years ago

So there is no way of making it work when everything is on one line? IMO having everything on one like is "nicer to look at", and it's suddenly another rule one have to take into account? It would be awesome if it supported both everything on the same line and separated with newlines. I managed to do this in my script though.

valeros commented 4 years ago

Maybe it's a good idea to be consistent with the official documentation ?

MCUdude commented 4 years ago

Ah, sorry! Let's keep it similar to the official documentation.

valeros commented 4 years ago

Have you tried the latest revision? Now it should be able to find binaries for BIGBOOT targets.

MCUdude commented 4 years ago

I'm at work now, so I don't have any suited hardware to test with. I will try again when I get home. So now the script accepts .hex and _BIGBOOT.hex as file suffix?

liebman commented 4 years ago

Problem: with this branch I can no longer burn fuses for attiny85. platformio.ini:

[env]
board = attiny85
platform = atmelavr@1.15.0
framework = arduino
build_flags = -D__AVR_ATtiny85__
board_build.f_cpu = 1000000L ; we run at 1Mhz
lib_deps =
    https://github.com/NicoHood/PinChangeInterrupt.git#ed1c1f4 ; current head as of Jul 27, 2019
extra_scripts=fuses.py ; fix fuses target not to erase flash!

[env:new_fuses]
platform = https://github.com/platformio/platform-atmelavr.git#feature/new-fuses-programming
; fuses for 1Mhz/bod=1.8/EESAVE
board_fuses.hfuse = 0xd6
board_fuses.lfuse = 0x62

and fuses.py used to remove the -e option when burning fuses as I need to set the reset pin to an IO so I upload the firmware then burn fuses:

Import('env')

# the uplaod flags for attiny85 adds -e that erases the flash and when we don't
# want that to happen when we are setting the fuses, espically when we change
# the reset pin to an IO pin.  The '-e' is actually added twice, once via extra
# upload flags in the board definition and once in the setup for the fuses target
def fuses_command(source, target, env):
    env['UPLOADERFLAGS'].remove('-e')
    cmd = " ".join(
        ["avrdude", "$UPLOADERFLAGS"] +
        ["-U%s:w:%s:m" % (k, v)
        for k, v in env.BoardConfig().get("fuses", {}).items()]
    )
    return env.Execute(cmd)

env.Replace(FUSESCMD=fuses_command)

Result:

zod: 07:46:39 I2CAnalogClock chris.l$ pio run -e new_fuses -t fuses
Processing new_fuses (platform: https://github.com/platformio/platform-atmelavr.git#feature/new-fuses-programming; board: attiny85; framework: arduino)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/attiny85.html
PLATFORM: Atmel AVR 1.15.0 #58c68e1 > Generic ATtiny85
HARDWARE: ATTINY85 1MHz, 512B RAM, 8KB Flash
PACKAGES: toolchain-atmelavr 1.50400.190710 (5.4.0), framework-arduinoavr 4.2.0, tool-avrdude 1.60300.190628 (6.3.0)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 10 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <PinChangeInterrupt> 1.2.7 #ed1c1f4
|-- <EEPROM> 2.0
|-- <Wire> 1.0
Error: fuse programming for attiny85 is not supported.
======================================================================================================================================= [FAILED] Took 0.43 seconds =======================================================================================================================================

Environment    Status    Duration
-------------  --------  ------------
default        IGNORED
testing        IGNORED
new_fuses      FAILED    00:00:00.435
================================================================================================================================== 1 failed, 0 succeeded in 00:00:00.435 ==================================================================================================================================
MCUdude commented 4 years ago

@valeros Now It's able to find BIGBOOT bootloaders, but it now can't find "regular" ones:

Target configuration:
Target = atmega32, Clock speed = 1000000L, Oscillator = internal, BOD level = 2.7v, UART port = uart0, Save EEPROM = no
Selected fuses: [lfuse = 0xa1, hfuse = 0xde]
Error: Couldn't find file /Users/hans/.platformio/packages/framework-arduinoavr/bootloaders/optiboot_flash/bootloaders/atmega32/1000000L/optiboot_flash_atmega32_UART0_115200_1000000L_BIGBOOT.hex

Another thing. I'm not able to manually override fuses. Here is my current configuration

[env:my_environment]
platform = atmelavr
framework = arduino

board = ATmega32
board_build.f_cpu = 1000000L
board_hardware.uart = uart0
board_upload.speed = 115200
board_hardware.oscillator = internal
board_hardware.bod = 2.7v
board_hardware.eesave = no
upload_protocol = usbasp
board_fuses.hfuse = 0xff
board_fuses.lfuse = 0xff
upload_flags = 
  -Pusb

And here is the output:

Target configuration:
Target = atmega32, Clock speed = 1000000L, Oscillator = internal, BOD level = 2.7v, UART port = uart0, Save EEPROM = no
Selected fuses: [lfuse = 0xa1, hfuse = 0xde]
avrdude -p atmega32 -C /Users/hans/.platformio/packages/tool-avrdude/avrdude.conf -c usbasp -Pusb -Ulock:w:0x3f:m -Uhfuse:w:0xde:m -Ulfuse:w:0xa1:m
valeros commented 4 years ago

Another thing. I'm not able to manually override fuses.

Sorry, forget to mention, hfuse, lfuse, efuse are now high_fuse, low_fuse, extended_fuses (just to be consistent with Arduino IDE. Is it OK or it'd better to keep hfuse, lfuse, efuse?)

It's able to find BIGBOOT bootloaders, but it now can't find "regular" ones:

Maybe becuase there is no suitable regular one for your config? The only one available for atmega32 is optiboot_flash_atmega32_UART0_9600_1000000L.hex. But I agree the error message is a bit misleading.

valeros commented 4 years ago

@liebman Thanks for reporting. -e flag is now excluded from default set of flags for fuses target. Could you please pull the latest changes and try again? @MCUdude I've reverted back hfuse, lfuse, efuse values.

MCUdude commented 4 years ago

Maybe becuase there is no suitable regular one for your config? The only one available for atmega32 is optiboot_flash_atmega32_UART0_9600_1000000L.hex. But I agree the error message is a bit misleading.

Sorry, my bad. You're absolutely right.

MCUdude I've reverted back hfuse, lfuse, efuse values.

Awesome!

liebman commented 4 years ago

@valeros yes, fuses run correctly again. Thanks!

liebman commented 4 years ago

I see that its now passing -Ulock:w:0x3f:m and was not before. Looks like 0x3f is a safe value but I was wondering where that value is coming from? A global default?

MCUdude commented 4 years ago

I see that its now passing -Ulock:w:0x3f:m and was not before. Looks like 0x3f is a safe value but I was wondering where that value is coming from? A global default?

Used by basically all AVRs that uses a bootloader. 0x3F is totally fine if you don't need to protect the content of the flash and eeprom memory.

liebman commented 4 years ago

@valeros I get this warning from avrdude:

avrdude: WARNING: invalid value for unused bits in fuse "lock", should be set to 1 according to datasheet
This behaviour is deprecated and will result in an error in future version
You probably want to use 0xff instead of 0x3f (double check with your datasheet first).
avrdude: 1 bytes of lock verified

So at least for attiny85 the default value should be 0xff. Or maybe only supply the -Ulock option for some types.

MCUdude commented 4 years ago

@valeros I was playing around with the script last night but had serious issues getting the script to work properly. Every now and then I got a mismatch error on the lock bits, and the script wouldn't continue.

After some time I realized that you can't set the lock bits to 0x3F without also erasing the flash memory with the -e flag. We still have to use lockbits, because 0x0F will protect the bootloader area, which is important.

The ATtiny85 does not have a bootloader area that needs to be protected, so the lock bits can be permanently besat to 0xFF. On the other side, AVRs that have a bootloader area (some ATTinys and all ATmegas except 48/48P) has to have -e applied when setting fuses and burning bootloader. This is important.

I suggest we focus on getting this script to work on the ATmegas first, before continuing to add support for other ATtinys. ATtinys has to be treated differently, but this cannot affect the ATmegas.

For reference, here's the error I get when I try to set the fuses on an ATmega1284P that already has a bootloader. adding -e fixes it.

Target configuration:
Target = atmega1284p, Clock speed = 16000000L, Oscillator = external, BOD level = 2.7v, UART port = uart0, Save EEPROM = yes
Selected fuses: [lfuse = 0xf7, hfuse = 0xd6, efuse = 0xfd]
avrdude -p atmega1284p -C /Users/hans/.platformio/packages/tool-avrdude/avrdude.conf -c usbasp -Pusb -B32 -Ulock:w:0x3f:m -Uhfuse:w:0xd6:m -Ulfuse:w:0xf7:m -Uefuse:w:0xfd:m

avrdude: set SCK frequency to 16000 Hz
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9705 (probably m1284p)
avrdude: reading input file "0x3f"
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x3f:
avrdude: load data lock data from input file 0x3f:
avrdude: input file 0x3f contains 1 bytes
avrdude: reading on-chip lock data:

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

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x0f != 0x3f
avrdude: verification error; content mismatch

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

avrdude done.  Thank you.

*** [bootloader] Error 1
========================================================== [FAILED] Took 0.80 seconds ==========================================================
Hanss-MacBook-Pro-2:pio-script hans$ pio run -t bootloader --verbose
Processing my_environment (platform: atmelavr; framework: arduino; board: ATmega1284P; board_build.f_cpu: 16000000L; board_hardware.uart: uart0; board_upload.speed: 115200; board_hardware.oscillator: external; board_hardware.bod: 2.7v; board_hardware.eesave: yes; upload_protocol: usbasp; upload_flags: -Pusb, -B32)
-------------------------------------------------------------------------------------------------------------------------------------------------
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/ATmega1284P.html
PLATFORM: Atmel AVR 1.15.0 > ATmega1284P
HARDWARE: ATMEGA1284P 16MHz, 16KB RAM, 127KB Flash
PACKAGES: toolchain-atmelavr 1.50400.190710 (5.4.0), framework-arduinoavr 4.2.0
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 12 compatible libraries
Scanning dependencies...
No dependencies
Target configuration:
Target = atmega1284p, Clock speed = 16000000L, Oscillator = external, BOD level = 2.7v, UART port = uart0, Save EEPROM = yes
Selected fuses: [lfuse = 0xf7, hfuse = 0xd6, efuse = 0xfd]
avrdude -p atmega1284p -C /Users/hans/.platformio/packages/tool-avrdude/avrdude.conf -c usbasp -Pusb -B32 -Ulock:w:0x3f:m -Uhfuse:w:0xd6:m -Ulfuse:w:0xf7:m -Uefuse:w:0xfd:m

avrdude: set SCK frequency to 16000 Hz
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9705 (probably m1284p)
avrdude: reading input file "0x3f"
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x3f:
avrdude: load data lock data from input file 0x3f:
avrdude: input file 0x3f contains 1 bytes
avrdude: reading on-chip lock data:

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

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x0f != 0x3f
avrdude: verification error; content mismatch

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

avrdude done.  Thank you.

*** [bootloader] Error 1
========================================================== [FAILED] Took 0.80 seconds ==========================================================
valeros commented 4 years ago

I suggest we focus on getting this script to work on the ATmegas first, before continuing to add support for other ATtinys.

Unfortunately we cannot only focus on individual targets. Users should be able to program at least fuses (fuse programming was already in previous versions of the platform, so we should try not to break it).

@liebman @MCUdude So what are your recommendations on this? Do we need to add -e to default flags only for targets with bootloader (is there a list of this targets)? What lock bits to use? Maybe user should specify it?

MCUdude commented 4 years ago

My recommendation is that we add 0x0F + -e to all targets that have a bootloader area.

We can make a list of all target that does not have a bootloader. It's ATmega48/48P + all ATtinys except ATtiny828.These should have the lock fuse set to 0xff.

valeros commented 4 years ago

@MCUdude So what are our next steps? Can you prepare the list of targets that require 0xff?

MCUdude commented 4 years ago

@valeros I can do that!

MCUdude commented 4 years ago

@valeros here's a list of all AVRs (I'm aware of) that require 0xff as lock bit

"atmega48", "atmega48p",
"attiny4313", "attiny2313", "attiny1634", "attiny861", "attiny841",
"attiny461", "attiny441", "attiny261", "attiny167", "attiny88",
"attiny87", "attiny85", "attiny84", "attiny48", "attiny45",
"attiny44", "attiny43", "attiny40", "attiny26", "attiny25",
"attiny24", "attiny13", "attiny13a"

Note that I've not added legacy parts such as the ATtiny15.

valeros commented 4 years ago

@MCUdude Thanks, I've made small changes to the fuses target, now it should be able to detect targets without bootloader. Did I miss anything? Could you please retest? Thanks!

MCUdude commented 4 years ago

@valeros just tried it on an ATmega1284P and an ATmega48P. Works great with both!

Just as expected, when running the fuses command when the 1284P is the target, the correct efuse is calculated and the -e flag is automatically added to the Avrdude command.

When running the fuses command on the 48P, the efuse is set to 0xff and no -e flag is added to the Avrdude command. Perfect!

MCUdude commented 4 years ago

So what's next? We now have a good foundation we later can add new targets to. As you already know, I've not added support for all ATtinys. I think the next step is to add support for @SpenceKonde's ATTinyCore, which covers pretty much all ATtinys except ATtiny13.

MCUdude commented 4 years ago

But I think the scripts are ready to be released with MightyCore, MiniCore and MegaCore support, along with some nice documentation how how to setup platformio.ini properly to generate the right fuse values.

valeros commented 4 years ago

Would be awesome, if you could you prepare some initial page with basic information that is important in your opinion (like the description of parameters used in calculations, their default values, etc)? BTW, did you try the bootloader target? Does it work as expected?

MCUdude commented 4 years ago

BTW, did you try the bootloader target? Does it work as expected?

I did for the 1284P, and it worked as expected. If you want I can provide some information about the different parameters and what they do. Is it OK if I post it here? I'm also not a native English speaker or writer, so someone should definitely read through what I've written to correct the worst grammar mistakes.

MCUdude commented 4 years ago

@valeos @ivankravets here's a base. Something should also be added about upload_protocol and upload_flags if not already in the documentation.

board_build.f_cpu = 16000000L Specifies the clock frequencies in [Hz]. Defaults to 16000000L if not specified. Is used to determine what bootloader file to load and what oscillator option to choose. A capital L has to be added to the end of the frequency number.

hardware.oscillator = external Specifies to use the internal or external oscillator. Defaults to external if not specified. The only valid board_build.f_cpu values when internal is used are `8000000L and 1000000L

hardware.uart = uart0 Specifies the hardware UART port used for serial upload. can be uart0, uart1, uart2 or uart3 depending on target. Defaults to uart0 if not specified. Use no_bootloader if you're not using a bootloader for serial upload.

board_upload.speed = 115200 Specifies the upload baud rate used by the bootloader. Higher or lower upload speeds may be used. See the Optiboot flash for a complete list.

Supported clocks/oscillator type/baud:

Frequency board_build.f_cpu hardware.oscillator board_upload.speed
20 MHz 20000000L external 115200
18.4320 MHz 18432000L external 115200
16 MHz 16000000L external 115200
14.7456 MHz 14745600L external 115200
12 MHz 12000000L external 57600
11.0592 MHz 11059200L external 115200
8 MHz 8000000L external/internal 57600/38400
7.3728 MHz 7372800L external 115200
3.6864 MHz 3686400L external 115200
1.8432 MHz 1843200L external 115200
1 MHz 1000000L external/internal 9600

hardware.bod = 2.7v Specifies the hardware brown-out detection. Defaults to 2.7v if not specified. Use disabled to disable brown-out detection.

Valid BOD values:

ATmega8
ATmega8535/16/32
ATmega64/128
AT90CAN32/64/128 Other targets
4.0v 4.1v 4.3v
2.7v 4.0v 2.7v
disabled 3.9v 1.8v
3.8v disabled
2.7v
2.6v
2.5v
disabled

hardware.eesave = yes Specifies if the EEPROM memory should be retained when uploading using a programmer. Defaults to yes of not specified. Use no to disable

Markdown tables for easy copy/paste

| Frequency   | board_build.f_cpu | hardware.oscillator | board_upload.speed |
|-------------|-------------------|---------------------|--------------------|
| 20 MHz      | 20000000L         | external            | 115200             |
| 18.4320 MHz | 18432000L         | external            | 115200             |
| **16 MHz**  | **16000000L**     | **external**        | 115200             |
| 14.7456 MHz | 14745600L         | external            | 115200             |
| 12 MHz      | 12000000L         | external            | 57600              |
| 11.0592 MHz | 11059200L         | external            | 115200             |
| 8 MHz       | 8000000L          | external/internal   | 57600/38400        |
| 7.3728 MHz  | 7372800L          | external            | 115200             |
| 3.6864 MHz  | 3686400L          | external            | 115200             |
| 1.8432 MHz  | 1843200L          | external            | 115200             |
| 1 MHz       | 1000000L          | external/internal   | 9600               |

| ATmega8<br/>ATmega8535/16/32<br/> ATmega64/128 | AT90CAN32/64/128 | Other targets |
|------------------------------------------------|------------------|---------------|
| 4.0v                                           | 4.1v             | 4.3v          |
| **2.7v**                                       | 4.0v             | **2.7v**      |
| disabled                                       | 3.9v             | 1.8v          |
|                                                | 3.8v             | disabled      |
|                                                | **2.7v**         |               |
|                                                | 2.6v             |               |
|                                                | 2.5v             |               |
|                                                | disabled         |               |
MCUdude commented 4 years ago

@valeros How is the implementation going?

I have a feature I'd like to discuss with you guys before I start working on it. [MightyCore](https://github.com(MCUdude/MightyCore) have three different pinouts; Standard, Bobuino and Sanguino. Standard and Sanguino are very similar, but the Bobuino pinout is supposed to be Arduino Uno compatible. The problem is that the Bobuino pinout uses the exact same bootloader as the Standard pinout do, and this breaks the idea that the LED should be connected to pin 13.

One (elegant) way around this is to add an extra parameter to the bootloader file name; the physical LED pin. Instead of

optiboot_flash_atmega1284p_UART0_115200_16000000L_BIGBOOT.hex

we instead have for the Standard pinout

optiboot_flash_atmega1284p_UART0_115200_16000000L_B0_BIGBOOT.hex

and for the Bobuino pinout

optiboot_flash_atmega1284p_UART0_115200_16000000L_B7_BIGBOOT.hex

This has to be done to MiniCore and MegaCore as well, but neither if these cores have pinouts that require a change in the physical LED position.

How does this fit in in the currect script implementation? Since the LED is pinout spesific, maybe this parameter can be stored in the manifest file?

See MightyCore issue 157 for more details.

valeros commented 4 years ago

Hi @MCUdude ! The scripts are merged but not yet released. It shouldn't be hard to add a new part to the name of bootloader and reupload framework packages with new bootloader names. What does the pin number depend on? Is it MCU specific or the pin number only depends on variant field? So for Standard it will be B0 and for Bobuino it will be B7?

MCUdude commented 4 years ago

What does the pin number depend on? Is it MCU specific or the pin number only depend on the variant field?

It depends on both really. When using MiniCore the default LED pin is B5, which corresponds to digital pin 13.

Here's a complete list

Core Pinout LED pin
MightyCore Standard B0
MightyCore Sanguino B0
MightyCore Bobuino B7
MegaCore 64-pin-avr B5
MegaCore 100-pin-avr B7
MegaCore 100-pin-arduino-mega B7
MiniCore Standard B5
MiniCore pb-variant B5

I suggest we'll focus on this later. First I'll have to properly implement this in all three cores. It's by no means a "killer feature", it will just make the bootloader LED a little more consistent when using other pinouts than the standard one 🙂