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

ATtiny fuses #128

Closed Thijxx closed 5 years ago

Thijxx commented 5 years ago

Setting the fuses for the ATtiny85 (for example) seems to be a issue that emerges every now and then. I've been struggling with this and read the documentation and some issues here in Github but it just looks broken.

When I use pio run -t upload and the board is attiny85 the fuses set are: E:FF, H:D7, L:E2 and it does not matter what I change in the boards directory in the attiny85.json file. It will always use the same fuses.

But when I run the command pio run -t fuses the fuses are set. Sort of. avrdude errors with avrdude: verification error; content mismatch because while it sets the new fuses it looks like it also sets the old fuses and when it verifies the new fuses it gets confused (no pun intended).

In the background avrdude asks: Would you like this fuse to be changed back? [y/n] But this question is invisible to the user, only visible using verbose output. When I choose n the right fuses are set and verified! So this seems to be a small bug, you maybe need to force the changes here to avoid the question asked by avrdude.

Now I have the right fuses but when I upload my code the fuses are overwritten by the defaults! So I still cannot use it.

ivankravets commented 5 years ago

How does Arduino IDE handle that? You can run uploading in verbose mode using pio run -v -t upload and compare command with Arduino IDE. Do yo usee any difference?

Thijxx commented 5 years ago

The Arduino IDE does not touch the fuses when uploading code. It also does not read the fuses. pio always returns the fuses.

When I use the Arduino IDE to set the fuses to E:FF, H:E2, L:E2 and then switch to pio the fuses are set to E:FF, H:D7, L:E2 when I execute pio run -t upload -v

Arduino IDE code upload (Upload Using Programmer)

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/home/thijs/.arduino15/packages/ATTinyCore/hardware/avr/1.2.1/avrdude.conf"
         User configuration file is "/home/thijs/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyACM0
         Using Programmer              : arduino
         Overriding Baud Rate          : 19200
         Setting bit clk period        : 5.0
         AVR Part                      : ATtiny85
         Chip Erase delay              : 400000 us
         PAGEL                         : P00
         BS2                           : P00
         RESET disposition             : possible i/o
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    12     4    0 no        512    4      0  4000  4500 0xff 0xff
           flash         65    12    32    0 yes      8192   64    128 30000 30000 0xff 0xff
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          2    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e930b (probably t85)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "/tmp/arduino_build_498083/Blink.ino.hex"
avrdude: writing flash (886 bytes):

Writing | ################################################## | 100% 0.69s

avrdude: 886 bytes of flash written
avrdude: verifying flash memory against /tmp/arduino_build_498083/Blink.ino.hex:
avrdude: load data flash data from input file /tmp/arduino_build_498083/Blink.ino.hex:
avrdude: input file /tmp/arduino_build_498083/Blink.ino.hex contains 886 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.27s

avrdude: verifying ...
avrdude: 886 bytes of flash verified

avrdude done.  Thank you.

pio code upload pio run -t upload -v

avrdude: Version 6.3, compiled on Sep 12 2016 at 15:21:49
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch

System wide configuration file is "/home/thijs/.platformio/packages/tool-avrdude/avrdude.conf"

User configuration file is "/home/thijs/.avrduderc"
User configuration file does not exist or is not a regular file, skipping

Using Port                    : /dev/ttyACM0
Using Programmer              : stk500v1
Overriding Baud Rate          : 19200
AVR Part                      : ATtiny85
Chip Erase delay              : 400000 us
PAGEL                         : P00
BS2                           : P00
RESET disposition             : possible i/o
RETRY pulse                   : SCK
serial program mode           : yes
parallel program mode         : yes
Timeout                       : 200
StabDelay                     : 100
CmdexeDelay                   : 25
SyncLoops                     : 32
ByteDelay                     : 0
PollIndex                     : 3
PollValue                     : 0x53
Memory Detail                 :

Block Poll               Page                       Polled
Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom        65    12     4    0 no        512    4      0  4000  4500 0xff 0xff
flash         65     6    32    0 yes      8192   64    128 30000 30000 0xff 0xff
signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00

Programmer Type : STK500
Description     : Atmel STK500 Version 1.x firmware
Hardware Version: 2
Firmware Version: 1.18
Topcard         : Unknown
Vtarget         : 0.0 V
Varef           : 0.0 V
Oscillator      : Off
SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e930b (probably t85)
avrdude: safemode: hfuse reads as D7
avrdude: safemode: efuse reads as FF
avrdude: erasing chip
avrdude: reading input file ".pioenvs/attiny85/firmware.hex"
avrdude: writing flash (7048 bytes):

Writing | ################################################## | 100% 5.44s

avrdude: 7048 bytes of flash written
avrdude: verifying flash memory against .pioenvs/attiny85/firmware.hex:
avrdude: load data flash data from input file .pioenvs/attiny85/firmware.hex:
avrdude: input file .pioenvs/attiny85/firmware.hex contains 7048 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 2.11s

avrdude: verifying ...
avrdude: 7048 bytes of flash verified

avrdude: safemode: hfuse reads as D7
avrdude: safemode: efuse reads as FF
avrdude: safemode: Fuses OK (E:FF, H:D7, L:E2)

avrdude done.  Thank you.
ivankravets commented 5 years ago

Could you provide full commands? Not only outputs. Need to check arguments to avrdude.

Thijxx commented 5 years ago

These are the avrdude commands I can see in the verbose output but it does not contain any fuses option for neither application. They both use a .conf file containing fuse settings but they seem to be something completely different.

Arduino IDE fuse settings in config file

     memory "lfuse"
         size            = 1;
         write           = "1 0 1 0  1 1 0 0  1 0 1 0  0 0 0 0",
                           "x x x x  x x x x  i i i i  i i i i";

         read            = "0 1 0 1  0 0 0 0  0 0 0 0  0 0 0 0",
                           "x x x x  x x x x  o o o o  o o o o";
        min_write_delay = 9000;
        max_write_delay = 9000;
       ;

     memory "hfuse"
         size            = 1;
         write           = "1 0 1 0  1 1 0 0  1 0 1 0  1 0 0 0",
                           "x x x x  x x x x  i i i i  i i i i";

         read            = "0 1 0 1  1 0 0 0  0 0 0 0  1 0 0 0",
                           "x x x x  x x x x  o o o o  o o o o";
        min_write_delay = 9000;
        max_write_delay = 9000;
       ;

     memory "efuse"
         size            = 1;
         write           = "1 0 1 0  1 1 0 0  1 0 1 0  0 1 0 0",
                           "x x x x  x x x x  x x x x  x x x i";

         read            = "0 1 0 1  0 0 0 0  0 0 0 0  1 0 0 0",
                           "x x x x  x x x x  o o o o  o o o o";
        min_write_delay = 9000;
        max_write_delay = 9000;
     ;

pio fuses

     memory "lfuse"
         size            = 1;
         write           = "1 0 1 0  1 1 0 0  1 0 1 0  0 0 0 0",
                           "x x x x  x x x x  i i i i  i i i i";

         read            = "0 1 0 1  0 0 0 0  0 0 0 0  0 0 0 0",
                           "x x x x  x x x x  o o o o  o o o o";
        min_write_delay = 9000;
        max_write_delay = 9000;
       ;

     memory "hfuse"
         size            = 1;
         write           = "1 0 1 0  1 1 0 0  1 0 1 0  1 0 0 0",
                           "x x x x  x x x x  i i i i  i i i i";

         read            = "0 1 0 1  1 0 0 0  0 0 0 0  1 0 0 0",
                           "x x x x  x x x x  o o o o  o o o o";
        min_write_delay = 9000;
        max_write_delay = 9000;
       ;

     memory "efuse"
         size            = 1;
         write           = "1 0 1 0  1 1 0 0  1 0 1 0  0 1 0 0",
                           "x x x x  x x x x  x x x x  x x x i";

         read            = "0 1 0 1  0 0 0 0  0 0 0 0  1 0 0 0",
                           "x x x x  x x x x  o o o o  o o o o";
        min_write_delay = 9000;
        max_write_delay = 9000;
     ;

pio

avrdude -P/dev/ttyACM0 -b19200 -v -p attiny85 -C /home/thijs/.platformio/packages/tool-avrdude/avrdude.conf -c stk50
0v1 -b 19200 -e -D -U flash:w:.pioenvs/attiny85/firmware.hex:i

Arduino IDE
/home/thijs/Downloads/arduino-1.8.7/hardware/tools/avr/bin/avrdude -C/home/thijs/.arduino15/packages/ATTinyCore/hardware/avr/1.2.1/avrdude.conf -v -pattiny85 -carduino -P/dev/ttyACM0 -b19200 -Uflash:w:/home/thijs/.arduino15/packages/ATTinyCore/hardware/avr/1.2.1/bootloaders/empty/empty_all.hex:i

ivankravets commented 5 years ago

Could you try -t program instead of -t upload? See https://docs.platformio.org/en/latest/platforms/atmelavr.html#upload-using-programmer

Thijxx commented 5 years ago

ok

avrdude -P/dev/ttyACM0 -b19200 -v -p attiny85 -C /home/thijs/.platformio/packages/tool-avrdude/avrdude.conf -c stk50
0v1 -U flash:w:.pioenvs/attiny85/firmware.hex:i
ivankravets commented 5 years ago

I see the last command is very similar with Arduino IDE. Does it work now?

Thijxx commented 5 years ago

Not yet. Am I missing something here? I have the fuses set in a JSON file but the fuses I end up with are different.

platformio.ini

[env:attiny85]
platform = atmelavr
board = tickle85
framework = arduino
upload_protocol = stk500v1
upload_flags =
  -P$UPLOAD_PORT
  -b$UPLOAD_SPEED
upload_port = /dev/ttyACM0
upload_speed = 19200
board_f_cpu = 8000000L

tickle85.json

{
  "build": {
    "core": "tiny",
    "extra_flags": "-DARDUINO_AVR_ATTINYX5",
    "f_cpu": "8000000L",
    "mcu": "attiny85",
    "variant": "tinyX5"
  },
  "frameworks": [
    "arduino"
  ],
  "fuses": {
    "efuse": "0xFF",
    "hfuse": "0xFF",
    "lfuse": "0xE2",
    "lock": ""
  },
  "name": "Tickle ATTiny85",
  "upload": {
    "extra_flags": "-e",
    "maximum_ram_size": 512,
    "maximum_size": 8192,
    "protocol": "usbtiny"
  },
  "url": "http://www.atmel.com/devices/ATTINY85.aspx",
  "vendor": "Atmel"
}

result of pio run -t program avrdude: safemode: Fuses OK (E:FF, H:D7, L:E2)

ivankravets commented 5 years ago

Could you help us to resolve this issue? See

The platform script is located in ~/.platformio/platforms/atmelavr/build

Thijxx commented 5 years ago

The fuses are read fine and the -t fuses is also working as it should. avrdude is vague about what it is reading and doing with this message:

avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as FF
avrdude: safemode: hfuse changed! Was ff, and is now df
Would you like this fuse to be changed back? [y/n] n
avrdude: safemode: Fuses OK (E:FF, H:FF, L:E2)

It's saying it reads DF, asks to change it, we do NOT change it and then it's suddenly FF. This can't be right. Then when I run it again it seems it is indeed still DF and not FF.

EDIT
Setting hfuse to FF is not possible so it seems (disabling SPIEN is a bad idea). I changed it to DF and now avrdude works ok and the -t fuses works ok. Unfortunatly -t program still does not set the right fuses. I'm looking at the main.py script again.

stonehippo commented 5 years ago

@Thijxx @ivankravets PIO does not pass the -u flag when programming via AVRDUDE in the builder/main.py script, so the default safemode setting is applied, which causes the fuses to be verified when you do pio run -t progam. It’s not setting the fuses at that point at all, just reading and verifying them.

In the Arduino IDE, most board support (such as ATTinyCore) is set up to do fuses with the Burn Bootloader command, and does not do it during flashing the hex program. PIO does this only through the -t fuses command. Looking at builder/main.py, it’s clear that there’s no fuse settings being done by default. If you wanted that to happen, you should pass multiple targets, i.e.

$ pio run -t fuses -t program

That will run the fuses target, then the program. Because the program target` doesn’t reset fuses (even though it does a chip erase with AVRDUDE), you should get the fuse settings in your custom board config before the program uploads.

stonehippo commented 5 years ago

@Thijxx @ivankravets one more thing: the fuses target needs to get the -u flag in main.py to disable the safemode warning if you really want to disable SPIEN (and I’d do that after programming, so switch the -t order above).

ivankravets commented 5 years ago

Thanks! Should be something done on our side?

stonehippo commented 5 years ago

@ivankravets I'll submit a pull request this weekend with the change to the fuses target for review.

@thijxx did you get the result you wanted by chaining the targets?

Thijxx commented 5 years ago

@stonehippo yes thank you