Board_fuses vs board_bootloader?

what’s the difference between board_fuses.lfuse and board_bootloader.lfuse.
when would you use one vs the other?

Where do you see those two being referenced?

https://docs.platformio.org/en/latest/platforms/atmelavr.html

If you run pio run -t bootloader it will burn the bootloader according to the board_bootloader settings with its respective fuses (lfuse, hfuse, efuse, …). See code

When using pio run -t program for normal programming it will use the fuses set by board_fuses. See

Optimally if you program a custom bootloader and a firmware, the fuses should match.

If you are not using a custom bootloader or using the pio run -t bootloader target, bootloader fuses will not be used anyway and can be ignored.

I, i never used lock bits until now. I’m using an atmega328p with arduino as isp programmer; i use this platformio.ini:

; PlatformIO Project Configuration File
;
;   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 and examples
; https://docs.platformio.org/page/projectconf.html

[env:nanoatmega3283t]
platform = atmelavr
framework = arduino
board = uno
lib_extra_dirs =
  D:\Documenti-Gio\Arduino-PROJECTS\libraries
upload_protocol = stk500v1
; FUSES STANDARD + FULL SWING CRYSTAL
board_fuses.lfuse = 0xF7
board_fuses.hfuse = 0xDE
board_fuses.efuse = 0xFD

upload_flags =
    -P$UPLOAD_PORT
    -b$UPLOAD_SPEED 
    -e 

upload_port = COM4
upload_speed = 19200     

Now i made a project that i would like to protect from only reading and copy. I read a bit about LB fuses and it seems to me that i have to put LB at 0x00.
Can i simply add line…

board_fuses.lock_bits = 0x00

… to my platformio.ini and program my chip as before or is needed a different method to program lock bits?

Looking at PIO’s code to get the fuses

The logic reads as follows. If a board_fuses.lock exists (e.g., from your platformio.ini or the board’s definition file), it will be used. Otherwise, the default value is the return value of the get_lock_bits function.

So you have to write

board_fuses.lock = 0x00

into your platformio.ini and then run the “Fuses” target in VSCode or pio run -t fuses from the commandline, as outlined in the above mentioned docs. That will cause an avrdude invocation which will program the lock bits to your desired value.

I’m playng with fuses… A question: upload_flag -e can restore board_fuses.lock to a non-locked state?
I mean if i set fuses (even bit lock at 0x00), then i flash my code with -e flag, the mcu is no longer locked. Is this a normal behaviour?

A related question: how can i read fuses state on connected mcu in platformio?

But if you have to erase the chip to unlock it, the program is also gone with it, so the protection worked? According to https://www.avrfreaks.net/forum/erasing-chip-not-resetting-lock-bits that’s normal. Atmel / now Microchip engineers would be the people to ask to make sure.

PlatformIO has no “read fuses” command but:

  1. isn’t the state of the fuse shown in the AVRdude output in each programming?
  2. You can use advanced scripting + custom targets to implement a new target which triggers the appropriate avrdude command to read out fuses (and / or Flash and EEPROM contents) to stdout or a file. E.g., avrdude -c usbtiny -p m328p -U flash:r:extracted.hex:i -U lfuse:r:-:b is a command that will attempt to use AVRDude with the usbtiny programmer to readout the flash contents in intel-hex format to the file extracted.hex and the LFUSE content in binary to stdout (-). All options are documented in avrdude and various internet pages.
  3. There also exist GUI programs for AVRDude to make it easier.

@maxgerhardt, I noted that the pio don’t get lock value from board.lock and yes from board.lock_bit.

I did the following test:

My platformio.ini

[env:test]
platform = atmelavr
board = ATmega328PB

board_fuses.lock = 0xFF
board_fuses.efuse = 0xFD
board_fuses.hfuse = 0xD6
board_fuses.lfuse = 0xE2

and the pio run -t fuses:

Selected fuses: [lfuse = 0xE2, hfuse = 0xD6, efuse = 0xFD]
avrdude -p atmega328pb -C "/home/mario/.platformio/packages/tool-avrdude/avrdude.conf" -e -c arduino -Ulock:w:0x0f:m -Uhfuse:w:0xD6:m -Ulfu
se:w:0xE2:m -Uefuse:w:0xFD:m

Note that the lock fuse is has not value I defined in platformio.ini (-Ulock:w:0x0f:m and I defined 0xFF).

when I put board_lock_bit in platformio.ini, I get the correct set for lock fuse.

My new platformio.ini

[env:test]
platform = atmelavr
board = ATmega328PB

board_fuses.lock = 0xFF
board_fuses.lock_bits = 0xFF
board_fuses.efuse = 0xFD
board_fuses.hfuse = 0xD6
board_fuses.lfuse = 0xE2

and the pio run -t fuses:

Selected fuses: [lfuse = 0xE2, hfuse = 0xD6, efuse = 0xFD]
avrdude -p atmega328pb -C "/home/mario/.platformio/packages/tool-avrdude/avrdude.conf" -e -c arduino -Ulock:w:0xFF:m -Uhfuse:w:0xD6:m -Ulfu
se:w:0xE2:m -Uefuse:w:0xFD:m

Note that the lock fuse now get the correct value (-Ulock:w:0xFF:m).

I don’t know if is a problem in platformio. I don’t found any documentation about difference between lock and lock_bit in platformio documentation.

The logic has changed since the time I’ve posted it. Have a look at

The fuses target will use board_fuses.lock_bits and when burning the bootloader (pio run -t bootloader) it will uses bootloader_fuses.lock_bits. No more board_fuses.lock.

Theses fuses are also explained in the docs.

1 Like