Forum: Compiler & IDEs Fuses per Source Code setzen


von Andreas (ah3112)


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

von Jim M. (turboj)


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.

von Oliver S. (oliverso)


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
von Hmmm (hmmm)


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?

von Andreas (ah3112)


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:
> 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
von Johann L. (gjlayde) Benutzerseite


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.

von Michael B. (laberkopp)


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
von Georg M. (g_m)


Lesenswert?

Michael B. schrieb:
> Wenn du den ATmega2560 runterlötest und in einen richtigen Programmer
> steckst

ISP: in-system programming
(also called in-circuit serial programming: ICSP)

von Hmmm (hmmm)


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.

von Andreas (ah3112)


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
von Andreas (ah3112)


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.

von Oliver S. (oliverso)


Lesenswert?

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

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

Oliver

von Johann L. (gjlayde) Benutzerseite


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
von Andreas (ah3112)


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.

von Rick (rick)


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;

von Andreas (ah3112)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.