Fuses per Source Code setzen

OP #7968419
Lesenswert?

Hallo,

ich habe ein Atmega2560 Pro Board. Dabei lassen sich die Fuses nicht über die USB-Schnittstelle bzw. den Bootloader setzen.

Daher hatte ich versucht, die per Source-Code zu setzen. Gefunden habe ich dazu mehrere Beispiele im Internet, u.a. das hier: https://www.nongnu.org/avr-libc/user-manual/group__avr__fuse.html

Nachdem das auf dem Board per Software nicht funktioniert hatte, war meine Vermutung, dass es am Board liegt und daher habe ich das für einen Atmega2560 auf dem STK600 probiert.

Hier der Source dazu:

1
#include <avr/io.h>
2
#include <util/delay.h>
3

4
__fuse_t __fuse __attribute__((section (".fuse"))) =
5
    {
6
        .low = LFUSE_DEFAULT,
7
        .high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & ~FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),
8
        //.extended = EFUSE_DEFAULT,
9
    .extended = FUSE_BODLEVEL0,
10
    };
11

12
#define STATUS_LED_DDR  DDRB
13
#define STATUS_LED_PORT  PORTB
14
#define STATUS_LED    PB7
15

16
int main( void )
17
{
18
  STATUS_LED_DDR = ( 1 << STATUS_LED ) ;
19

20
    while( 1 ) {
21
      STATUS_LED_PORT ^= ( 1 << STATUS_LED );
22
        _delay_ms(1500);
23
    }
24
}

Das ich dort den Bodlevel0 eingetragen habe, hat nur den Grund, dass ich überhaupt eine Änderung an den Fuses gegenüber vorher sehen wollte. Ich habe auch bei einem weiteren Test High-Fuse & ~FUSE_JTAGEN eingetragen.

Ich habe mit avrdude zunächst die hex-Datei übertragen. Irgendwo im Internet habe ich gelesen, dass ich die elf-Datei übertragen muss. Der Aufruf war folgendermaßen:

1
avrdude.exe -p atmega2560 -P usb -c stk600  -U flash:w:AVR_Set_Fuses.elf:a

Aber auch das hat nicht funktioniert.

Auch beim Überspielen der elf-Datei mit Mikrochip-Studio hat das nicht funktioniert.

Daraufhin habe ich das zum Testen mit der arduino-IDE gemacht.

1
#include <avr/io.h>
2
FUSES = 
3
{
4
    LFUSE_DEFAULT, // .low
5
    (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & ~FUSE_JTAGEN), // .high
6
    //EFUSE_DEFAULT, // .extended
7
    FUSE_BODLEVEL0,
8
};
9

10
#define STATUS_LED_DDR  DDRB
11
#define STATUS_LED_PORT  PORTB
12
#define STATUS_LED  PB7
13

14
void setup() {
15
  // put your setup code here, to run once:
16
  STATUS_LED_DDR = ( 1 << STATUS_LED ) ;        // PB5 an PORTB als Ausgang setzen
17
}
18

19
void loop() {
20
  // put your main code here, to run repeatedly:
21
  STATUS_LED_PORT ^= ( 1 << STATUS_LED );
22
  _delay_ms(1500);
23
}

Aber auch das hat nicht funktioniert. In der Arduino-IDE habe ich das per Programmer auf das STK600 gespielt. Dort wird allerdings immer die Hex-Datei aufgerufen.

Kann mir jemand sagen, was ich falsch mache?

Vorab vielen Dank. Andreas

#7968428
Lesenswert?

Würde mich nicht überraschen wenn die Fuses nur via ISP/Debug Port veränderbar sind.

Lies mal das entsprechende Kapitel im Handbuch des µC nach.

Da bei AVR auch der primäre Oszillator in den Fuses drin ist, wird es mit dem Setzen in Software eher schwierig.

Die Fuse Daten landen via Liker im ELF und können so von ISP Tools wie avrdude direkt benutzt werden (d.h. von Tools die Fuses schreiben können).

Kann sein das diese Daten gar nicht erst im Hex landen - da würde ich mal nach der Zeile im Makefile schauen die das Hex erzeugt.

#7968434
Lesenswert?

Andreas schrieb:

Daher hatte ich versucht, die per Source-Code zu setzen. Gefunden habe ich dazu mehrere Beispiele im Internet, u.a. das hier: https://www.nongnu.org/avr-libc/user-manual/group__avr__fuse.html

Dann lies nochmal genau nach, was da steht. Fuses setzen über Software geht nicht. Das geht nur über einen ISP/Jtag/…Programmer, nicht jedoch über einen bootloader. Wenn dein Board die dafür erforderlichen Pins nicht rausführt, dann gehts halt gar nicht. Das ist allerdings ziemlich unwahrscheinlich.

https://forum.arduino.cc/t/fuses-uber-arduino-board-andern/176933/4

In der Arduino-IDE habe ich das per Programmer auf das STK600 gespielt. Dort wird allerdings immer die Hex-Datei aufgerufen.

AVRDude von Hand mit dem elf-file aufrufen würde helfen, aber eben nicht über den bootloader.

Oliver

: Bearbeitet durch User
#7968442
Lesenswert?

Andreas schrieb:

Gefunden habe ich dazu mehrere Beispiele im Internet, u.a. das hier: https://www.nongnu.org/avr-libc/user-manual/group__avr__fuse.html

Da steht doch explizit drin, dass das nur eine ELF-Section mit den Fuses erzeugt, die dann von geeigneten Programmer-Tools gelesen wird.

Bringt Dir also gar nichts, wenn Dein Bootloader Dich nicht an die Fuses lässt.

Andreas schrieb:

avrdude.exe -p atmega2560 -P usb -c stk600 -U flash:w:AVR_Set_Fuses.elf:a

Damit werden ohnehin keine Fuses geschrieben.

Andreas schrieb:

Irgendwo im Internet habe ich gelesen

Tolle Quelle. Wie wär's stattdessen mit der offiziellen AVRDUDE-Dokumentation?

OP #7968446
Lesenswert?

Jim M. schrieb:

Kann sein das diese Daten gar nicht erst im Hex landen - da würde ich mal nach der Zeile im Makefile schauen die das Hex erzeugt.

Mit dem Hex-File kann ich nachvollziehen. Aber ich habe das auch mit dem elf-File versucht. Jim M. schrieb im Beitrag #7968428:

Lies mal das entsprechende Kapitel im Handbuch des µC nach.

Das ich die Fuses nicht direkt in der Software ändern kann, dass hatte ich verstanden. Aber laut der von mir verlinkten Seite, sollte das auf die Art gehen. Danke Dir trotzdem für Deine Anmerkung.

Oliver S. schrieb:

Dann lies nochmal genau nach, was da steht. Fuses setzen über Software geht nicht. Das geht nur über einen ISP/Jtag/…Programmer, nicht jedoch über einen bootloader.

Vielleicht solltest Du mal genau lesen, was ich im Eingangsbeitrag geschrieben habe. Dann hättest Du festgestellt, dass ich das beim STK600 gemacht habe. Ohne Bootloader.

Oliver S. schrieb:

AVRDude von Hand mit dem elf-file aufrufen würde helfen, aber eben nicht über den bootloader.

Auch hier hilft lesen meines Eingangsbeitrages. Darin steht, dass ich das elf-File auf das STK600 übertragen habe. Sogar ohne avrdude und nur mit Mikrochip. Wenn von Dir nichts hilfreiches kommt, dann lass es doch einfach. Ich habe auch den Eindruck, dass Du die von mir verlinkte Seite gar nicht gelesen hast.

Hmmm schrieb:

Bringt Dir also gar nichts, wenn Dein Bootloader Dich nicht an die Fuses lässt.

Nochmal, ich habe es auch über Mikrochip-Studio direkt auf einen Atmega2560 auf dem STK600 versucht. Dabei habe ich auch das elf-File übertragen. Auch dies ging nicht.

: Bearbeitet durch User
Persönliche Seite #7968517
Lesenswert?

Andreas schrieb:

Ich habe mit avrdude zunächst die hex-Datei übertragen. Irgendwo im Internet habe ich gelesen, dass ich die elf-Datei übertragen muss.

Nicht "muss", aber ELF macht vieles einfacher.

Der Aufruf war folgendermaßen:

1
> avrdude.exe -p atmega2560 -P usb -c stk600  -U 
2
> flash:w:AVR_Set_Fuses.elf:a

Da wird der Flash geschrieben. Es fehlt ddas Schreiben der Fuse Section.

Soweit ich weiß kann man die Fuses zwar im Programm angeben, aber dadirch landen dien nicht per Magie auf dem Device. Schreiben muss man die Fuses schon, und die liegen eben im normalen Progammspeicher, wie er mit flash:w übertragen wird.

Müsste sowas sein wie:

1
-Uhfuse:w:AVR_Set_Fuses.elf -Ulfuse:w:AVR_Set_Fuses.elf -Uefuse:w:AVR_Set_Fuses.elf

Und da sieht man auch warum das einfacher ist als mit IHEX: Man brauch nur eine Datei, nämlich AVR_Set_Fuses.elf anstatt nen ganzen Zoo von .hex.

#7968520
Lesenswert?

Andreas schrieb:

Kann mir jemand sagen, was ich falsch mache

Du hast keinen ATmega2560 board sondern einen ARDUINO 2560(pro).

Bei dem lassen sich fuses nicht setzen aka verändern.

Denn er ist schon programmiert mit einem Programm namens bootloader und fuses passend zum Quartz auf dem board.

Deine 'Programme' aka Sketche werden nur noch seriell hochgeladen.

Wenn du den ATmega2560 runterlötest und in einen richtigen Programmer steckst, kannst du alles machen.

u.a. hex oder elf reinprogrammieren.

: Bearbeitet durch User
#7968558
Lesenswert?

Andreas schrieb:

Nochmal, ich habe es auch über Mikrochip-Studio direkt auf einen Atmega2560 auf dem STK600 versucht. Dabei habe ich auch das elf-File übertragen. Auch dies ging nicht.

Den Grund dafür habe ich Dir genannt:

Hmmm schrieb:

Damit werden ohnehin keine Fuses geschrieben.

Und Johann hat dann noch mehr dazu geschrieben. Man muss AVRDUDE schon sagen, was es alles tun soll, in Deinem Fall war das nur das Schreiben des Flashs.

OP #7968586
Lesenswert?

Johann L. schrieb:

Da wird der Flash geschrieben. Es fehlt ddas Schreiben der Fuse Section. Soweit ich weiß kann man die Fuses zwar im Programm angeben, aber dadirch landen dien nicht per Magie auf dem Device. Schreiben muss man die Fuses schon, und die liegen eben im normalen Progammspeicher, wie er mit flash:w übertragen wird.

Ah, ok. Danke. Dann hatte ich das Ganze falsch interpretiert. Ich hatte das so verstanden, wenn das im Sourcecode steht, dann wird beim flashen automatisch auch die Fuses gesetzt.

Ich werde das morgen, so wie Du geschrieben hast, mit dem elf-File und dem setzen der Fuses auf dem STK600 mal testen. Nur rein aus Interesse, löst zwar nicht mein Problem. Das es über den Bootloader nicht geht, ist mir schon klar.

Michael B. schrieb:

Wenn du den ATmega2560 runterlötest und in einen richtigen Programmer steckst, kannst du alles machen.

Das war auf dem STK600 ein separater 2560. Der wurde dort über ISP programmiert. Aber wie ich zu Johann geschrieben hatte, habe ich das Ganze falsch verstanden. Bin davon ausgegangen, steht im elf-File, dann werden die mitgesetzt. Aber habe es jetzt verstanden. Dann muss ich die auf dem Board auch über ISP setzen.

: Bearbeitet durch User
OP #7969189
Lesenswert?

So, ich habe das jetzt nochmal getestet. Es ist genau so, wie Johann es beschrieben hat. Nachdem ich die Software compiliert habe, wurden die Fuses mit folgendem Aufruf verändert.

1
avrdude.exe -p atmega2560 -P usb -c stk600     -U flash:w:AVR_Set_Fuses.elf:a -U lfuse:w:AVR_Set_Fuses.elf:a -U hfuse:w:AVR_Set_Fuses.elf:a -U efuse:w:AVR_Set_Fuses.elf:a

Nachdem ich die Fuses mit avrdude und auch microchip-studio ausgelesen hatte, konnte ich feststellen, dass die tatsächlich verändert waren.

Wie ich schon geschrieben hatte, war mein Gedankengang falsch. Ich bin davon ausgegangen, wenn die Änderung der Fuses im Source-Code stehen, dann wird das von der Software, sei es avrdude oder mikrochip-studio, erkannt und sofort beim flashen der Software geändert.

Somit sehe ich in der Vorgehensweise keine grossen Vorteile. Man sieht zwar in der Software, wie die Fuses stehen und kann sich ein separates Setzen der Fuses ersparen, in dem man avrdude mit dem elf-file aufruft. Aber ansonsten bringt das nicht viel. Schon gar nicht ist das möglich, was ich mir eigentlich erhofft hatte. Daher muss ich die Fuses auf dem Board über ISP ändern.

Als ich avrdude beim Setzen der Fuses mit dem hex-File statt dem elf-File aufgerufen hatte, funktionierte das nicht. Avrdude hat mir für die Low- und High-Fuses immer 0x0C geschrieben.

Danke nochmal an alle, die sich hier mit konstruktiven Vorschlägen beteiligt haben. Nur dadurch bin ich darauf gekommen, dass mein Ansatz falsch war und zu dem jetzigen Ergebnis gelangt. Das hilft mir zwar nicht weiter, spielt aber keine Rolle.

Persönliche Seite #7969266
Lesenswert?

Andreas schrieb:

So, ich habe das jetzt nochmal getestet. Es ist genau so, wie Johann es beschrieben hat. Nachdem ich die Software compiliert habe, wurden die Fuses mit folgendem Aufruf verändert.

1
> avrdude.exe -p atmega2560 -P usb -c stk600     -U 
2
> flash:w:AVR_Set_Fuses.elf:a -U lfuse:w:AVR_Set_Fuses.elf:a -U 
3
> hfuse:w:AVR_Set_Fuses.elf:a -U efuse:w:AVR_Set_Fuses.elf:a

Nachdem ich die Fuses mit avrdude und auch microchip-studio ausgelesen hatte, konnte ich feststellen, dass die tatsächlich verändert waren.

Wie ich schon geschrieben hatte, war mein Gedankengang falsch. Ich bin davon ausgegangen, wenn die Änderung der Fuses im Source-Code stehen, dann wird das von der Software, sei es avrdude oder mikrochip-studio, erkannt und sofort beim flashen der Software geändert.

Kontrolle : Automatismus = 1 : 0

Somit sehe ich in der Vorgehensweise keine grossen Vorteile.

Vorteil ist, dass man alles in der Quelle beschreibt und nicht an 2 Stellen, die nicht wirklich was miteinander zu tun haben (Quelle und Makefile).

Allerdings weiß ich nicht, ob Angabe der Fuses in der Quelle immer funktioniert: Es gab mal AVR-LibC Bug-Reports bzgl. invertierter Fuse-Bits in avr/io.h, d.h. eine zu setzende Fuse hatte den Wert 1 anstatt wie üblich 0. Wenn man einen solchen Header erwischt, dann hat man mit dem Ergebnis bestimmt keinen Spaß.

Schon gar nicht ist das möglich, was ich mir eigentlich erhofft hatte.

Evtl. geht das bei neueren Devices wie x-Serie oder AVR-xx, also auf Devices wo die Fuses per LDS / STS zugegriffen werden können?

AVR128DA32:

1
10.2 NVMCTRL Overview
2
The NVM Controller (NVMCTRL) is the interface between the CPU and
3
Nonvolatile Memories (Flash, EEPROM, Signature Row, User Row, and
4
fuses).  These are reprogrammable memory blocks that retain their
5
values when they are not powered.

Aber weiter unten dann:

1
10.3.1.5 Fuses
2
The fuses can be read by the CPU or the UPDI but can only be
3
programmed or cleared by the UPDI.
: Bearbeitet durch User
OP #7969309
Lesenswert?

Oliver S. schrieb:

Da du ja das Microchip-Studio schon am Start hast: Google nach „Production file“.

Danke, aufgrund Deines Hinweises habe ich das nochmal aufgebaut. Ich hatte nicht verstanden, was Du meintest, da ich die Tage über AVR-Studio das elf-File schon übertragen hatte und dabei die Fuses unverändert blieben.

Bei genauerer Betrachtung von microchip-Studio habe das mit dem Production-File gefunden. Wenn ich dort "Fuses" anklicke, dann werden aus dem elf-File die Fuses auch gesetzt. Habe die dann separat nochmal eingelesen, da standen dann die veränderten Werte.

Johann L. schrieb:

Kontrolle : Automatismus = 1 : 0

Ich hatte es ja kontrolliert. Dabei aber gesehen, dass sich an den Fuses nichts geändert hatte :-)

Johann L. schrieb:

Vorteil ist, dass man alles in der Quelle beschreibt und nicht an 2 Stellen, die nicht wirklich was miteinander zu tun haben (Quelle und Makefile).

Ja, das hatte ich verstanden und sehe diesen Vorteil auch. Aber den halte ich für minimal. Zum Setzen der Fuses, sofern überhaupt erforderlich, wird bei mir sowieso separat avrdude bzw. mikrochip-studio aufgerufen.

Johann L. schrieb:

Allerdings weiß ich nicht, ob Angabe der Fuses in der Quelle immer funktioniert: Es gab mal AVR-LibC Bug-Reports bzgl. invertierter Fuse-Bits in avr/io.h, d.h. eine zu setzende Fuse hatte den Wert 1 anstatt wie üblich 0. Wenn man einen solchen Header erwischt, dann hat man mit dem Ergebnis bestimmt keinen Spaß.

Bei mir lief dann keine Software mehr. Dies kann aber auch an meinen Werten gelegen haben. Ich habe das zuerst nicht kontrolliert, ob die Werte, die ich im Sourcecode hatte, mit denen übereinstimmen, wie sie tatsächlich gesetzt wurden. Aber jetzt gerade habe ich das mal auf die Schnelle kontrolliert. So ist es in der Software:

1
__fuse_t __fuse __attribute__((section (".fuse"))) =
2
    {
3
        .low = LFUSE_DEFAULT,
4
        .high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & ~FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),
5
        //.extended = EFUSE_DEFAULT,
6
    .extended = FUSE_BODLEVEL0,
7
    };

LFUSE_DEFAULT wären 10011101 (0x9D), invertiert 01100010 (0x62). Das hat mir mikrochip-Studio auch angezeigt. Das Gleiche bei der extended. FUSE_BODLEVEL0 binär 1, invertiert 0xFE. Das passt also. Bei High-Fuse habe ich mir jetzt nicht die Mühe gemacht, das auch noch zu kontrollieren. Wird schon passen.

Weiter werde ich dem aber auch nicht nachgehen, da das, was ich mir "gedacht" hatte nicht funktioniert bzw. nicht auf dem Wege lösbar ist, wie ich es gehofft hatte.

#7970481
Lesenswert?

Man kann zwar die Fuses nicht per Software verändern, aber wenn es nur um den Vorteiler geht (CKDIV8), der läßt sich im Programm anpassen. Das geht über das CLKPR-Register (Kapitel 10.13.2):

1
    // Make sure all clock division is turned off (8MHz RC clock)
2
    CLKPR = (1 << CLKPCE);
3
    CLKPR = 0x00;
OP #7970726
Lesenswert?

Rick schrieb:

Man kann zwar die Fuses nicht per Software verändern, aber wenn es nur um den Vorteiler geht (CKDIV8), der läßt sich im Programm anpassen. Das geht über das CLKPR-Register (Kapitel 10.13.2):

Danke. Aber darum ging es mir leider nicht. Ich wollte die Brownout-Detection verändern. Aber das klappt leider nicht per Software.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren