Forum: Projekte & Code AVR-Bootloader mit Verschlüsselung


von Hagen R. (hagen)


Lesenswert?

Dein Portmon.Log sagt mir folgendes:

- korrekter Verbindungsaufbau
- das erste mal sendet der PC das 0xFD00 Kommando und AVR antwortet auch 
korrekt mit 0xC1 Fehlercode. Dieses Kommand ist das "Keep Alive" 
Kommando das einerseits dazu dient das die PC-Software erkennt das der 
AVR noch errichbar ist und andererseits den Watchdog Timer im AVR 
zurücksetzt. Dh. wenn man UseWDT=1 hat so würde beim Ausbleiben dieses 
Kommandos oder eben andere Kommandos der AVR nach ca. 2 Sekunden einen 
Watchdog RESET durchführen.
- das zweite Keepalive Kommando das gesendet wurde wird aber durch den 
AVR eben nicht mehr beantwortet. Daraufhin trennt die PC-Software 
korrekterweise die Verbindung zum AVR.

Du hast also irgendeine ungewollte Verbindungsunterbrechung gehabt. Das 
das nun an der leicht inkorrekten BootCodeSize gelegen haben soll, die 
ja bei 512 Bytes Bootsection eh keinen Einfluß hätte, kann ich mir eben 
nicht so recht vorstellen. Außnahme wäre halt die Aktivierung der 
UseSpecialXXX Funktionen, nur müsstest du dann eine Kompilierwarnung 
erhalten.

>PS:Kann es daran liegen das ich im Moment den internen Osczilator
>verwende?

Eigentlich nicht, es sei denn du hast UseAutoBaud=0, XTAL zb. auf 8MHz 
aber nicht die CKDIV8 Fuse programmiert. Dh. der AVR läuft real mit 1MHz 
und die konfigurierte Baudrate wäre 8 mal langsammer als real nötig. 
Aber das ist ja bei dir nicht der fall da du einen Connect bekommst.

Am besten ist es meinen Empfehlungen fürs erste zu folgen, hier im 
Thread nachzulesen. Und ich empfehle immer UseAutoBaud=1 und UseWDT=1 zu 
setzen. Mit UseAutoBaud=1 ist der MCU Takt fast irrelevant, falsche 
Fuses oder falsche XTAL Einstellung würden dann nur den 
Verbindungstimeout negativ beeinflussen.

Gruß Hagen

von Totaler (Gast)


Lesenswert?

Hallo Hagen,

danke für die ausführliche Antwort.

>>UseSpecialXXX
ist bei mir deaktiviert

Auf die Antwort von Dir habe ich es nochmals versucht die BootCodeSize
zurückzuändert.

Doch "leider" funktioniert es jetzt trotzdem, d.h. wahrscheinlich hatte 
ich tatsächlich ein anderes Problem und es hat sich zufällig mit
dem ändern der BootCodeSize in wohlgefallen aufgelöst.

Schöne Grüße
Hannes

von Hannes 0. (totaler)


Lesenswert?

Hallo Hagen,

jetzt hätte ich aber noch ein Frage.
Ich habe schon andere Bootloader getestet z.B. den von Peter Dannegger
(Auch sehr gut, nur das Verschlüsseln etc gefällt mir bei Deinem besser)

Damit ich jedoch ohne Reset mittels Bootloader flashen konnte,
mußte ich in meine Applikation eine Routine einbauen,
welche auf RX horchte und beim Empfang von 0xFF durch einen WD einen 
Reset ausführte.
Funktionierte auch einwandfrei.

Jetzt ist nur die Frage, wie funktioniert das bei Dir,
dass Du in den Bootloader kommst während das Programm läuft.
Ich habe zwar die Funktion mit dem WD noch eingebaut, aber die horcht 
auf RX und nicht auf den 1Wire Port PD5 welchen ich verwende.

Ich kann mir die Funktionsweise nicht erklären?!?

Wenn das Programm läuft ist doch der Bootloader komplett ohne Funktion 
oder?

Schöne Grüße
Hannes

von Hannes 0. (totaler)


Lesenswert?

Hallo Hagen,

sorry aber anscheinend brauche ich es, dass ich was in das Forum 
schreibt
damit bei mir entweder der Groschen fällt, oder es einfach funzt ;-)

Hab jetzt doch gefunden warum der autoconnect geht,
anscheinend aktivierst Du den WD im BL und wenn dieser nicht explizit 
von
der Applikation deaktiviert oder bedient wird
erfolgt ein Reset.

Jetzt habe ich am Anfang meiner Applikation einfach den WD deaktiviert 
:-)

Trotzdem schöne Grüße
Hannes

von Andy F. (maulfisch) Benutzerseite


Lesenswert?

Hi Hagen,
hab einen ATMEGA32 mit internen Takt , funkt da der bootloader?
wie muss ich denn den einstellen?

von Stefan R. (stefan09)


Lesenswert?

Andy F. schrieb:

> hab einen ATMEGA32 mit internen Takt , funkt da der bootloader?
Natürlich !

> wie muss ich denn den einstellen?

Was willst du jetzt wissen ? Wie du die Fuses programmieren mußt oder 
welche Einstellungen im Bootloader ?

Bei den Fuses empfehle ich dir das Datenblatt vom Atmega32, und beim 
Bootloader die wirklich ausführliche Anleitung, bzw. die Kommentare im 
Bootloader selbst.
Keine Angst, so schwierig ist das garnicht !Sollte es wieder erwarten 
nicht funktionieren, poste einfach deine Einstellungen nochmal !

Gruß Stefan

von Andy F. (maulfisch) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hab die Fuses wie im Bild eingestellt und die Baudrate auf 2400 gestellt 
und
dann kommt immer der Fehler Cannot setup baudrate to 2400
Den Port hab ich auf AUTO gestellt.
 Wenn der PORT COM1 ist, tut sich nach minuten nichts.
kann das sein weil die baudrate zu größ ist?
denn wenn ich mit dem Mega32 was sende muss beim Hyperterminal 1200baud 
eingestellt sein.

von Andy F. (maulfisch) Benutzerseite


Lesenswert?

Hat jemand schon den Bootloader an einem ATMEGA32 mit internem Takt zum 
Laufen gebracht?

von Andy F. (maulfisch) Benutzerseite


Lesenswert?

Hier der Log vom Programm
hab jetzt ext quarz mit 16Mhz am Mega32
im AVRootloader.asm hab ich bei Clock 16mhz eingestellt
und trotzdem kommt:
06.05.09-16:36:57-125 > Connecting on port COM1...
06.05.09-16:36:57-843 > Error: can not setup baudrate to 19200
06.05.09-16:36:57-906 > Error: can not setup baudrate to 19200
06.05.09-16:36:57-953 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-000 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-062 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-109 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-156 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-218 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-265 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-312 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-359 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-421 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-468 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-515 > Error: can not setup baudrate to 19200
06.05.09-16:36:58-578 > Error: no Device found

von Hagen R. (hagen)


Lesenswert?

Was hast du da für einen COM Port bzw. Betriebsystem ?
Die fehlermeldung ist eindeutig, das Program kann über das Windows API 
beim ausgewählten COM Port die eingstellte Baudrate nicht aktivieren. 
19200 ist Standard und sollte von jedem COM Port unterstützt werden, von 
deiner Hardware aber anscheinend nicht.

Überprüfe deine Hardware, deren Treiber, dein Betriebsystem oder benutze 
eine Baudrate die dein Gerät auch unterstützt.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

@Hannes:

Die PC-Software unterstützt eine ganze Reihe an Möglichkeiten um den 
Bootloader im AVR automatisch zu starten.

1.) Du kannst den RTS Pin der RS232 an den RESET des AVRs oder einen 
anderen Pin legen. Angenommen du legst ihn an den RESET Pin dann kannst 
du in der AVRootloader.ini mit den Einstellungen bei RTSPulse und 
RTSInterval das exakte Timing, den Zeitpunkt, Logiklevel und Periode wie 
die PC-Software die RTS Leitung der RS232, die am RESET liegt, steuert 
einstellen.
Statt RESET Pin ginge natürlich auch ein anderer Pin der dann aber 
innerhalb deiner Anwendung ausgewertet werden muß um in den Bootloader 
zu springen oder per WDT einen RESET zu erzwingen.

2.) Wenn deine Awendung selber den UART benutzt dann kannst du auf 
eigene, definierbare Kommandos zum Starten des Bootloaders reagieren. 
Dazu werden in AVRootloader.ini die Werte in AppCmd und AppCmdResponse 
und Timeouts.AppCmd konfiguriert. Die PC-Software sendet bei einem 
Verbindungsaufbau als aller erstes den Wert=String in AppCmd. Zb. 
AppCmd=startboot/0A/0D sendet den String startboot gefolgt von 
Zeilenumbruch und Linefeed. Sonderzeichen also in der Form / + 2 HEX 
zeichen. Sollte nun in AppCmdResponse ebenfalls was konfiguriert worden 
sein so wartet die PC-Software nach Absenden des AppCmd auf diesen 
AppCmdResponse. Zb. steht in AppCmdResponse=bootstart. Nach senden von 
startboot wird deine Anwendung erstmal den Wert bootstart absenden und 
dann zb. per WDT mit 17ms Timout den Bootloader starten. Es entsteht 
durch den 17ms WDT eine kleine Zeitverzögerung und diese würdest du in 
Timeouts.AppCmd=20 mit 20ms vorgeben. Also nach dem Empfang des 
AppCmdResponse wird die PC-Software erstaml 20 Millisekunden warten 
bevor sie mit dem eigentlichen Verbindungsversuch zum Bootloader 
beginnt.

Steht in AppCmdResponse nichts drinnen so wartet die PC-Software 
logischerweise nicht auf dieses sondern setzt bei der Warteschleife für 
Timeouts.AppCmd fort. Ist dieses auf 0 so wird auch nicht gewartet.

Ich würde bei dieser Methode mit WDT in kürzester Periode arbeiten und 
Timeouts.AppCmd=20 setzen um das Gesamttiming zu verbessern.

Statt in AppCmd mit einem kompletten Komando zu arbeiten könntest du 
auch einfach zb. AppCmd=/55 setzen. Die Software sendet also den Wer 
0x55 ab. Im 1-Wire Modus und ohne eigene UART Software an diesem Pin 
würdest du den PinChange IRQ für diesen Pin benutzen. Innerhalb dessen 
ISR schiebst du in ein Register die Daten rein und wenn dieses Register 
eben 0x55 enthält, oder ähnliche Bitkombinationen, startest du den 
Bootloader. So arbeite ich meistens noch mit der Erweiterung das ein 
parallel laufender Timer diese Variable nach einer Zeit auf 0 
zurücksetzt. Du kannst das natürlich erweitern wie du möchtest.

3.) sobald die PC-Software den COM Port öffnet und solange er geöffnet 
ist wird die DTR Leitung der RS232 auf H Pegel gesetzt. Dies diente 
primär als Mini-Stromversorgung für einen eventuell angeschlossenen 
Pegelwandler, oder Pullup (max. erlaubte Ströme beachten). Auch diesen 
Pin könntest du für diesen Zweck benutzen. Er ist aber nicht per 
Konfiguration im Verhalten einstellbar.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

>Wenn das Programm läuft ist doch der Bootloader komplett ohne Funktion
>oder?

Ja sicher, es läuft ja deine Anwendung. Ergo, wenn aus deiner Anwendung 
heraus der Bootloader gestartet werden soll dann musst du auch in deiner 
Anwendung den Bootloader-Pin überwachen und je nach obiger Methode 
darauf reagieren.

Zusätzlich könntest du auch im AVRootloader.asm über die Einstellung 
UseBootMode=? noch das Event festlegen bei dem der Bootloader 
durchstarten soll. Zb. bei UseBootMode=3 würde der Bootloader nur 
durchgestartet wenn entweder der WDT einen Reset ausgelösst hat oder der 
AVR unprogrammiert ist, also noch keine Anwendung drauf ist oder der 
Bootloader per direktem RJMP/JMP/CALL/RCALL gestartet wurde. Bei allen 
anderen RESETs, wie Brownout, USB, JTAG, OnChipDebug, Ext. RESET, 
Powerup würde der Bootloader sofort die installierte Anwendung starten. 
Somit wartet der Bootloader dann nicht mehr und die Startupzeiten deiner 
Anwendung beträgt diejenige die du über die Fuses eingstellt hast plus 
par MCU Takte (ca. 16 Takte)

Aber Vorsicht, überlege dir dann genau den Programablauf. Wenn deine 
Anwendung zb. den WDT deaktiviert und danach einen Programfehler hat, 
zb. Endlosschleife dann wirst du den Bootloader nicht mehr starten 
können und somit keine neue Anwendung über den Bootloader flashen 
können. Denn der Bootloader reagiert ja nur auf einen WDT Reset oder 
RJMP und beides trifft nicht mehr ein da deine derzeitig installiert 
Anwendung einen Bug hat.


Gruß Hagen

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

Ich kämpfe gerade an zwei Fronten mit deinen Quellen ;-). Zum einen 
machen die DEC Hash Funktionen in einer C++ Lib Probleme und ermittelt 
mit jedem Start einen anderen Hash bei gleichen Ausgangswerten und 
Konfigurationen und zum anderen mit deinem Bootloader. Zum zweiten mal 
ein wenig ausführlicher:

Ich habe eine eigene Client Anwendung geschrieben, welche sich mit dem 
AVR über ein eigenes Protokoll unterhält. Dieses enthält ein Reset über 
den WDT um in deinen Bootloader zu kommen. Dieser hat 3 gesetzt, also 
wartet er auch brav nach dem vom WDT ausgelösten Reset. Leider gibt es 
Verzögerungen beim Schliessen des COM Ports in meinem Client, 
instanziieren der Interface Klasse und anstossen des Verbindungsaufbaus 
über dein Interface. Dadurch klappt das Update nur in max 1 von 40 
Fällen. Von daher würde ich es gerne so umstellen, dass ich dein 
Interface damit beauftrage anhand meines Protokolls den Reset auszulösen 
und damit alles von dem Interface aus anstossen. Von daher wäre nun die 
Frage: Die in 2. genannten INI Einstellungen, kann ich die auch bei 
deinem Interface angeben? Wenn ja: wo?

Ansonsten wollte ich mal fragen, ob es möglich wäre das Interface vllt. 
auf IStream oder ähnliches zu erweitern, so dass ich nicht gezwungen bin 
die Firmware auf den Rechner abzulegen für die Übergabe an dein 
Interface? Ich lade die Firmware in meinem Client runter bzw. der Client 
bringt die letzte Firmware mit und somit würde ich die gerne "intern" 
weitergeben ohne über externe (ausserhalb der App) Speicher zu gehen.

Und ansonsten nochmal dickes Lob an deine ganzen Projekte und Arbeiten: 
die sind wirklich Klasse und von daher nochmals ein dickes Lob & Danke, 
vor allem da du sie auch allen zur Verfügung stellst.

von Robert M. (bandgap)


Lesenswert?

Hallo Hagen,

bitte entschuldige das ich so spät antworte.
(ich hatte das Verbindungsproblem)
Also ich habe jetzt in der PC-Software den Auto-Modus deaktiviert und 
wie von dir empfohlen den COM-Port direkt angegeben.
Einstellungen komplett so wie von dir empfohlen - und es funktioniert 
prima.
Wahrscheinlich gab es Timingprobleme des Rechner beim durchscannen der 
Ports.(COM3:USB-Serial-Port)

Vielen Dank für deine Hilfe und die Zeit die du hier investierst.

Grüße
bandgap

von Andy F. (maulfisch) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Was hast du da für einen COM Port bzw. Betriebsystem ?

hab Xp sp3

von Hagen R. (hagen)


Lesenswert?

@Andy F. meine Frage war eher rethorischer Art, also ein Hinweis für 
dich das dort der Fehler nach meiner Meinung zu suchen ist. Solange der 
Fehler kommt das er die Baudrate nicht einstellen kann (ein Fehler der 
vom Treiber/OS kommt und nicht von meiner Software) wird meine Software 
nicht in der lage sein den COM Port zu öffnen. Dh. es kommt im 
Programablauf noch nichtmal zu den ersten Verbindungsaufbauschritten da 
schon das Öffnen und Initialisieren des COM Port durch diesen Fehler 
abgebrochen wird.
Sogesehen brauchen wir erst hier weiter machen wenn du dieses Problem 
gelösst hast. Hast du schon mal in den Gerätemanager geschaut und 
verifiziert das das System den COM Port auch als aktiv anzeigt ?

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

@Robert,

>Wahrscheinlich gab es Timingprobleme des Rechner beim durchscannen der
>Ports.(COM3:USB-Serial-Port)

das war eben auch meine Vermutung. Timingprobleme wird es immer geben, 
genauer gesagt sind es Synchronisationsprobleme. Die Anforderungen sind 
halt dergestalt das ein Kompromiß aus Baudrate, MCU Takt, Wartezeit im 
Bootloader,  Timing im HW-Kommunikationskanal, Verzögerungen in den 
Treiber dieser Hardware, Timnings/Prioritäten im Tasksheduller des OS 
und am Ende dieser Kette meine Software und das benutze Protokoll für 
den Verbindungsaufbau. Sobald sich eine dieser Variablen ungünstig 
verändert so entsteht der Fall das theoretisch ohne Probleme ein Connect 
möglich wäre aber durch ungünstige sich überschneidende Intervale es 
nicht zum richtigen Zeitpunkt zu einem Connect kommt. Es gibt nur eine 
Antwort des Programmieres auf solche Probleme: entweder Umstellung auf 
Ereignisbasierte Systeme, dh. wir lösen explizit und exakt ein Eregnis 
aus das deterministisch exakt zu einer reproduzierbaren Reaktion führt: 
in diesem Falle Bootoader startet, oder wie senden quasi mit Dauerfeuer 
unseren Loginversuch bis der AVR antwortet. Letzeres ist aber unmöglich 
wenn man eine ganze Reihe von COM Ports scannen möchte, da es dann eine 
Frage der zeitlichen Dauer des Scannings wird. Naja, lange Rede kurze 
Lösung: im AUTO Modus in der AVRootloader.ini bei solchen Problemen den 
ConnectTrials Wert erhöhen, oder gleich die richtige Schnittstelle 
auswählen.
Interesanterweise sind es immer die blöden USB-RS232, oder TCP/IP-RS232 
Wandler die diese Probleme machen. Bei Benutzung der nach MS absolut 
veralteten RS232 gehts bei mir immer ohne Probleme, egal welche 
Baudrate, Konfiguration etc.pp.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

@Thomas:

vom Aufwand her und der Stabilität empfehle ich dir den RESET durch 
meine PC-Software/DLL auslösen zu lassen. Die PC-Software lädt die 
Einstellungen dazu aus der AVRootloader.ini Datei und übergibt sie dem 
Interface als Parameter. Dh. für dich du kannst diese Parameter in 
deiner Konfiguration speichern wie du es möchtest, lädst diese selber 
und übergibts sie dem AVRootloader Objekt.

1.) dein Application Interface/Objekt alloziert bei OpenCOM() ein 
Interface auf die Kommunikationsschnittstelle. Dieses Interface muß zb. 
de Baudrate schon korrekt eingestellt bekommen haben durch deine 
Anwendung. Gleiches gilt für die anderen Parameter dieser 
Kommunikationsschnittstelle, eg. COM Port.
2.) bei den jeeiligen Aktionen die nun das AVRootloader Interface 
ausführen soll fragt es bei deinem Application Interface die fehlenden 
Parameter ab.

Siehe in AVRootIntf.pas die Dekalration von IApplication. Alle .GetXXX 
Methoden sind exakt diese Abfrage Methoden von Parametern. Die findest 
dort auch die Methoden .GetTimeouts um alle Timeouts aus der Sektion 
[Timeouts] der INI Datei an den AVRootloader zurückzugeben, oder die 
Methoden .GetAppCmd und .GetAppCmdResponse um die Kommandostring für 
deine installierte Anwendung auf dem AVR um in den Botloader zu kommen, 
abzufragen.

Der einzige Wermutstropfen bei der Sache ist die Festlegung auf eine 
jeweilige Baudrate. Deine AVR Anwendung läuft mit einer vorgegebenen 
Baudrate und diese muß auch für den Bootloader benutzt werden.

Ein Einbauen der IStream Schnittstelle halte ich für möglich aber im 
Sinne von zeitlichen Aufwand in Relation zum Nutzen für mich und andere 
für unökonomisch. Kurz gesagt: wenn dein Preis den du zahlst hoch genug 
ist baue ich die den Bootloader so um das du damit zum Mond fliegen 
kannst, aber das lohnt sich nicht. Statt einem IStream ist es ja jetzt 
so das du eine HEX Datei zur Verfügung stellen musst ohne Änderungen am 
jetzigen System. Damit geht die Verschlüsselung und alles andere.

Möchtest du dich nicht auf die schon fertige Umsetzung mit 
AppCmd/AppCmdResponse und den RTS Geschichten verlassen dann besteht 
durchaus auch die Möglichkeit das du über mein ICOM Interface, also 
AVRootloader.COM: ICOM selber auf Lowlevel Ebene deine Daten für deine 
AVR Anwendung sendest. Du hast alle Funktionen in ICOM die nötig sind um 
über zb. die RS232 Daten zu senden und zu empfangen. Es spricht also 
nichts dagegen das deine Applikation gemsicht mit AVRootoader über die 
gleiche geöffnete ICOM Schnittstelle mit dem AVR kommunizieren. 
Desweiteren enthält das AVRotloader Interface ein SubInterface mit Namen 
.Command: ICommandSet. Dieses impelemtiert die 
Bootloader-Protokoll-Kommandos. Auch diese kannst du benutzen um jedes 
einzelene Bootloader Kommando auszuführen statt sich auf die HighLevel 
Methoden wie .Program() .Erase() usw. verlassen zu müssen.

Und finally könntest du ein eigenes Kommunikationobjekt benutzen das nur 
die ICOM Schnittstelle implementieren müsste. Somit kannst du quasi 
deinen eigene Zwischenschicht bauen damit der AVRootloader zb. auf den 
LPT oder andere Kommunikationshardware Zugriff bekommt. Bei 
IApplication.OpenCommunication(): ICOM würdest du diese, deine 
Implementierung der Schnittstelle zum neuen Gerät dem AVRootloader 
mitteilen.

Defakto hast du also in AVRootIntf.pas alles was du benötigst um meine 
PC-Software fast 1 zu 1 nachbauen zu können (fast:).

Die AppCmd/AppCmdresponse Geschichten habe ich hier im Thread erst vor 
kurzem ausführlich beschrieben.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Für all diejenigen die nicht den komplexen Weg über meine Interfaces und 
die DLL gehen wollen oder können gibt es auch noch den Weg über mit 
Übergabe von parametern an meine AVRootloader.exe das Program zu 
steuern. Nachzulesen hier im Thread und in der AVRootloader.txt Datei.

Mit der Einschränkung der weniger flexiblen Einstellungsmöglichkeit kann 
man über diese Paramater im Grunde auch alles machen.

Gruß Hagen

von Thilo M. (Gast)


Angehängte Dateien:

Lesenswert?

@ Hagen Re:

Ich hab' jetzt nicht den ganzen langen Thread durchforstet, daher frag' 
ich dich einfach:
entweder habe ich Tomaten auf den Augen oder ich check's nicht, aber 
dieselbe Einstellung wie auf dem Bild funktioniert auf mehreren mega644P 
problemlos, '.inc' - File vom mega32 aktiviert (644 deaktiviert) läuft 
nicht auf dem mega32 (16MHz) (siehe Protokoll). Benutzt wird RS232 mit 
max232, µC und Verbindung ist OK.

Kannst du mir sagen was ich übersehen habe?

von Thomas K. (muetze1)


Lesenswert?

Was mir als erstes auffällt: Die BootCodeSize unterscheidet sich nicht 
um 2 Bytes.

Diese sollte auf 0 gesetzt werden, dann erneut erstellen. Danach den 
[used] Eintrag des Code Segmentes dort eintragen. Danach erneut 
erstellen, dann sit der Eintrag unter [Used] zwar 2 Bytes grösser, aber 
das sollte man ignorieren. Somit sollte es eigentlich eine Differenz 
geben von 2 Bytes.

@Hagen: Das Update klappt nun alles, ich hatte einfach noch eine alte 
Version und dadurch gab es die GetAppCmd, etc noch nicht in 
IApplication. Dadurch kam es überhaupt zu der Frage. Wegen den DEC 
Sachen mache ich einen Thread in der DP.net auf nächste Woche. Danke 
nochmals!

von Thomas K. (muetze1)


Lesenswert?

Ich habe doch noch eine Frage: Ich habe nun das Versioning mit 
eingeschaltet. Ich kann im AVR Code die App Version ermitteln, das 
zeigst du ja in dem Beispielcode. Genauso über die Interfaces auf PC 
Seite, aber ich habe noch nicht rausgefunden: wo wird die App Version 
festgelegt und wo kann diese ändern? Muss ich in meinem "user Code" 
einen bestimmten Offset mit einem uint32_t freihalten oder wird es im 
BootLoader gespeichert? Wenn letzteres: wenn ich meine Update eigentlich 
immer ohne BootLoader ausliefere, wie kann diesen dann aktualisieren? 
Oder kann ich dies vom User Code aus im AVR?

von Hagen R. (hagen)


Lesenswert?

Im AVR wird sie 4/6 bytes vor BootStart gespeichert, also im FLASH der 
Anwendung logischer Weise und das in den letzten nutzbaren Bytes des 
FLASHs. Man kann diese also auch mit einem hardcoded Addresszugiff in 
der eigenen Anwednung auslesen (Adresse wird in der PC-Software bei den 
Infos angezeigt). 4 Bytes vor Bootstart wenn der AVR eine eigene 
Bootsection unterstützt, 6 bytes vor Bootstart wenn wir einen ATTiny oä. 
ohne Bootsection benutzen. 6 Bytes weil ja noch der rjmp Main mit rein 
muß. Die AppVersion wird also genauso wie bei den Tinys die Vektoren 
durch die PC-Software beim Programmieren eines neuen HEX Files in dieses 
HEX File live rein gepatcht. Man ändert die AppVersion also nicht auf 
direkte Weise sondern beim flashen einer neuen Anwendung. Irgendwie auch 
logsich da sich diese Version ja auf eine Anwendung, eh. Version eines 
HEXs bezieht.
Sollten diese 4/6 Bytes im HEX File nicht alle auf 0xFF stehen gibt es 
eine Fehlermeldung das die PC-Software nicht patchen konnte. Logisch da 
sie davon ausgehen muß das diese Bytes dann von der Anwendung benutzt 
werden und ergo die Anwendung zu groß für den zur Verfügung stehenden 
FLASH ist.

Ist die Verschlüsselung aktiviert so gelten auch die 4 Checkboxen 
welchen Teil der AppVersion der Bootloader überprüfen soll. Dh. eine 
Überprüfung der aktuellen Version mit den Teilen der neuen Version und 
ein eventuelles Unterbinden des Updates funktioniert nur mit der 
Verschlüsselung. Auch das ist im Grunde logisch da nur so eine 
kryptographische Sicherheit und damit unmanipulierbare 
Versionsnummernprüfung überhaupt erst möglich ist. Also ohne 
Verschlüsselung ist die AppVersion bei einem Update auf einen beliebigen 
Wert einstellbar, mit Verschlüsselung überprüft der Bootloader erstmal 
die Teile der neuen Version die man zur Prüfung per Checkboxen aktivert 
hat. Diese müssen dann gleich oder höher der aktuell installierten 
Version sein oder der AVR lässt kein Update zu.

In den Interfaces gibt es die Methode IApplication.GetAppVersion(Masked: 
Bool): Integer. Diese Funktion sollte die neue Version als 4 Bytes 
Integer zurück geben. Wenn Masked = TRUE ist dann die gleiche neue 
Version aber diejenigen Bytes die nicht überprüft werden sollen müssen 
auf 0xFF gesetzt werden. Dh. dann auch das jedes der 4 Bytes einen 
Wertebereich von 0 bis 254 hat und der Wert 255 reserviert ist. SO 
ähnlich arbeiten unsere IP Adressen.
Wenn also ein ACY File mit .DoCompile() oder .DoProgram() erzegt werden 
soll so wird auch .GetAppVersion() zweimalig aufgerufen. Einmal 
Masked=FALSE um das HEX File zu patchen und einmal Masked=TRUE um die zu 
überprüfende Versionsnummer in den ersten verschlüsselten 
Initialisierungdatenblock zu kodieren. Beide Versionsnumer, also die 
schlußendliche im HEX File hineingepatchte und die teilweise zur 
Überprüfung im Initialisierungblock sind verschlüsselt und können damit 
im fertigen ACY File nicht manipuliert werden. Die aus dem 
Initialisierungblock, der bei Verschlüsselung immer als erstes an den 
AVR gesendet werden muß, wird nun mit der schon installierten überprüft. 
Schlägt dies fehl akzeptiert der AVR keine weiteren Datenpackete und 
unterbindet so das Programmieren des FLASHs. Hat ein Angreifer keinen 
Zugriff auf die Register des AVRs so kann er nur noch per Brute Force 
versuchen das 128 Bit Passwort zu knacken. Da dies aber weitaus weniger 
wahrscheinlich zum Erfolg führt als den AVR als Hardware, also seine 
Fuses/Die anzugreifen, ist dies relativ sehr sicher. Mehr ist 
kryptographisch als Schutz nicht rauszuholen aus den AVRs, in Software.
Dieses Initialisierungpacket ist 16 oder 24 Bytes groß. 24 Bytes wenn 
UseVersionng aktiviert. Die ersten 8 Bytes sind reine Zufallsbytes und 
randomisieren somit wie ein Initvector die komplette Verschlüsselung auf 
Grund der Verknüpfung aller Datenblöcke des HEX File über ein 
Feedbackregister intern. Dh. wird das gleiche HEX File mit gleichen 
Enistellungen (Passwort etc.pp) merhmals verschlüsselt so wird der 
Output sich immer komplett unterscheiden. Dieser zufällige IV stellt 
also sicher das eine ganze Reihe von kryptologischen Angriffen effektiv 
unterbunden werden, zb. Austausch von verschlüsselten Datenblocken, 
Manipulation einzelner Bits im Datenblock, Choosen Plain Text Angriffe 
um das Passwort in Erfahrung zu bringen, Differentielle Krypoanalyse 
usw. usf.
In den letzten 8 Bytes dieses Initialisierungsblockes stehen 4 Bytes die 
aktuelle Versionsnummer des Bootloaders, der AVR Typ also alles was bei 
BootInfo steht. An hand dieser Werte überprüft die Entschlüsselung ob 
die nachfolgenden Daten exakt für diesen Bootloader und AVR bestimmt 
sind. Die letzten 4 Bytes sinde eine Signatur die identisch zu den 
ersten 4 Bytes des gewählten Passwortes sein müssen, nach der 
Entschlüsselung. Somit eine geheime Signatur mit unbekannten und nicht 
festen Inhalt da sie vom Passwort direkt abhängig ist und gleichermaßen 
eine 32 Bit Prüfsumme. Da der XTEA Algorithmus eine 64 Bit breite 
Blockverschlüsselung ist heist die das sie in meinem 
Doppel-CBC-Feedback-Modus wie eine 64 Bit sichere Prüfsummenfunktion 
arbeitet. Die Daten, also alle Datenblöcke einer Datenübertragung sind 
am Ende mit einem solchen 8 Bytes Zusatzdatenblockes abgesichert. Ergo 
benutzt die Verschlüsselung eine Prüfsumme vergleichbar zu einer 64 Bit 
breiten CRC die mit einer Wahrscheinlichkeit von 32Bit sicher ene 
Aussage treffen kann ob die vorherigen Daten korrekt und unmanipuliert 
übertragen wurden. Bei den Datenpacketen zur Programmierung des FLASH 
steht statt der 4 Bytes BootInfo in diesem Datenblock dann eine 24 Bit 
Adresse drinnen. Das ist diejenige FLASH/EEPROM Adresse an den die 
vorher empfangenen Daten, und die im SRAM Buffer entschlüsselt worden 
sind, programmiert werden sollen. Dh. auch die Addressinformation wird 
durch das kryptographische Protokoll geschützt und nicht manipulierbar 
gesichert. Es hat den Vorteil das man Datenblöcke mit sich 
wiederholbaren Muster nur einmal übertragen kann und in den eigentlichen 
FLASH/EEPROM Programmierroutinen mehrmals linear hintereinander ab einer 
Startadresse programmieren kann. Möchte man zb. 512 Bytes mit dem Inhalt 
0x01 0x02 programmieren so überträgt man effektiv nur 2 Bytes, nämlich 
0x01 und 0x02, plus die 3 Bytes Startadresse. Dann ruft man die 
Programmfunktion für den EEPROM/FLASH einmalig auf und teilt ihr mit das 
sie 256 mal diese 2 Bytes ab der Addresse programmieren soll. Teilweise 
wird dieses Feature auch schon in der PC-Software benutzt, als Art 
Komprimierung und Beschleunigung der Datenübertragung.

Mit IAVRootloader.Device.AppVersion: Integer, fragt man vom aktuell 
verbundenen bzw. zu letzt verbundenem AVR die Versionsnummer ab. Ist 
diese 0xFFFFFFFF und .Device.Supports & sfVersioning <> 0 dann wurde im 
AVR noch nichts installiert.

Soweit zur Versonsnummer, der Verschlüsselung, wie und warum es so 
funktioniert.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

@Thilo, folge mal Thomas seiner Vermutung, das ist auch meine.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Übrigens, die oben beschriebene Art der Versionsüberprüfung kann auch 
angewendet werden wenn man nur den EEPROM per sicheren ACY updaten 
möchte. Dh. ein kompiliertes und verschlüsseltes ACY File das nur EEPROM 
Daten enhält kann über die Versionsprüfung auf einen AVR serialisiert 
werden. Nur AVR mit der gleichen oder geringeren Versionsnummer der 
Anwednung akzeptieren dann diese neuen EEPROM Daten. Das war auch einer 
der Gründe es so zu machen wie es jetzt ist.

Ach und nochwas: das interne Feedback Register wird innerhalb der 
merhfachen Übertragung verschiedener nachfolgender Datenpackte nicht 
zurückgesetzt. Dh. auch wenn die PC-Software unser HEX File in kleinere 
Packate a maximal SRAM Buffer der zur Verfügng steht zerlegt und dabei 
jeden mit einem 8 Bytes Prüfsummenblock absichert, so besteht für einen 
Angreifer keine Möglichkeit durch Austauschen dieser 
Kommunikationsbedingten Zerlegung die Packete auszutauschen oder um zu 
sortieren. Dh. sie müssen damit sie korrekt entschlüsselbar sind in der 
exakten Reihenfolge gesendet werden.

Gruß Hagen

von Thilo M. (Gast)


Lesenswert?

Hagen Re schrieb:
> @Thilo, folge mal Thomas seiner Vermutung, das ist auch meine.
>
> Gruß Hagen

Habe ich getestet. Keine Änderung.
Auch ein vorsichtshalber neuer µC brachte keine Änderung.
Wie gesagt: Austausch gegen einen m644P, Codegröße und .inc angepasst, 
funktioniert. Mega32 nicht.

von Hagen R. (hagen)


Lesenswert?

@Thilo:

mein Auftraggeber sagt immer: mache nicht deine Probleme zu meinen ;)
Du musst irgendwo einen Fehler gemacht haben. Gehe also alles nochmal 
wie hier irgendwo im Thread beschrieben step by step durch.
Letztens erst trat der Fall auf das die RX/TX Pin/Port Einstellungen 
nicht mit den benutzen Pins übereinstimte, hast du das überprüft ? Fuses 
richtig ? Korrektes Include ? Mal in AVRootloader.ini [Timeouts] Options 
= 2 gesetzt und den Inhalt des Protokollfensters hier gepostet, nach 
einem Verbindungsversuch ?
Arbeitest du mit internem RC Oszillator oder externen Quarz ? Wenn 
extern schwingt dieser ? Fuses richtig ?

Gruß Hagen

von Thilo M. (Gast)


Lesenswert?

>mein Auftraggeber sagt immer: mache nicht deine Probleme zu meinen ;)

Hast ja Recht ... ;)

Ich kann's mir eben nicht erklären.
Ich nehme den m32 aus der Schaltung, stecke den m644 'rein, .inc und 
Codegröße angepasst, sonst alles gleich => läuft problemlos.

Protokollfenster, Einstellungen und Fuses habe ich weiter oben als .jpeg 
gepostet.

Danke für die Mühe! ;)

Edit: ich werde mal die Schaltung auf m644P aufrüsten.

von Hagen R. (hagen)


Lesenswert?

Jetz habe ich das erstmal gesehen ! Der Output ist also von deinem M32. 
Er programmiert deinen M32 bricht dann aber beim Verify mit einem 
Lesefehler, eg. Timeout ab. Ändere mal in AVRootloader.ini [Timeouts] 
Buffer= auf einen höheren Wert ab.

Dh. im Grunde läuft bei dir alles korrekt bis einschließlich Connect. 
Dann gibts einen Timeout Fehler der nicht auftreten sollte.

Setze mal [Timeouts] Options=2 und dann nochmal das Protokoll hier 
posten. Diese Option aktiviert den Debugmodus aus dem ich dann im 
Protokoll mehr heraus lesen kann.

Gruß Hagen

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

Das Problem mit dem Verify Timeout hatte ich auch, ich habe aber nun 
einfach das Verify abgeschaltet und mache dies nun auch nicht mehr. Aber 
ich habe noch ein Problem und zwei Fragen:

1. DoConnect() hat einen Working Parameter - was bedeutet dieser? Du 
bist in dem Thread nicht darauf eingegangen und hast ihn in deinen 
Beispielen mal auf true gesetzt und mal auf den default (false).

2. ProcessMessages hat nun ja einen boolschen Rückgabewert. Wenn ich das 
richtig sehe, dann kann ich dort true zurück geben um die aktuelle 
Aktion abzubrechen und false wenn alles wie gehabt weiter werkeln soll. 
Richtig?

3. Ich habe noch das Problem, dass er mir beim DoConnect() eine 
Exception aus deiner DLL wirft ohne Message (ist leer). Diese wird 
danach auch über Output gemeldet mit dem Code für einen Fehler 
(ocError), aber weiterhin ist Msg leer. Danach ruft die DLL wieder 
OpenCommunication auf, was dann natürlich schief geht, da der Port schon 
noch von dir geöffnet ist (Access Denied, Code 5 von Windows zum 
CreateFile() des COM Ports). Und dies dreht sich dann endlos, angefangen 
mit der Exception aus DoConnect ohne Message.
Mit jedem Versuch setzt die DLL trotzdem erfolgreich mein App Command ab 
zum resetieren des AVR, was dieser auch richtig macht - also irgendwer 
in deiner DLL weiss noch um den offenen COM Port ;-).
Das Programm von dir macht es ohne Probleme, aber braucht mehrere 
Anläufe zum absetzen des App Commands, vllt. gibt es intern auch diese 
Probleme?

Alle o.g. Probleme treten nicht auf, wenn ich mich direkt verbinde und 
Update, also ohne App Command, was z.b. direkt nach brennen des 
Bootloaders der Fall ist.

Und eine letzte Frage, rein informativ: woher unterscheidest du bei der 
AppCommand Funktion ob ich die Daten die du senden musst nun 2 Byte oder 
1 Byte pro Zeichen sind?

Nachtrag: Wenn ich, wie von dir öfters beschrieben, in deinem Programm 
die Options auf 2 setze, dann schafft er es nicht mehr, sich zu 
verbinden. Die RxD Leitund des MC flasht die ganze Zeit, er selber 
resetet auch ordentlich (AppCommand klappt) und bleibt im BootLoader, 
aber er bekommt keine Verbindung zu stande. Bei Options=0 schafft er es, 
er flasht vllt. erstmal eine Minute rum mit der RxD, aber er schafft 
dann aber eine Kommunikation aufzubauen.

Ich kann bei Interesse dir auch alles mal zippen, von der Config deines 
Progs, bis zu meiner Software, Client etc. Zum selbst ausprobieren 
sollte ein beliebiger (bei mir ATMega 8) AVR 8 Bit reichen mit serieller 
Verbindung.

von Thilo M. (Gast)


Lesenswert?

Hallo Hagen,

hier das Protokoll mit Buffer=5 und Options=2:

------------------------------------------------------
11.05.09-17:35:04-375 > Connecting on port COM1...
11.05.09-17:35:38-671 > Device connected
11.05.09-17:35:38-671 > Program...
11.05.09-17:35:38-671 > execute compiled data
11.05.09-17:35:38-671 > 1.0.0.0
11.05.09-17:35:38-671 > selected options in compiled file:
11.05.09-17:35:38-687 > - programming FLASH
11.05.09-17:35:38-687 > - erase FLASH during programming
11.05.09-17:35:40-843 > Cmd.SetBuffer.ReadByte() ICOM: read error.
11.05.09-17:35:40-906 > Device disconnected
------------------------------------------------------
>Dh. im Grunde läuft bei dir alles korrekt bis einschließlich Connect.
Richtig. Connect funktioniert prima.

von Hagen R. (hagen)


Lesenswert?

Ok, Fehler zu erst:

Option=1 um den Debug Modus zu aktivieren
Option=2 um den alten Connect zu aktivieren
Option=3 für beides.

@Thilo: also Option auf 1 setzen und nicht 2. Da bin ich durcheinander 
gekommen.

Der alte Connect bis Version 4 glaube ich, benutzt nach dem Senden des 
BootSign keine 16 Bit CRC über diese BootSign. Beim neuen Connect, also 
diese Option nicht gesetzt, wird über die BootSign noch eine CRC 
berechnet und gesendet. Der neue Bootloader erwartet also diese CRC und 
akzeptiert nur mit gültiger CRC einen Connect Versuch. Der alte 
Bootloader kann auch mit dem neuen Verfahren zurecht kommen, wird aber 
in der nachfolgenden Command FSM am Anfang aus dem Tritt geraten. Wenn 
man also mit der neusten PC-Software eine Verbindung zu einem älteren 
Bootloader machen möchte dann empfehle ich diese Option auf 2 zu setzen. 
Unter Umständen geht das aber auch ohne diese Option.

@Thomas: sieht so aus als ob dein RS232 Timing sehr ungünstig ist, neben 
den anderen oben besprochenen Dingen.

>1. DoConnect() hat einen Working Parameter - was bedeutet dieser?

Es gibt zwei Grundmodis, moConnected und moWorking. moConnected heist 
einfach manuell verbunden und muß auch manuell mit DoDisconnect() 
getrennt werden. Der Unterschied zwischen moConnected und moWorkng liegt 
in deiner Callback Methode IApplication.Changed begründet. Ist 
IAVRootloader.Mode = moConected dann solltest du andere Bedienelemente 
enablen als im moWorking Modus. Als Beispiel hättest du einen Program 
Button der in der Callback Methode .Changed disabled werden sollte wenn 
der .Mode auf moWorking steht.

Mit dem Bool Parameter in .DoConnect() teilst du also im Vorhinein mit 
ob du nur eine Verbindung aufbauen möchtest oder ob du eine Verbindung 
aufbauen möchtest und gleich danach irgendeine Aktion durchführen 
möchtest, also DoProgram() usw.

.DoConnect() und .DoDisconnect() Aufrufe können verschachtelt sein, als 
2 DoConnect()s benötigen 2 DoDisconnect()s. Wird eine Methode wie 
.DoProgram() aufgerufen ohne vorher connected zu sein so wird intern 
autom. DoConnect() aufgerufen und nach Beendigung DoDisconnect().

>2. ProcessMessages hat nun ja einen boolschen Rückgabewert.

Korrekt. Alle deine Aufrufe von Methoden der Interfaces sollten zu 
äußerst mit einem try except Schutzblock gekapselt sein. Wird in 
.ProcessMessages TRUE zurück gegeben dann wird intern eine EAbort 
Exception ausgelösst auf die du dann in deinem äußersten Schutzblock 
reagieren solltest. Exception sind Außnahmebedingungen und die meisten 
Programmierer verstehen ihr Konzept gründlich falsch. Es ist keine reine 
Fehlerbehandlung sondern eben Ausnahme Bedingungen und was als Ausnahme 
gilt ist reine Definitionssache. Sogesehen benutze ich die Exceptions 
nicht nur als Fehlermeldungen sondern bewusst auch zur sauberen 
Terminierung von Aktionen. Zb. eben das Abbrechen einer Aktion durch den 
Benutzer. Das funktioniert solange gut wie man als programmeirer die zu 
äußerst liegenden Codeblöcke auch mit try except Schutzblöcken sichert.

>3. Ich habe noch das Problem, dass er mir beim DoConnect() eine
>Exception aus deiner DLL wirft ohne Message (ist leer).

Die .OpenCommunication() Methode hat einen Parameter Index. 
.OpenCommuication() wird bei einem Connect Versuch in .DoConnect() quasi 
als Callback aufgerufen. IAVRootloader ruft .OpenCommunication() mit dem 
Index beginnend bei 0 auf. Kehrt .OpenCommunication() mit nil zu 
IAVRootloder zurück bricht dieser den Connect Versuch ab. Bricht 
.OpenComunication() mit einer Exception EAbort ab so wird IAVRootloader 
den Index um +1 inkrementeren und wider .OpenCommunication() nun mit 
Index =1 aufrufen. Somit kann über .OpenCommunication() eine nicht so 
ganz offensichtliche "Schleife" aufgebaut werden und der ansich für dich 
nicht frei zugreifbare Connect im IAVRootloader gesteuert werden. 
Letzendlich dient es dazu im AUTO Modus, einem Scan der COM Ports, alle 
COM Ports der Reihe nach ihrem Index durch zu iterieren bis ein gültiger 
Connect zustande kommt. Dieses Vorgehen habe ich nachträglich als 
Feature implementiert und deshalb die nicht ganz so offensichtliche 
Arbeitsweise. Hier mal mein Sourcecode der .OpenCommuniation() Methode 
in meiner PC-Software
1
function TMainForm.OpenCommunication(Index: Integer): ICOM;
2
var
3
  PortName: String;
4
begin
5
  Result := nil;
6
  if AnsiCompareText(Port, 'AUTO') = 0 then
7
  begin
8
    if Index >= CBPort.Items.Count then
9
    begin
10
      Output('Error: no Device found', ocError);
11
      Exit;
12
    end;
13
    PortName := CBPort.Items[Index];
14
    try
15
      Result := OpenCOM('\\.\' + PortName, Self);
16
    except
17
      Output(Format('Info: can not open port %s', [PortName]), ocInfo);
18
      raise EAbort.Create('');
19
    end;
20
  end else
21
  begin
22
    if Index > 1 then Exit;
23
    PortName := Port;
24
    try
25
      Result := OpenCOM('\\.\' + PortName, Self);
26
    except
27
      raise Exception.CreateFmt('Error: can not open port %s', [PortName]);
28
    end;
29
  end;
30
  try
31
    Result.SetParams(Baudrate);
32
  except
33
    raise Exception.CreateFmt('Error: can not setup baudrate to %d', [Baudrate]);
34
  end;
35
  Output('Connecting on port ' + PortName + '...', ocInfo);
36
end;

Es ist ja so das das IAVRootloader Interface keinerlei Zugriff auf den 
eigentlichen COM Port über das ICOM Interface bekommt. IAVRootloader 
kann nur lesen und schreiben in dieses Interface/Port aber eben nicht 
festlegen welchen Port, welche Hardware oder Einstellungen möglich sind. 
Diese Aufgaben sind dem eigenen IApplication Interface vorbehalten. Dies 
ist eine  restriktive Form der Softwareprogrammierung, die konsequente 
Modularisierung, Aufgabenteilung und Protektisierung um unabsichtliche 
logische Fehler durch den Programmierer zu verhindern. Leider führt dies 
dazu das manchesmal, wenn zu regide angewendet, das spätere 
konzeptionelle Richtungsänderungen schwerer ohne größere Änderungen 
umsetzbar sind.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

>Ich kann bei Interesse dir auch alles mal zippen, von der Config deines
>Progs, bis zu meiner Software, Client etc. Zum selbst ausprobieren
>sollte ein beliebiger (bei mir ATMega 8) AVR 8 Bit reichen mit serieller
>Verbindung.

Danke für dieses nette Angebot, und ich wäre wirklich interessiert wenn 
da nicht das Zeitproblem ist. Im Grunde habe ich ja selber schon alles 
mal verwendet und weiß also wie es funktioniert ;-) Wenn du sichergehen 
möchtest das ich mal über deine Arbeit drüber schaue um dir 
Verbesserungen vorschlagen zu können dann würde ich das natürlich auch 
machen.


>Und eine letzte Frage, rein informativ: woher unterscheidest du bei der
>AppCommand Funktion ob ich die Daten die du senden musst nun 2 Byte oder
>1 Byte pro Zeichen sind?

Diese Frage habe ich nicht ganz verstanden. In AppCmd/AppCmdResponse 
wird ein String drinnen stehen der minimal 1 Zeichen bis zu x Zeichen 
lang sein kann. Die Escaped Sequenzen also 3 Zeichen ala /3F werden 
umgewandelt und raus kommt der fertige String der gesendet eg. empfangen 
werden muß. Nun, IAVRootloader sendet AppCmd und wartet auf den Empfang 
des AppCmdResponse. Dessen Länge in Bytes ist ja dann schon bekannt und 
somit ist es einfach diese X Zeichen vom COM Port zu lesen und mit 
AppCmdResponse zu vergleichen. Real ist es natürlich ein bischen anders 
da ich dort Zeichenweise beginnend mit dem ersten Zeichen des gültigen 
AppCmdResponse vergleiche und einen Zeichen-Index bei Erfolg 
inkrementiere. Dh. sowas wie eine sliding Window Vergleichsroutine.

Hm, könnte es sein das du dich auf die Deklaration mit WideString 
beziehst und die Unterscheidung zwischen Singlebyte/Multibytes String 
meinst ? Ganz einfach: alle WideStrings werden als nicht translierbare 
Singlebyte Strings interpretiert. 2 Bytes ASCII Formatirungen also 
garnicht berücksichtigt.
Der Grund für die Verwendung von WideStrings ist einfach der das nur 
dieser Typ für dynamische Strings über Prozess/Thread/Task-grenzen 
hinweg im MS DCOM/COM/AQctiveX Standard erlaubt, eg. sinnvoll sind. 
Würde ich meine DLL also in ein echtes ActiveX/COM Objekt umbauen wollen 
so müsste ich nichts am bestehenden Code abändern aus dem Fakt der 
dynamischen Allozierung. Dann wäre diese DLL als Inprozess/Outprocess 
COM Server sofort benutzbar als ActiveX/COM Objekt in anderen Sprachen 
die sich an die Regeln halten. Die Alternative zu Widestrings als 
"binärer dynaqmsicher Datenkontainer" wären andere Interfaces/Objekte zu 
benutzen, wie IStreams usw. Das ist aber viel komplizierter als mit 
WideStrings zu arbeiten. Neuerdings gäbe es noch die Varianten aber in 
diese ein Bytesarray zu allozieren kostet im Source mehr als eine simple 
Zuweisung wie bei den WideStrings in Delphi. WideString sind in Delphi 
kompatibel zu deren eigenen AnsiStrings.

Gruß Hagen

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

Danke für die Erklärungen, nun bin ich ganz gut informiert und vieles 
ist nun auch sehr gut verständlich. Ich hatte bei der DoConnect 
Exception mich schon recht gut gewundert, wie eine DLL mir eine Delphi 
kompatible Exception werfen kann, da afaik Delphi dies nicht ordentlich 
handelt mit externen Exceptions. Wäre es eine EAbort Exception, dann 
hätte man ja vllt. wenigstens den Classname ermitteln können, aber die 
gefangene ist einfach Exception, von daher kann es von Delphi vllt. eine 
neu generierte sein nach auffangen der von dir generierten.
Ich werde zumindest demnächst nochmal weiter debuggen und schauen woher 
das ganze stammt, es wäre doch wohl gelacht, wenn ich das nicht zum 
stabilen laufen bekommen würde.

Ich kenne das mit der fehlenden Zeit selbst ganz gut, aber derzeit kann 
ich mich mal gut dem Projekt widmen - da es ein privates Projekt ist, 
ist das eine schöne Urlaubsbeschäftigung. Ich würde dich nur im Notfall 
bitten dir den Quellcode anzuschauen - ein Notfall wäre, wenn ich nach 3 
Tagen debuggen noch immer keinen Anhaltspunkt habe, warum das nicht 
klappt oder die Exception mir weiter um die Ohren fliegt. Das Angebot 
war eher dazu gedacht, dass du die Fehler besser nachvollziehen kannst, 
da ich mit dem Verify das gleiche Problem hatte und dazu noch halt diese 
Exception + hackliger Verbindungsaufbau mit deinem Programm. Aber 
erstmal stehle ich dir ja schon genug Zeit mit den Beiträgen hier.

Und zu der AppCommand Frage, diese zielte eher darauf ab, da du ja einen 
WideString haben willst. Dies ist zwar durch das ActiveX beste Wahl, 
aber wenn ich dir nun einen zurück gebe, z.B. "test", dann wäre es im 
Speicher folgender aufbau: 00 74 00 65 00 73 00 74. Woher weisst du nun, 
dass du nur 74 65 73 74 senden musst und ich nicht vllt. Binärdaten 
nutze in meinem Protokoll und du von daher 00 74 00 65 00 73 00 74 
versenden müsstest?

Grüße,
Thomas

von Hagen R. (hagen)


Lesenswert?

Ok, ganz einfach würdest du mit WideString die Bytes 00 74 00 65 00 73 
00 74 versenden wollen dann stünde im WideString folgendes drinnen
00 00 00 74 00 00 00 65 00 00 00 73 00 00 00 74, expandiere also jedes 
der Bytes um ein weiteres Nullbyte. Per see wandle ich alle WideString 
Parameter von und nach ANSI Strings. Ich benutze also intern selber nur 
die LongStrings/eg. AnsiStrings vom Delphi. WideString dient nur dazu um 
in den Interfaces CMO/ActiveX konform zu sein und eben nicht die 
aufwändigeren Alternativen nutzen zu müssen.


Beim Debuggung mit Delphi musst du aufpassen. Der JIT Debugger von 
Borland zeigt dir auch abgefangende Exception an und hält auch dann. 
Diese Exception könntest du leicht als Exception für dich interpretieren 
werden aber intern in jedem Falle behandelt und interessieren dich somit 
überhaupt nicht. Das liegt darin begründet das der Debugger zwar sich in 
die globale Exceptionchain einlinken kann er aber eben nicht zum 
Zeitpunkt des Auslösens einer Exceptions in der Lage ist zu ermitteln 
bis zu welchem übergeordneten Sourcecode Bereich die Nicht Bearbeitung 
dieser Exception reicht. Normalerweise bist du als Programmierer nur an 
denjenigen Exceptions interessiert die bis in deinen Source hinein 
unbearbeitet bleiben und dort abgefangen und behandelt werden sollten. 
Zum Auslösezeitpunkt einer Exception könnte es aber so sein das in 
meinem Source ich später diese Exception abfange, sie behandle und eine 
andere neue Exception als Folge davon raise. Möchte man aber nun einen 
Haltpunkt an exakt der Codestelle an der eine Exception ausgelösst wurde 
dann kann zu diesem Zeitpunkt der Debugger eben nicht wissen das es sich 
um eine Exception handelt die garnicht bis in deinen Source hinein 
reichen wird da ich sie in meinem Source vollständig behandle.

Exceptions sind heutzutage ein Feature des Windows Betriebsystemes, mit 
klar definierter Struktur und einigen hilfreichen API Funktionen. 
Borland Delphi kannte noch vor dem Windows OS Exceptions, diese wurden 
aber ganz anders umgesetzt. Egal, worauf ich hinaus will ist das Fakt 
das der Borland Debugger auch andere Programme geschrieben in anderen 
Sprachen und deren Exception Handling debuggen kann, solange sie sich am 
MS Window Standard halten. In diesem Falle, und eben bei 
Interprozess-Debugsessions stehen aber bestimmte Infos nicht mehr zur 
Verfügung. Also zb. der Klassennamen der Objektimplementierung einer 
Delphi Exception, selbst wenn sie in einer DLL mit Delphi geschrieben 
ausgelösst wird. Das liegt einfach daran das die Delphi Exception 
Klassen eben ein Feature nur von Delphi sind und nicht kompatible 
Objektstrukturen zu anderen Sprachen, es gibt da ja keine Standards. Der 
debugger kann die also anzeigen wo und das eine Exception ausglösst 
wurde im Sinn der Funktionalität die das OS/Hardware zur Verfügung 
stellt aber eben keine Informationen über den OOP Überbau den ein Source 
benutzt um diese Exception in Objekte zu verkapseln.
Nebenbei bemerkt hätte der Delphidebugger sehr wohl die Möglichkeit auch 
den Klassennamen von Exceptions aus anderen Prozessen/DLLs die selber 
mit Delphi geschrieben wurden zu ermitteln und anzuzeigen. Die Windows 
OS Exception Strukturen können nämlich durchaus erweiteret werden, 
werden sie sogar, nämlich um zb. Zeiger auf die Exception Objekte, und 
damit die OOP-mäßige Kapselung dieser Exceptions. Nur kommt man da an 
die Grenze zwischen planmäßiger definierter Benutuung einer 
Schnittstelle und einem Hack zum Auslesen anderer Prozessspeicher.

Sogesehen: die Aussage Delphi/Debugger würde dies nicht richtig 
handhaben ist falsch ;) Er darf es gar nicht anders handhaben auch wenn 
es möglich wäre, es existiert keine klar umrissene Schnittstelle  solche 
Informationen über Prozessgrenzen und Sprachgrenzen hinweg abfragen zu 
können.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Übrigens Exceptions dürfen auch in COM/ActiveX Interfaces über die 
Grenzen der DLL/Prozesses/Tasks usw. weitergereicht werden. Man sollte 
dies nicht machen aber zulässig ist es. Deshalb oft bei den COM/ActiveX 
die umständliche alte Arbeitsweise über ein HRESULT als Rückgabe einer 
Methode.

Die Punkte an denen manchesmal der JIT Debugger mit "externe Exception" 
aussteigt sind von ganz spezieller Natur. Meistens sind es nämlich 
Exception innerhalb des Kernels vom Windows ausgelösst um spezielle 
Tricks zu ermöglichen. Exceptions sind nämlich hervorragende Mittel um 
Hacking/Debugging zu erschweren. Nun, diese "seltene" Fälle in denen der 
JIT Debugger aussteigt liegen darin begründet das diese Exception sich 
eben nicht an den Standard in der Exceptionbehandlung halten den MS 
vorgegeben hat.

Man kann also einen Debugger der selber ein Exceptionhandling benutz 
dahin gehend austricksen das man in seinem eigenen Code dessen 
Excpetionchain so umbiegt das eine Exception ausgelöst im eigenen Code 
sich so verhält als wäre sie innerhalb des Debuggercodes ausgelösst. Das 
führt dazu das der eigene Code die Kontrolle über den Debugger erlangen 
kann und diese abschießt. Aber das ist Hardcore und sprengt diesen 
Thread ;)

Gruß Hagen

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

Jo, danke. Manches davon war mir noch nicht bewusst - ich habe bisher 
auch meistens immer beide Seiten programmiert bei irgendwelchen 
Interfaces oder anderen Schnittstellen, so dass ich dort meistens mit 
results gearbeitet hatte.

Ich meinte bei meinen Ausführungen nicht EExternalException sondern 
bezog mich mit "externe Exception" auf Exceptions aus nicht meinem 
Programmcode - somit u.a. aus deiner Interface DLL.

Ich werde mal debuggen und schauen. Wenn es Problem gibt, dann melde ich 
mich nochmals.

Vielen Dank nochmals für deine Zeit und wie immer ausführlichen 
Erklärungen!

Gruss,
Thomas

von Hagen R. (hagen)


Lesenswert?

>Ich meinte bei meinen Ausführungen nicht EExternalException sondern
>bezog mich mit "externe Exception" auf Exceptions aus nicht meinem
>Programmcode - somit u.a. aus deiner Interface DLL.

Und eben diese siehst auch du in deinem Debugger. Ich empfinde diese 
ebenfalls störend in der produktiven Entwicklung, aber aus oben 
genannten Gründen kann der Debugger dies nicht unterscheiden. Naja, 
möglich wäre es schon aber Borland hat keine GUI Schnittstelle 
integriert um dies selektiv abzuschalten. Wahrscheinlich weil sie es 
nicht sauber überprüfen können obwohl es doch sehr einfach wäre das 
Modulhandle und damit die virtuelle Adresse des Modules in der die 
Exception ausgelöst wird als Filterbedingung zu benutzen. Problematisch 
bei einem solchen Filter ist eben der Fakt der realen Behandlng einer 
solchen Exception. Wird sie im fremden Modul vollständig behandelt 
bräuchtest du sie auch nicht sehen. Passiert dies nicht und du stepst 
nicht durch dann landest du in deinem Source an einer Stelle die du dir 
nicht erklären kannst wie du dahin gekommen bist. Aus deiner Sicht ist 
die Kausalität nicht mehr vorhanden und ergo suchst du in deinem Code 
bis in alle Ewigkeit nach dem Auslöser dieses Verhaltens. Borland hat da 
wohl pragmatisch reagiert und zeigt alle Exceptions an weil sie 
eventuell direkt in deinen Code springen könnten und baute somit auch 
keine Filterung für solche Exceptions ein.

Das was du nun als Exception bekommst sind meine internen EAbort's die 
ich zur Flußsteuerung benutze. Diese werden behandelt und wie ich es 
oben schon sagte sehe ich Exception bischen weiter gefasst als nur pure 
Fehlerbehandlungen.

Gruß Hagen

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

Zwischenzeitlich kann ich erfreuliches berichten: es läuft. Ich hatte 
diese Verbindungsprobleme aus dem gleichen Grund wie dein Programm: 
Options war noch 2 und nicht halt 1. Nun mit der neuen Connect Methode 
von dir (also Options 0 oder 1) klappt nun auch alles wieder vorzüglich. 
Ich war auch schon recht verwundert, da ich zuvor ein paar Updates ohne 
Probleme fahren konnte. Die Exception war somit einfach nur die Meldung 
über den ausgebliebenen Verbindungsaufbau. Komisch bleibt aber weiterhin 
warum deine Output() Funktion anspringt mit einer leeren Message und dem 
Code für einen Fehler. Du stellst doch den ausbleibenden 
Verbindungsaufbau fest (Timeout), somit bist du doch Herr bzw. Generator 
der Meldung. Alle meine weiteren Probleme die ich vorhin geschildert 
hatte waren nur Folgefehler (Index war dann 2, erneuter Aufbau, anderer 
Port/Enumeration, dadurch dann Code 5, Access denied - nun ist dies 
alles klar).

Also, ergo, alles in Butter und derzeit läuft das Update schonmal 
grundsätzlich. Nun bleibt nur noch die Frage, warum meine AppVersion 
immer so komisch aussieht, obwohl ich doch alles gesetzt habe und auch 
mein klein genug ist (noch rund 2,5 kB frei, 1 kB für Bootloader, also 
1,5 kB frei). Deine App und das Interface ermitteln die App Version 
korrekt, nur die von deinem test Beispiel übernommene Code ermittelt 
wohl Müll. Auch der gesicherte MCUSR ist müllig. Aber das sind 
Kleinigkeiten, die löse ich noch mit der Zeit.

/Nachtrag: Sprich ermitteln der AppVersion auf dem AVR mit dem Client 
Code schlägt fehl. Special Read ist an, sonst würde er ja ins Nirvana 
springen (war mein vorheriger Fehler ^^).

Das ganze Projekt wird eh wieder komplett veröffentlicht, es ist "nur" 
ein Update des bisherigen Projektes 
(http://blog.mütze1.de/?page_id=231).

Also nochmals vielen Dank für deine Hilfe. Und ich werde mich ranhalten 
Beispielprojekte für das DEC Problem zu erstellen.

Grüsse,
Thomas

PS: Ich nutze in meinen Programmen auch zu gerne SEH, weil es im OO 
programmieren einfach die beste Möglichkeit ist um den Programmablauf 
ausserhalb der Reihe zu steuern. Gerade Aktionsabbruch etc., 
Fehlerbehandlung, Flusssteuerung, etc.

von Hagen R. (hagen)


Lesenswert?

>..Probleme fahren konnte. Die Exception war somit einfach nur die Meldung
>über den ausgebliebenen Verbindungsaufbau. Komisch bleibt aber weiterhin
>warum deine Output() Funktion anspringt mit einer leeren Message und dem
>Code für einen Fehler. Du stellst doch den ausbleibenden
>Verbindungsaufbau fest (Timeout), somit bist du doch Herr bzw. Generator
>der Meldung...

Korrekt, ich bin auch der Herr und Generator der Fehler die immer in 
einem solchen Projekt versteckt sind ;) Kurz, es könnte durchaus auch 
ein fehlerhaftes Verhalten sein auf das ich in meinem Überbau nicht 
stoßen konnte weil er sich von deiner Benutzung der Interfaces 
unterscheidet. Um dies beurteilen zu können und eventuell einen Hinweis 
auf meinen Fehler zu bekommen wäre es vieleicht doch sinnvoll wenn ich 
mir deine Sourcen anschaue.

> Nun bleibt nur noch die Frage, warum meine AppVersion
>immer so komisch aussieht, obwohl ich doch alles gesetzt habe und auch
>mein klein genug ist (noch rund 2,5 kB frei, 1 kB für Bootloader, also
>1,5 kB frei). Deine App und das Interface ermitteln die App Version
>korrekt, nur die von deinem test Beispiel übernommene Code ermittelt
>wohl Müll. Auch der gesicherte MCUSR ist müllig. Aber das sind
>Kleinigkeiten, die löse ich noch mit der Zeit.

Das gesicherte MCUSR muß unter WinAVR GCC exakt so geholt werden wie ich 
es gezeigt habe (könnte vielleicht auch von der WinAVR Version abhängig 
sein). In meinem Example benutze ich absichtlich die Zuordnung der 
einzelnen Funktion zu bestimmten Sections für den Linker. Damit stelle 
ich sicher das die Initialisierung durch den WinAVR Startup Code 
teilweise schon erfolgte aber der Stack noch nicht benutzt wurde. Das 
gesicherte MCUSR liegt ja an der ersten Speicherstelle im Stack. Hast du 
vor dem Auslesen nach meinem Vorschlag aber schon zb. eine 
Unterfunktion, also CALL, getätig ist dieser Inhalt nun mit der 
Rücksprungadresse überschrieben worden. Es ist halt nicht so einfach 
eine Methode zu wählen die einfach, schnell und Resurcenschonend 
funtioniert und dann noch keine Kollisionen mit zb. dem WinAVR Startup 
Code provoziert.

Natürlich mus auch UseSaveMCUSR=1 gesetzt sein.

Wie gesagt so wie es in meinem Example demonstriert wurde, exakt so, 
sollte es auch immer funktionieren.

Und als Letztes könnte es auch der Fall sein das du schon den korrekten 
Inhalt des MCUSR siehst nur dieser für dich komisch aussieht. Einige 
AVRs speichern noch andere Bits in dieses Register, oder bei einem 
Powerup hast du gleich 3 Bits gesetzt, die für PowerUp, Ext. Reset und 
Brownout. Das war mir bis vor kurzem (bei der Entwicklung des 
Bootloaders) auch noch nicht so bewusst.

Die Funktionen aus AVRootloader.h um die Versionsnummer auszulesen sind 
ein bischen umständlicher als notwendig, einfach aus dem Grund heraus 
unabhängig von der realen Speicheradresse der AppVersion zu sein. Sie 
ermittelt also zur Laufzeit die Adresse der AppVersion durch Auslesen 
der mit GetBootMsg zurückgelieferten Addresse. Damit wird der BootInfo 
Inhalt ermittelt um auf die Anzahl der FLASH Pages die der Bootloader 
benutzt zu kommen. Diese Anzahl wird mit der FLASH Page Größe 
multipliziert und von der höchsten FLASH Addresse plus -4/6 subtrahiert 
und schwups hast du die Adresse im FLASH an der die AppVersion steht. 
Nun, ziemlich kompliziert dafür sollte es universell sein. In deinem 
Falle, und ich mache es eigentlich auch immer so, lese einfach mit 
pgm_read_dword(0x?????) direkt mit fester hardcoded Adresse die 
AppVersion aus. Nicht schön aber effizient und funktionierend egal 
welche Lockbits gesetzt wurden. Ich musste nämlich feststellen das je 
nach WinAVR version der Compiler mit meinen Makros fehlerhaften Code 
erzeugt.

Eventuell hast du auch nicht UseSpecialMsg=1, UseSpecialRead=1 gesetzt ?

Diese Funktionen wären dann nötig. Erstens mal UseSpecalMsg=1 um 
diejenige Funktion zu aktivieren die die FLASH Addresse vom BootInfo: 
Label zurückliefert, inklusive Größe in Bytes davon. Dann 
UseSpecialRead=1 damit der eventuell vor dem Lesen mit LPM geschützte 
FLASH Bereich der Bootsection auslesebar wird. Je nach Fuses halt.

Also ziemlich viel Aufwand und Resourcen und man sollte schon selber 
wissen ob einem dies auch Wert ist im Vergleich zu einem fixen 
pgm_read_dword(0x????) mit hardcoded und auf den aktuellen AVR bezogenen 
Source. Übrigens exakt dies ist der Grund warum die PC-Software die 
reale Adresse der AppVersion auch im Info Fenster anzeigt.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

@Thomas, habe mir mal dein Projekt angeschaut, ich beneide dich für die 
Ausdauer eine so umfangreiche Dokumentation zu machen. Ist das 
kommerziell ?
Und dann frage ich mich ob du als Muetze auch in der Delphi Praxis 
unterwegs bist und wir von anderer Seite her schon öfters mal Kontakt 
hatten ?

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

Also die UseSaveMCUSR ist gesetzt und ich habe die Anweisung zum Wert 
holen direkt am Anfang der Main, aber bisher noch mit dem cli() zuvor. 
Ich habe das gerade mal verschoben und bin noch am probieren.
1
int main(void)
2
{
3
  cli();
4
5
    // read MCUSR saved by bootloader
6
  uint8_t lSavedMCUSR = *(uint8_t*)(RAMEND);
7
8
  ...
9
}

Wegen der App Version vom AVR aus auslesen - nun ja, was soll ich sagen, 
die UseSpecialMsg war nicht gesetzt, obwohl mir das beim anschauen 
deiner Sources bei dem Test Projekt schon aufgefallen und bewusst war, 
dass du die Funktion brauchst. Nun ja, mein Fehler. hust

Und wegen dem Projekt: Das ist noch der alte Stand, neue Doku 
(umfangreicher, dann auch zweisprachig) ist fast fertig und die Software 
auch entsprechend. Das derzeitige ist wirklich noch alt.

Aber ich denke mal, ich versuche mal meine ganzen Erkenntnisse zu deinem 
Bootloader die ich hier gewonnen habe vllt. auch nochmal zusammen zu 
fassen.

Und ja, der bin ich (es kann nur eine Muetze1 geben ^^). Wir hatten 
schon öfters mit einander zu tun und deshalb ja auch schonmal den 
Hinweis auf einen Thread bei der dp.net (also DelphiPraxis.net) 
bezüglich ein paar Schwierigkeiten mit der DEC.

Und das ganze Projekt ist nicht kommerziell. Eigentlich auch schön doof, 
da ich dazu erst gekommen bin, da mich ein Freund fragte, ob man da 
nicht was machen kann bezüglich dieser Steuerung beim Aquarium. Es gibt 
genug Systeme, z.T. mit weniger Umfang bzw. weniger Möglichkeiten, aber 
alle haben eins gemeinsam: Startpreis bei rund 150-200 €. Eigentlich 
könnte man das Projekt vllt. doch nochmal etwas professioneller aufbauen 
und die Geräte schonmal zusammenstellen, die Gewinnspanne bei einem 
fairen Preis von 50-100 Euro wären noch recht immens...

Danke mal wieder für die guten Hinweise - vor allem da der AppVersion 
Fehler mal wieder bei mir lag - schlimmer noch: es war mir schonmal 
bewusst...

Gruss,
Thomas

von Hagen R. (hagen)


Lesenswert?

Mache es so
1
void init_MCUSR(void) __attribute__((naked)) __attribute__((section(".init5")));
2
void init_MCUSR(void) {
3
// lese Kopie von MCUCSR gespeichert durch Bootloader vom Stack
4
    _MCUCSR = *(uint8_t*)(RAMEND);
5
}

Damit erzeugen wir erstmal eine "Procedure" die ohne Stackframe oder 
Return kompiliert wird, also nur das nackige _MCUSR = 
*(uint8_t*)(RAMEND); enthält. Dieses Codestückchen wird nach einem Teil 
der Initialsierung durch den WinAVR Startup Code und bevor der Main() 
Code kommt durch den Linker relokiert. Somit ist sichergestellt: Du als 
programmierer der keine speziellen Sachen macht sondern ganz stink 
normal WinAVR benutzt hat keine Chance den Stack noch vor dem Auslesen 
des gesicherten MCUSR register zu zerstören. Das könnte in deinem Main 
der Fall sein ohne das du es dir bewusst bist.

Nicht schön aber der einzigst gangbare Weg unter WinAVR mit der 
geringsten Fehlerwahrscheinlichkeit. Das ganze Problem entsteht weil wir 
das MCUSR Register eben löschen müssen (bzw. zumindest das WDR Bit) und 
es nicht wieder setzen können. Löschen wir das WDR Bit nicht so bleiben 
die nachfolgenden Schreibzugriffe um den WDT zu programmieren erfolglos. 
Da der WDT eine gültige RESET Source ist und die eigene Anwendung auch 
unabhängig vom Bootloader eventuell wissen muß welcher RESET ausgelösst 
wurde, wir dieses Regsiter also löschen müssen damit der Bootloader den 
WDT programmieren kann und der WinAVR eg. Programierer den Stack 
unbeabsichtigt zu früh überschreiben könnte, wir auch keine Register für 
unsere Zwecke mißbrauchen können, verbleiben nur sehr wenige 
Alternativen unser Ziel zu erreichen. Und der jetzige Weg ist der einige 
der in meinen Augen übrig bleibt und die wenigsten Seiteneffekte hat. 
Auf einigen AVR gibt es 3 zusätzliche Register im Addressbereich der 
Ports die man hätte dafür benutzen können aber exakt diese wertvollen 
Register wollte ich mir für meine Projekte aufheben, zumal nicht jeder 
AVR solche hat.
Auch die Option UseBootMode baut darauf das das MCUSR Register im 
Bootloader gelöscht wird. Diesesmal nicht nur bezogen aud das WDR Bit 
sondern auch auf alle anderen RESET Sourcen. Denn je nach UseBootMode 
selektieren wir ein Event das bei nicht programmierten AVR, also ohne 
Anwendung, wenn wir es nicht löschen würden den Bootloader dann 
aussperrt. Der Bootloader würde dann zb. nur auf den Borwout RESET 
reagieren und nicht mehr auch wenn er garkeine Anwendung vorher schon 
installiert hat. Dh. UseBootMode stellt sicher das der Bootloader beim 
RESET und eben auch bei nicht vorhandener Anwendung ausgeführt wird. 
Diese zweite Möglichkeit tritt aber nur auf wenn der Bootloader quasi 
eine nicht vorhandene Anwednung aufruft dann durch die 0xFF im 
Anwedenungsflash wquasi wieder in sich selber reinläuft und bei diesem 
zweiten Aufruf auf ein MCUSR register trifft das 0 ist auf Grund dessen 
das es beim ersten Aufruf gelöscht wurde.
Naja, ziemlich viel worte für diese einfachen Sachverhalte.

Meine init_WDT() Procedure wird noch weiter vor verlegt, also noch 
früher ausgeführt nämlich noch bevor der WinAVR Startup Code den SRAM 
initialisert, also .data und .bss (preinitialisierte globale 
Variablen/Strings etc.pp.). Mit langsamen Takt und schnellem WDT ist das 
zu präferieren.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Übrigens das CLI() ist nicht notwendig, erst recht nicht wenn du meinen 
Vorschlag benutzt.

von Thilo M. (Gast)


Angehängte Dateien:

Lesenswert?

Hi Hagen,

habe die Options mal auf 3 gesetzt.
Ergebnis siehe Protokollfile.

von Thilo M. (Gast)


Lesenswert?

Sorry für das riesen File! ;)

von Hagen R. (hagen)


Lesenswert?

er bekommt keine Verbindung, bzw. der AVR antwortet nicht.

Also verbinde RX-TX Pin vor dem AVR, natürlich ohne AVR. Versuche erneut 
einen Connect und es müsste im Protokoll zu sehen sein das er 1.) zum 
1-Wire Modus wechselt, 2.) die Daten die er sendet einmalig auch wieder 
empfängt.
Wenn dies nicht so ist dann stimmt irgendwas mit einem COM Port, 
Hardware, Windows Setup nicht.

Gruß Hagen

von Thilo M. (Gast)


Lesenswert?

Hi Hagen,

die Hardware ist OK.
Ein Testprogramm mit USART des m32 funktioniert perfekt.
Wie gesagt: im gleichen Steckplatz, mit gleichem Bootloader (nur .inc 
und Codegröße geändert) läuft es auf dem m644P ja. Nur der m32 will 
nicht.

Ist kein Beinbruch, werde den m32 durch m644P ersetzen (ist ja keine 
Großserie).

von Hagen R. (hagen)


Lesenswert?

@Thilo,

Das sind zu wenig Informationen. Schaue dir mal deine Postings selber 
an. Du hast einen lauffähigen Bootloader für Mega644, tauscht diesen in 
deinem Board mit M32 aus, änderst logischerweise im AVRootloader.asm auf 
den M32, und es geht nicht. Protokoll zeigt auch das es nicht geht, der 
M32 antwortet nicht.

Tja das ist das was ich an Infos habe.

Ich kann dir versichern, mit den fortschreitenden Versionen wurde die 
Benutzerschar immer größer und auch das Feedback mit welchen AVRs in 
welcher Konfiguration der Bootloader schon eingesetzt wurde. Der M32 ist 
darunter.

Es muß also bei deinem Aufbau irgendwas falsch laufen. Lösche alle 
Dateien bis auf die Sourcen und Konfigurationen. Dann kompiliere das 
AVRootloader.asm nochmal neu mit BootCodeSize=0 und dann nochmal mit dem 
Wert aus CSEG used. Stelle dann sicher das du auch wirklich das korrekte 
HEX File auf deinen M32 installierst und nicht eventuell eine der vielen 
anderen Kopien aus den vielen anderen Ordnern ;) Ich kenne die 
Arbeitsweise mancher Programmierer und da kann man schonmal mit den 
Kopien durcheinander kommen, ich muß ja auch öfters so arbeiten. 
Besonders weil AVRStudio in der Pfadangabe zum HEX File sich die alten 
Einstellungen merkt und nicht diejenge zum Projekt.

Gruß Hagen

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

Ich habe es nun auch endlich hinbekommen den MCUSR Code von deinem 
Bootloader sauber in meinen Code zu bekommen. Als erstes hatte mich an 
deinem folgenden Code schon immer verwundert, warum du eine init_MCUSR() 
deklarierst mit den schönen Attributen von wegen früher Ausführung und 
Init, aber das eigenliche Lesen wiederrum machst du in einer 
init_prots() ohne all' diese schönen Attribute. Nun ja, somit wird diese 
Routine wohl auch nicht aufgerufen.

Dein Code den du vorgeschlagen hattest:
1
void init_MCUSR(void) __attribute__((naked)) __attribute__((section(".init5")));
2
void init_ports(void) 
3
{
4
    // read MCUSR saved by bootloader
5
  gvaResetFlags = *(uint8_t*)(RAMEND);
6
}

Und von daher habe ich es so umgeändert, dass es nun nur noch die eine 
Routine gibt, welche dann auch die Attribute hat von wegen init5 Aufruf, 
etc.
1
void __attribute__((naked)) __attribute__((section(".init5"))) init_ports(void) 
2
{
3
    // read MCUSR saved by bootloader
4
  gvaResetFlags = *(uint8_t*)(RAMEND);
5
}

Das läuft aber so noch nicht richtig, da die Variable ja eine globale 
ist und somit mit 0 initialisiert wird. Also muss man diese globale 
Variable davon noch ausschliessen - mal wieder mit Attributen.
1
  // Reset cause flag register, saved at startup
2
extern volatile uint8_t gvaResetFlags __attribute__ ((section (".noinit")));

Das ist aus dem Header, daher das "extern". Die Deklaration in der .c 
Datei kann man sich ja denken.

Damit klappt dies nun einwandfrei und ich kann auslesen ob ich von 
deinem Bootloader komme, eigener WDT Reset, Brown Out oder direkt 
gestartet. Klappt nun einwandfrei.

Das ganze Firmware Update etc ist nun auch stabil und läuft super 
integriert in meinem Client.

Also, danke nochmals für den super Bootloader!

Gruss,
Thomas

von Hagen R. (hagen)


Lesenswert?

Sorry muß heisen
1
void init_MCUSR(void) __attribute__((naked)) __attribute__((section(".init5")));
2
void init_MCUSR(void) 
3
{
4
    // read MCUSR saved by bootloader
5
  gvaResetFlags = *(uint8_t*)(RAMEND);
6
}

Du musst dann nicht darauf achten ob gvaResetFlags mit 0 überschrieben 
wird oder volatile deklarieren. Der Init Code des GCC der die globalen 
Variablen mit 0 initialisert wird in einer Section gelinkt die noch vor 
der Section .init5 kommt. Dh. der obige Code sollte nach der 
Initialisierung des GCC aber vor der Main() aufgerufen werden.

Gruß Hagen

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

In deinem Test Projekt ist auch alles richtig drin. Nun ja, ich hatte 
mich halt auf das Beispiel aus diesem Thread gestürzt. Ich hätte da eine 
"declared but unused" Warnung vermisst...

Ansonsten das mit der 0 Initialisierung des Startup Codes, das kann gut 
sein, da ich das mit dem Reset Code nebenbei mit ein paar anderen 
Änderungen an der Firmware gemacht hatte. Von daher werde ich das gleich 
nochmal wieder entfernen.

Jetzt muss ich nur noch klären, warum die AppVersion über den Controller 
ausgelesen immer eine total komische Zahl ergibt. Dazu doch gleich mal 
eine neue Frage: Wenn ich über dein Interface eine neue Firmware flashe, 
diese aber nicht verschlüsselt ist und direkt ein HEX file gegeben wird 
(kein ACY), dann kann ich die gewünscht AppVersion in der Methode des 
Interfaces zurück geben, oder? Weil soweit ich verstanden habe, ist die 
Masked Option zum überprüfen vor dem Flash nur bei verschlüsselter 
Firmware von nöten, somit sollte er bei mir die neue Version nur 
abfragen. Sehe ich das richtig? Also bei dem Masked Parameter auf true, 
gebe ich dann 0 zurück und im anderen Falle die neue AppVersion?

Gruss,
Thomas

von Hagen R. (hagen)


Lesenswert?

Bei Masked=TRUE solltest du in diesem Falle $FFFFFFFF = -1 zurück geben. 
Allerdings wird .GetAppVersion(True) ausschließlich nur dann aufgerufen 
wenn der IAVRootloader Daten verschlüsseln muß. Es gibt zwei Momente in 
denen das passieren kann, erstens man erzeugt and ACY File und der 
verbundene AVR unterstützt die Verschlüsselung, egal ob er auch 
unverschlüsselte Daten zulässt oder nicht. Zweitens, der AVR soll mit 
einem HEX File geflsht werden und erwartet zwingend verschlüsselte 
Daten. Dann wird IAVRootloader das HEX File intern und temporär in einem 
Stream speichern und ein verschlüsseltes ACY kompilieren. Ganz genau 
genommen wird intern bei einem HEX/EEP immer ein ACY Stream erzeugt, so 
als wenn man den Compile Button erzeugt. Meine .DoProgram() Methode 
arbeitet intern also immer mit einem ACY Script. Dies ist entweder im 
Speicher temporär erzeugt oder eine reale ACY Datei in den Speicher 
geladen.

Wenn also Masked=True ist so sollte deine Methode entweder $FFFFFFFF 
zurückgeben und damit die Versionüberprüfung im AVR Bootloader defakto 
deaktivieren. 0 wäre grundsätzlich falsch da es bedeuten würde das du 
die kleinste Versionnummer benutzen möchtest. Wenn nun schon Version 
0.0.0.1 installiert ist so würde der AVR Bootloader die Version 0.0.0.0 
nicht akzeptieren und den programiervorgang abbrechen.

Gibst du zB. $01FF02FF zuück so überprüft der AVR intern das die aktuell 
installierte Version klein oder gleich 1.?.2.? ist. Dh. installierte 
Version wie 1.0.2.0, 1.123.2.15 usw. wären gleich. Wäre die installierte 
Version aber 1.?.3.? oder 2.?.?.? dann wäre sie größer als die zu 
installierende Version.

Gibst du ohne die $FF Masken die gleiche Versionsnummer wie bei 
Masked=FALSE zurück, also zb. 1.2.3.4 dann überprüft der AVR also auch 
alle 4 Zahlen mit der installierten Version.

Ergo: gib -1 oder $FFFFFFFF bei Masked=True zurück und du hast keine 
Probleme da die Versionüberprüfung im AVR dann deaktiviert ist. Diese 
Überprüfung erfolgt nur bei verschlüsselten Daten.

Beim Auslesen der AppVersion in der eigenen AVR Anwendung gibt es zwei 
Wege:

1.) der direkte Weg: pgm_read_dword(0x???????) oder 
pgm_read_dword_far(0x??????) wenn mehr als 64Kb FLASH vorhandeen, oder 
RAMPZ auf 1 setzen und mit pgm_read_dword() arbeiten. Die Adresse 
0x?????? findet man im Info Fenster meiner PC-Software wenn man mit dem 
AVR verbunden ist. Dieser Weg funktioniert immer egal welche zus. 
Features im Bootloader aktiviert/nicht aktiviert wurden und egal welche 
Lockbits man im AVR gesetzt hat solange der LPM Opcode für die 
Applikation freigegeben ist.

2.) der indirekte Weg: über die Funtionen in AVRootloader.h. Dazu muß 
aber zwingend der Bootloader mit UseSpecialMsg=1, UseSpecialRead=1 und 
UseSpecialBootVect=1 konfiguriert sein. Wie diese Funktionen dann benutz 
werden um dynamisch die Adresse der AppVersion im FLASH zu berechnen 
habe ich in einem vorherigen Thread schon beschrieben.

Ich würde den direkten Weg gehen, ist simpel, verbraucht weniger Code in 
der eigenen Anwendung und die UseSpecialXXX Funktionen müssen nicht 
zwingend in den Bootloader eingelinkt werden, was wiederum im Bootloader 
Code spart.

Konzeptionell habe ich in AVRootloader.h nur deshalb diese 
Implementierung gemacht damit man dieses Header benutzen kann für die 
Programierung einer universellen Bootloader-Update-Anwendung. In diesem 
Moment würde der Bootloader sowieso die UseSpecialXXX Funktionen 
einlinken damit er durch diese Anwendung updated werden kann. Es ist 
dann hilfreich wenn diese Update-Anwendung auf universelle Weise die 
wichtigen Daten wie die BootMsg, BootInfo und AppVersion ermitteln kann, 
unabhängig vom jeweiligen AVR Typ und den anderen Einstellungen des 
jeweiligen Bootloaders.

Gruß Hagen

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

Danke mal wieder für die Ausführungen. Erstmal zu dem einfacheren Thema: 
Die AppVersion will ich weiterhin mit deinen Beispielquellen aus dem 
Test Projekt auslesen, da diese allgemeingültig sind. Ich müsste sonst 
desto mehr den Personen X erklären, welche das Projekt auf einem anderen 
Mikrocontroller nachbauen wollen. Von daher würde ich die direkte 
Methode vermeiden wollen.

Und nun nochmal zum anderen Thema: Meine Frage war eher: wenn ich nun 
eine neue Version auf den AVR bringe, wie und wo kann ich die neue 
Versionsnummer festlegen? Also die Versionsnummer, welche dann auch im 
Atmel Flash abgelegt wird. Die Frage interessiert mich vor allem, da ich 
es bisher noch nicht gelöst habe.

Gruss,
Thomas

von Hagen R. (hagen)


Lesenswert?

Ich gehe davon aus das du mein IAVRootloader Interface benutzt. Deine 
IApplication Impelemtierung muß die Methode .GetAppVersion(Masked: 
Booelan): Integer auch implementieren.

Wenn Masked = FALSE dann gibts du die neue Versionnummer als 4 Bytes 
Wert zurück.

Wenn Masked = TRUE dann gibts du die gleiche neue Versionsnummer zurück 
aber alle Bytes die nicht überprüft werden sollen werden mit $FF ODER 
verknüpft.

Ich habe angenommen das dir das schon klar ist. Falls du dich nicht auf 
IAVRootloader beziehst und meine PC-Software meintest dann geht die so:

Auf der 1. Page sind 4 Edit Felder mit der neuen Versionsnummer. In 
diese nun die Versionsnummer eingeben. Die 4 Checkboxen rechts daneben 
stelen die Maskierung in der Abfrage auf dem AVR dar. Jeweils die 
entsprechende Checkbox anhacken deren Versionsnummerbyte überprüft 
werden soll.

Das Überprüfen der Versionsnummer ist aber nur aktiv wenn mit 
Verschlüsselung gearbeitet wird.

Alternativ kann man die PC-Software auch per Kommandozeilenparameter 
aufrufen. Der Parameter -V definiert die neue Versionsnummer.
zb. -V0102A0FE0C definiert die neue Versionsnummer 1.2.160.224 und der 
letzte HEX Wert 0C die Bitmaske der anzuhackenen Checkboxen und damit 
auch welche der 4 Bytes überprüft werden muß. In diesem Falle also die 
beiden höchstwertigen Zahlen 1.2. die überprüft werden sollen.

Nun, diese neue Versionsnummer wird beim nächsten Programmieren des 
FLASHs über den Bootloader programmiert. Es gibt keine Schnittstelle im 
Protokoll diese Versionsnummer unabhängig zu programmieren. Defakto ist 
es ja auch logisch denn auch die Versionsnummer befindet sich im 
Anwendungsflash.

Du kannst meinen AVRootloader.asm Source auch erweiteren um eine eigene 
kleine Spezialfunktion die direkt die AppVersion als DWord zurückgibt. 
Das könnte so aussehen:
1
.if UseSpecialVersion
2
getappversion:
3
ldi  zl, byte1(AppVerAddr)
4
ldi  zh, byte2(AppVerAddr)
5
ldi  r22, byte3(AppVerAddr)
6
xout RAMPZ, r22
7
lpm  r22, z+
8
lpm  r23, z+
9
lpm  r24, z+
10
lpm  r25, z+
11
ret
12
.endif

Diese Funktion gibt in den Registern r25:r24:r23:r22 die AppVersion 
zurück.
In Special.inc muß dann am Ende die Vektortabelle geändert werden:
1
.if UseSpecialWrite || UseSpecialRead || UseSpecialMsg || UseSpecialVersion
2
bjmp  getappversion, UseSpecialVersion
3
bjmp  getbootmsg, UseSpecialMsg            bjmp  readflash, UseSpecialRead
4
bjmp  writeflash, UseSpecialWrite
5
bjmp  dospm, BLS
6
rjmp  bootstart
7
.elif UseSpecialBootVect
8
.if BLS
9
rjmp  dospm
10
.endif
11
rjmp  bootstart
12
.endif

Nun noch UseSpecialVersion als Define in AVRootloader.asm eintragen und 
die Codegrößenberechnung am Anfang von Datei Special.inc erweitern.

In AVRootloader.h dann folgende Erweiterungen
1
static inline uint32_t get_appversion(void) __attribute__((always_inline));
2
3
#define GETVER_VEC      FLASHEND -11
4
5
uint32_t get_appversion(void) {
6
    unit32_t (*proc)(void) = (void*)GETVER_VEC;
7
    return proc();
8
}

Vorteil dabei ist es das wenn man UseSpecialRead=0, UseSpecialWrite=0 
setzt ,so denoch auf einheitlichem Wege über den Bootloader an die 
Version herankommt und dabei weniger an FLASH im Bootloader wie auch in 
der eigenen Anwendung verbraucht.

Hm, ich weise nur ungern darauf hin das ich mich wiederhole. Alle diese 
Informationen findet man wiederholt hier im Thread erklärt. Ich nehme 
also an das ich nicht in der Lage bin einen Sachverhalt verständlich zu 
erklären oder meine ausführlichen Erklärungen nicht ordentlich gelesen 
werden ;)

Gruß Hagen

von Thomas K. (muetze1)


Lesenswert?

Hallo Hagen!

Nein nein - das mit der AppVersion hatte ich auch schon so probiert, um 
die neue Version zu setzen. Ich war mir nur nicht sicher, ob es der 
richtige Weg ist, da er bei mir immer wieder eine andere Versionsnummer 
zurück bekommen. Von daher war ich am zweifeln, ob das setzen so richtig 
ist. Von daher wollte ich nur eine Bestätigung, dass die Version so 
gesetzt wird (hatte ich ja auch so beschrieben zwei Beiträge von mir 
zuvor), nur das ich den Teil mit Masked = true etwas missverständlich 
dargelegt hatte - obwohl ich es schon so verstanden hatte wie du es 
zuvor und danach erneut beschrieben hast.

Und mit der AppVersion setzen habe ich nach nun schon dreimaligen 
Lesen des gesamten Threads nie eindeutig rauslesen können, da es immer 
nur im Zusammenhang mit ACY bzw. vor allem verschlüsseltem Bootloader 
genannt wurde, aber nie für unverschlüsselte Bootloader. Ich hatte es ja 
schon richtig vermutet und wollte dies nur bestätigt haben, nur leider 
hattest du den ganzen anderen Teil nochmals ausführlich erklärt...

Es tut mir leid wenn es zu Missverständnissen gekommen ist. Und ich 
entschuldige mich auch, wenn ich die Fragen vllt. ungenau stelle. Ich 
habe diesen Thread nun schon dreimalig komplett gelesen und versuche 
von daher nur noch offene Dinge zu fragen.

Danke nochmals für das Beispiel mit der Anpassung des Bootloaders. Ich 
hoffe ich kann den Bootloader dann als ganzes (u.a. mit angepasstem Code 
von dir) mit beilegen.

Aber ich denke auch, dass ich keine weiteren Fragen haben werde.

von Hagen R. (hagen)


Lesenswert?

Hey schon gut, wollte mal nur Luft rauslassen ;)

Die AppVersion wird durch dynamisches Patchen des HEX Files 
programmiert. Geht auch garnicht anderst, da ansonsten wegen den 4 Bytes 
im Bootloader eine ganze FLASH Page erst gelesen dann im Speicher 
geändert und wieder programmiert werden muß. Um also nicht eine solche 
zusätzliche Funktion in den AVR Bootloader programmieren zu müssen, oder 
eine FLASH Auslesefunktion im Protokoll zur Verfügung stellen zu müssen 
(Sicherheitsproblem), habe ich eben den Weg gewählt die AppVersion nur 
im Zusammenhang mit dem Programmieren der eigenen Anwendung aus dem HEX 
setzen zu können.

Die .GetAppVersion(True) wird nur aufgerufen wenn ein HEX File zu einem 
ACY verschlüsselt werden muß. Ob dies als Datei gespeichert wird hängt 
nur davon ab ob der Compile Button gedrückt, .Methode .DoCompile() 
aufgerufen wurde oder der Program Button gedrückt, .Methode .DoProgran() 
aufgerufen wurde.
Intern erzeugt die Software also in jedem Falle ein ACY als 
Speicherstruktur die entweder wie ein Script sofort ausgeführt oder als 
Datei gespeichert wird. Ob dieses ACY Script nun verschlüsselt oder 
unverschlüsselt erzeugt wird hängt vom Feature des Bootloaders im AVR 
ab. Je nachdem wird also .GetAppVersion(TRUE) aufgerufen oder nicht.

Hoffe das dies verständlicher rüber kommt, kenne solche 
Kommunikationsprobleme zur Genüge in meiner täglichen Arbeit ;)

Gruß Hagen

von Thilo M. (Gast)


Lesenswert?

Hi Hagen,
betrifft
>@ Hagen Re:

>Ich hab' jetzt nicht den ganzen langen Thread durchforstet, daher frag'
>ich dich einfach:
>entweder habe ich Tomaten auf den Augen oder ich check's nicht, aber
>dieselbe Einstellung wie auf dem Bild funktioniert auf mehreren mega644P
>problemlos, '.inc' - File vom mega32 aktiviert (644 deaktiviert) läuft
>nicht auf dem mega32 (16MHz) (siehe Protokoll). Benutzt wird RS232 mit
>max232, µC und Verbindung ist OK.

>Kannst du mir sagen was ich übersehen habe?

Habe den Fehler gefunden.
Es lag am USB-RS232-Treiber (FTDI-Chipsatz). Trotz der selben Hardware 
läuft der Treiber auf einem anderen Notebook nicht mehr sauber. Mit dem 
ursprünglichen Notebook funktioniert alles prima.

Ich hoffe das hilft dir, falls ähnliche Fragen in dieser Richtung 
kommen.

Gruß Thilo

von Thilo M. (Gast)


Lesenswert?

Kleiner Nachtrag:
durch setzen der CKOPT - Fuse lässt er sich jetzt auch mit allen 
USB-RS232 Adaptern programmieren. Irgendwie scheint die Startup-Zeit 
(Quarz-Anschwingen) nicht ganz gepasst zu haben.

von Rudolf S. (rudolfschenker)


Lesenswert?

Hallo,
Versuche leider ohne Erfolg, beim starten des Bootloaders Pin6 von PortD 
dauerhaft auf Low zu ziehen, muss dazu sagen das ich nicht wirklich viel 
Ahnung von ASM habe schreibe meistens alles in C
1
.org BootStart
2
init:  
3
    ldi r16, 0xFF
4
    cli
5
    xwdr
6
    clr    zerol
7
8
    ldi    cmdl, byte1(RamEnd)
9
    xout  SPL, cmdl
10
11
;portd pin6 auf low
12
ldi     r16, 0b01000000
13
out     DDRD, r16
14
cbi     PORTD, 0b0000000   ; turn on LED
15
ldi r16, 0xFF

von Hagen R. (hagen)


Lesenswert?

1
.org BootStart
2
init:  
3
    cli
4
    xwdr
5
    clr    zerol
6
7
    ldi    cmdl, byte1(RamEnd)
8
    xout  SPL, cmdl
9
10
;portd pin6 auf low
11
    sbi    DDRD, PD6
12
    cbi    PORTD, PD6
13
14
; PORTD PIN6 auf High
15
    sbi    PORTD, PD6

Register r16 ist benutzt für paral, kannst du an dieser Stelle nutzen, 
solltest du aber im weiteren Source unterlassen.

Gruß Hagen

von rubiktubik (Gast)


Lesenswert?

Hallo,

Gute Arbeit mit dem Bootloader, Hagen! Funktioniert sehr gut!

Jetzt habe ich mal eine Frage:

Ich habe mir einen Asuro Roboterbausatz gekauft wo ein
Atmega8 drauf ist. Diesen Atmega8 kann man beim Asuro mit Infrarot
programmieren.
Die Entwickler habe da einen Bootloader draufgepackt der das 
Programmieren
per Infrarot möglich macht.

Dieser Bootloader ist aber nicht quelloffen und nur für Atmega8.

Ich habe nun diesen Asuro Roboter durch einen Atmega32 erweitert und mit 
einer ISP und RS232 Schnittstelle bestückt.

Auf dem Atmega32 ist AVRootloader drauf und das Programmieren über die
RS232 Schnittstelle funktioniert sehr gut.

Ich wollte nun deinen Bootloader so erweitern das ich die TX Signale 
über Infrarot sende. Dafür ist eine Infrarot-LED mit dem TX-Port und 
einem Timer-PIN vom Atmega32 verbunden.

Über den Timer-PIN wird 36khz Frequenz moduliert und über den TX-PIN 
kommen ganz normal die TX-Daten.

Wenn ich jetzt ein Programm schreibe wo ich etwas über IR-Senden will, 
aktiviere ich nur die Modulationsfrequenz und sende die Daten ganz 
normal über UART. Und es klappt Hardwaremäßig auch!

Damit das ganze funktioniert habe ich mir gedacht das ich im Bootloader 
nur die Modulationsfrequenz am OC2 aktivieren muss damit das ganze auch 
über IR läuft. (Denn die TX-Daten sollten ja genauso wie bei einer 
Kabelverbindung kommen.Oder?)

Ich habe das ganze eingefügt aber es funktioniert nicht? Was mache ich 
falsch? (Wie gesagt über Kabel funktioniert das ganze!)

Hier die Änderung im Quellcode:
1
.include "AVRootloader.inc"
2
;.listmac
3
.list
4
5
6
.org BootStart
7
;Vorher .def temp=r27
8
;----------------------------------------------
9
ir:  
10
  ldi temp,TCCR2
11
  ldi temp, (1 << WGM21) | (1 << COM20) | (1 << CS20)
12
  out TCCR2,temp ;Timer2 Register
13
  ldi temp,0x6e ;36Khz einstellen
14
  out OCR2,temp
15
  sbi DDRD,7
16
;--------------------------------------------------------  
17
  
18
init:  cli
19
  xwdr
20
         ......usw.

von Hagen R. (hagen)


Lesenswert?

@rubiktubik:

Das wird leider so nicht funktionieren. Der Bootloader benötigt eine 
bidirektionale Verbindung und deine IR Strecke geht ja nur in eine 
Richtung.
Du könntest alle Sendedaten im Bootloader in's Leere laufen lassen und 
nur die Empfangsdaten berücktsichtigen, das würde gehen, mit der 
Einschränkung das alle Lesefunktionen wie EEPROM oder SRAM lesen nicht 
mehr gehen. Auch dein IR Sender müsste von Anfang an exakt wissen für 
welchen AVR die gesendeten Daten bestimt sind da die vom AVR gesendeten 
Daten -> BootInfo nicht empfangen werden können.

Auf alle Fälle ist es mit dem Stückchen Code nicht getan und ehrlich 
gesagt verstehe ich auch garnicht was du damit bezwecken möchtest.

Was hast du denn für Software auf der IR Sendeseite ? Falls du es mit 
dem Asuro Bootloader probiert hast dann kann das garnicht funktionieren. 
Du müsstest mir schon deinen kompletten Aufbau erklären damit ich dir 
weiterhelfen kann.

Gruß Hagen

von rubiktubik (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Der Sinn der Sache ist das ich meinen Asuro per Infrarot programmieren 
kann.
Normalerweise ist im Asuro der Atmega8. Mit diesem kann die 
Asurosoftware IR-Software was anfangen.

Beim Atmega8 funktioniert das ganze so, dass auf eine IR-LED eine 
Modulationsfrequenz und ein TX Signal gegeben wird. (Siehe Anlage und 
Asurowiki)

Ich habe jetzt einen Atmega32 an den Asuro gebaut.
Auf dem Atmega32 habe ich deinen Bootloader drauf und ich kann per 
Kabelverbindung(RS232) den 32er programmieren.

Ich mir das so gedacht das:
Dein Bootloader sendet auch über TX und RX.
Das heisst das ich nur noch
im Bootloader die Modulationsfrequenz aktivieren muss und das gleiche 
Signal was normalerweise durchs Kabel geht, geht jetzt durch IR.

Das was der Bootloader macht ist ja das Senden der Daten über RX und TX.
Wo die letzendlich durchgehen(Kabel oder Infrarot) ist dann egal.

Was ich natürlich nicht bedacht habe, ist das deine Windowssoftware zum 
erkennen eines gültigen(CONNECTED) Signals auch eine RX Leitung 
benötigt.

Wenn ich die RX-Leitung auch noch über IR verbinde müsste es doch gehen?

Hier die Asuroseite für die Asuroseite:
http://www.asurowiki.de/pmwiki/pmwiki.php/Main/Infrarotschnittstelle

Und die PC-Seite
http://www.asurowiki.de/pmwiki/pmwiki.php/Main/InfrarotRS232Transceiver

Im Anhang: die Beschaltung der IR-LED.

von Hagen R. (hagen)


Lesenswert?

Die wesentliche Frage ist doch warum du überhaupt IR benutzen möchtest ?
Sie ist langsammer, störanfälliger und kostet dir auch noch zusätzlichen 
Aufwand.

Das was mich interessiert ist die Frage wie sieht die Gegenstelle 
hardwaretechnisch aus. Deine Links sind gut&schön aber wenig hilfreich 
für mich um sehr schnell einen Überblick zu erlangen. Immerhin kannst du 
ja nicht verlangen das ich mich jetzt Stunden mit deinem Problem befasse 
noch dazu wenn ich keinen Sinn darin sehe.

Also: auf PC Seite wie wird dort der IR Port umgesetzt? Wenn er nur die 
RS232 nach IR umsetzt dann dürfte das sehr wohl gehen, denn so wie es 
aussieht hat der Asuro ja einen TSOP als Empfänger und eine IR SendeLED 
als Sender integriert. Es geht also halbduplex bidirektional.

Du solltest den ATMega32 mit externen Quarz betreiben, UseAutoBaud=0 und 
BootBaudrate=2400 setzen. Eventuell musst du UseUartInvert=0 oder 1 
anpassen je nach Pegel die vom TSOP ankommen. Auch die Anschaltung der 
IR-SendeLED ist entscheidend also an welchem Pin deren Anode hängt. Wenn 
das mit den Pegeln korrekt eingestellt wurde dann sollte das sogar 
funktionieren.

Entscheidend ist die PC Seite. Am besten einen RS232 zu IR Umsetzer 
damit du meine PC Software benutzen kannst.

Mal angenommen die Probleme mit den richtigen Pegeln, Baudrate, PC-Seite 
mit RS232<->IR Wandler sind gelösst dann wird das auch funktionieren. 
Denn der Rest ist eine halbduplex bidirektionale Kommunikationsstrecke 
und das benutzte Protokoll des Bootloaders unterstützt diese 
Kommunikationsart. Dh. in deinem Falle könntest du zb. auch das EEPROM 
lesen und schreiben über IR.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Hab gerade den PC teil gefunden. Scheint ja nicht so sauber zu 
funktionieren und die Hardware ist ja wirklich einfachst und damit 
störanfällig aufgebaut.
Probier es, aber empfehlen würde ich dir sowas nicht da es nicht als 
"professionell" zu bezeichnen ist. Mit viel Fuggelei ist es aber 
sicherlich zum Laufen zu bekommen.

Wenn ich das richtig sehe so musst du UseUartInvert=0 setzen, also mit 
physikalischen Pegeln der RS232 arbeiten.

Öffne AVRootloader.ini und setze dort [Timeouts].Option = 1 damit du in 
der PC-Software siehst was empfangen wird bei einem Connect.

Vom Aufwand her, der Stabilität usw. würde ich dir ja den RS232-1-Wire 
Modus des Bootloaders empfehlen. Der geht bis maximale Baudrate sauber 
und wie im 1-Wire.png Schematik zu sehen ist benötigt der auch 
wesentlich weniger Bauteile. Auf deinem Board benötigst du dann nur 
einen 2-Pin Stecker.

Gruß Hagen

von rubiktubik (Gast)


Lesenswert?

Hallo,
Danke für die schnelle Antwort.
Es ist mir klar, dass das mit Infrarot nicht
gerade die beste Lösung ist.

Ich habe bei meinem Asuro auch ein paar Änderungen am Sender und 
Empfänger
gemacht um das Signal sauberer und stabiler zu Übertragen.

Der Sinn der Sache ist der das ich beim Programmieren immer ein Kabel an
den Asuro anschliessen muss. Wenn ich also kurz was testen will, muss 
ich das Kabel anschließen, programmieren und zum ausprobieren wieder 
abschliessen.
Beim nächsten Test (z.b. Ein Wert im Programm geändert) muss ich wieder 
das Kabel anschliessen usw.

Was es beim original Atmega8 IR-Flashprogramm noch gibt ist die 
Funktion:

"Transfer only new pages"

ich denke mal das er nicht die ganze Datei komplett überträgt sondern 
nur kleine Teile die sich geändert haben z.b. ein Wert einer Variable.
Dann ging das Programmieren recht schnell.

Ich weiss nicht wie das bei dir funktioniert!?

Aber danke für die Tipps!

von Hagen R. (hagen)


Lesenswert?

Eine solche Funktion ist nicht implementiert wobei das Protokoll sowas 
unterstützt. Dh. man müsste nur die PC Software leicht umschreiben um 
sowas ebenfalls zu unterstützen der komplette Rest der Software könnte 
es jetzt schon.
Das Problem mit einer solchen Funktion ist das auf der PC Seite die alte 
HEX und das neue HEX vorliegen müssen. Denn nur so kann die PC Seite 
ohne den FLASH erneut auslesen zu müssen die Differenzen zwischen Alt 
und Neu ermitteln. Aus meiner Sicht hat eine solche Vorgehensweise aber 
gravierende Probleme die man erstmal sauber lösen muß.
1.) was ist wenn das alte HEX File nicht mit den Daten im FLASH 1 zu 1 
übereinstimmt ?
Die Bootloader Software würde bei der Übertragung der Differenzen somit 
eher den AVR und dessen Program zerstören. Das müsste nun extra 
abgesichert werden. ZB. per Prüfsummen über den FLASH Inhalt der durch 
die PC Seite abgefragt wird. Diese Prüfsumme wird abgefragt jeweils vor 
dem Programmieren um zu erkennen ob das angegebene alte HEX File auch 
wirklich mit dem FLASH übereinstimmt und auch nach dem Programmieren um 
zu überprüfen ob der neue FLASH Inhalt auch 1 zu 1 mit dem neuen HEX 
File übereinstimmt. Nun, Prüfsummen haben aber ein Problem denn es gibt 
defakto keine Prüfsumme die zb. 16Kb FLASH mit 100% Sicherheit abprüfen 
kann. Die einzige Prüfsumme die das kann würde ebenfalls 16Kb groß sein 
und damit 1 zu 1 der FLASH Inhalt den man erwarten würde.
2.) Sicherheitsproblematik. Eine solche Funktion öffnet einem Abgreifer 
eine Tür die er für seine Angriffe ausnutzen könnte. Da mein Bootloader 
aber exakt diese Sicherheitsproblematik lösen soll wäre ein solches 
Vorgehen also indiskutabel. Hier muß man abwägen zwischen dem einen und 
dem anderen Feature das man sich wünscht.
3.) "Transfer only new Pages". Die Wahrscheinlichkeiten im Alltag ! Ich 
meine damit den Punkt das die Wahrscheinlichkeiten im Alltag so gelegt 
sind das wenn sich eine Page verändert sehr häufig alle nachfolgenden 
Pages ebenfalls ändern. Da dadurch zb. viele Funktionsadresse im HEX 
reallokiert/verschoben werden und somit auch zb. die ISR EInsprungpunkte 
sich verändern ist die Wahrscheinlichkeit sehr hoch das sich die ersten 
FLASH Pages ändern und auch alle nachfolgenden. Das ist aber nur eine 
Vermutung meinerseits und man müsste dies erstmal praktisch ermitteln. 
Was ich aber damit aussagen möchte ist das ich meine das eine solche 
Funktion im Alltag der Programmierung eher weniger als mehr Sinn macht.
4.) was ist mit Anwendungen die sich selbst modifizieren können. Dh. 
also solchen Anwendungen die veränderliche Daten im eigenen FLASH 
abspeichern können. Nungut, mit solchen Anwdendungen hätte man eh ein 
grundsätzliches Problem auch mit meinem Bootloader der diese Daten 
einfach überschreiben würde. Mit der hier diskutierten Funktion und der 
Problematik einer Prüfsumme über den FLASH würde das dann dazu führen 
das die PC Seite die korrekte alte HEX Datei als ungültig erkennen würde 
und das Programmieren somit verweigert.

Im gewissen Sinne ist diese Funktionalität also eher eine Augenwischerei 
um den vorher gebauten Schaden durch die Wahl der IR Schnittstelle 
abzuschwächen. Alles in Allem also aus meiner Sicht viele Indizien die 
ihre eigene Sprache sprechen. Ich möchte das wirklich nicht schlecht 
machen aber mal pragmatisch darüber nachgedacht sollte man schon zu 
ähnlichen Gedanken kommen.

Du sprachst die Problematik an das du jedesmal einen Stecker dranstecken 
möchtest. Nun was für einen Unterschied macht es mit dem IR-Dongle auf 
wenige Zentimeter heran gehen zu müssen um mit 75% Wahrscheinlichkeit 
ein neues Program flashen zu können ? Das dann mit 2400 Baud statt mit 
115200 Baud, mit höherer Fehlerwahrscheinlichkeit. Ich für meinen Teil 
erwarte von einem Bootloader als aller erstes und wichtigstes 
"Stabilität".

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Für 20 Euro würde ich daher ein fertiges Bluetooth Dongle kaufen das 
RS232 unterstützt. Das drangepappt an die RS232 des AVRs und auf 
PC-Seite über einen virtuellen COM Port gearbeitet. Schon erledigen sich 
mit wenig Investitionen all deinen Probleme ;) Wenn du noch den RTS Pin 
am RESET des AVRs anschließt ist es eine Frage von 5 Minuten um die 
Konfiguration der Bootloader Software anzupassen, und schwups brauchst 
du noch nichtmal irgendeinen Taster auf dem Asuro drücken um die neue 
Software aufzuspielen.

Gruß Hagen

von Fabian (Gast)


Lesenswert?

Hallo Hagen,

ich versuche gerade ein kleines Kommanadozeilen-Tool unter Linux zu 
basteln welches EE-Prom-Daten über den Bootlader lesen und schreiben 
kann.

Evtl. schalte ich da noch ein graf. Frontend davor.

Das Lesen geht schon, aber nur weil ich die Sache mit der CRC hier 
ignorieren kann bzw. fixe Werte setzen kann.

Leider komme ich mit der 16Bit CRC arg ins schleudern.

Was ist denn das nun genau für ein Algo?  Gibt es einen init-Vector und 
einen finalen Vector?
Aus dem AVR-ASM werde ich nur bedingt schlau.
Meine C-Routine wirft mit dem Polynom 0xA001 bzw. 0x8005 und 
verschiedenen Anfangswerten immer was Anderes raus. :-(
Ist da noch ein Trick dabei oder übersehe ich da was?


Gruß

Fabian

von Hagen R. (hagen)


Lesenswert?

InitVector = 0x0000
FinitVector = 0x0000
Polynom = 0xA001

Die empfangene CRC einfach mit durch den CRC Algo jagen und es muß 
0x0000 rauskommen.
1
uint16_t crc_update(uint16_t crc; uint8_t data) {
2
3
  crc ^= data;
4
  for (i=8; i>0; i--) {
5
    if (crc & 1) {
6
      crc >>= 1;
7
      crc ^= poly;
8
    } else {
9
      crc >>= 1
10
    }
11
  }
12
  return crc;
13
}

das ist der vereinfachte code.

Gruß Hagen

von Fabian (Gast)


Lesenswert?

Hallo Hagen,

vielen Dank für den Hinweis und deine Mühen!

Werde das mal vergleichen.

bei diesem(deinem) Code wird schonmal anders herum geschoben...
(Daher auch mein gespiegeltes Polynom)

Denke damit komme ich klar.


Gruß

Fabian

von Fabian (Gast)


Lesenswert?

Hallo Hagen,

ich nochmal kurz:

Damit scheit es zu gehen zumindest stimmt mal eine Summe.
Kann dein Kurzer Blick ein OK geben?
Optimieren kann man ja immer noch...

uint16_t crc16(unsigned char* data, int length, uint16_t crc)
{
  uint16_t poly = 0xA001;
  int c, i;
  for (c = 0; c < length; c++)
  {
    crc ^= data[c];
    for (i=8; i>0; i--)
    {
      if (crc & 1)
      {
        crc >>= 1;
        crc ^= poly;
      }
      else
      {
        crc >>= 1;
      }
    }
  }
  return crc;
}


Vielen Dank und viele Grüße


Fabian

von Hagen R. (hagen)


Lesenswert?

@Fabian, sieht korrekt aus.

Ich würde es aber so machen:
1
uint16_t crc16(unt16_t crc, const uint8_t* data, uint16_t length)
2
{
3
  uint16_t poly = 0xA001;
4
  while (length--)
5
  {
6
    crc ^= *data++;
7
    for (uint8_t i=8; i>0; i--)
8
    {
9
      if (crc & 1)
10
      {
11
        crc >>= 1;
12
        crc ^= poly;
13
      }
14
      else
15
      {
16
        crc >>= 1;
17
      }
18
    }
19
  }
20
  return crc;
21
}

Das dürfte dem Compiler bei der Optimierung auf die Sprünge helfen. 
Idealerweise uint16_t crc -> R25:R24 und damit von Anfang an im Result, 
data in R23:R22 wird nach R31:R30 = Z per MOVW kopiert und später mit LD 
temp, Z+ bei crc ^= *data++ compiliert. length in R21:R20 kann im Kopf 
der while Schleife erstmal subiw R21:R20 dekreetiert werden und da 
unit16_t, also ohne Vorzeichen würde das Carry Flag die Abbruch 
Bedingung darstellen.
Am Ende wird crc da es schon in r25:r24 steht direkt als Resultat 
zurückgegegen. In der innersten Schleife dekremtieren wir i was dem 
WinAVR mit Sicherheit zu einem besserem Code verhilft.
ABER! das ist das was ich als Programmierer vom WinAVR GCC verlangen 
würde, erwarten würde ich dagegen das er erstmal kein MOVW benutzt, er 
die wihle Abfrage umständlicher lösst, er data nicht in X,Y,Z optimiert 
und damit kein LD mit Postinkrement des Zeigers macht, er am Ende CRC 
nach r25:r24 doppelt umkopiert ;)

Macht man es in Assembler so könnte es so aussehen:
1
; r25:r24 CRC, r23:r22 data, r21:r20 Length
2
  movw ZL, r22
3
  ldi  r23, hi8(0xA001)
4
  ldi  r22, lo8(0xA001)
5
@loop:
6
  sbiw r20, 1
7
  brcs @exit
8
  ld   r0, Z+
9
  eor  r24, r0
10
  ldi  r19, 8
11
@crc:
12
  lsr  r25
13
  ror  r24
14
  brcc @skip
15
  eor  r25,r23
16
  eor  r24,r22
17
@skip:  
18
  dec  r19
19
  brne @crc
20
  rjmp @loop 
21
@exit:
22
  ret

Gruß Hagen

von Fabian (Gast)


Lesenswert?

Hallo Hagen,

vielen Dank für deine optimierungs Tipps.

Da der Algo zunächst ausschließlich unter Linux/PC laufen wird, ist das 
mit dem Optimieren (solage es keine geliebte lib-Funktion wird) nicht so 
extrem heilig.
Trotzdem sind deine Tipps für mich interessant da ich AVR-Seitig 
tatsächlich viel mit dem AVR-GCC (allerdings auch hier unter Linux ;-)) 
arbeite.
Ich denke, dass die Umstrukturierung auch dem Linux-GCC auf die Sprünge 
helfen wird (werde mir das mal anschauen).

Ich finde es toll, dass es offensichtlich doch noch Leute gibt, die sich 
den Assembler-Output regelmäßig anschauen um unnötige Code-Mengen und 
Laufzeiten gliech mal im Keim zu minimieren!

Ach ja das Tool läuft nun! Die Summe wird nicht nur einmal korrekt 
berechnet ;-)

Da fällt mir noch eine kleine Frage ein:

Kann man mit dem Delphi-Tool in der Kommandozeile einzig nur das EE-Prom 
schreiben und lesen jeweils über Hex-Dateien ohne dass das Flash 
angefasst wird?

Das würde mir das Kompilieren des geschriebenen Tools in einer 
Linux-Emulation unter Windows(mingw od. Cygwin) ersparen. Meine Versuche 
haben immer dazu geführt dass immer das Flash mit programmiert wurde.


Nochmals vielen Dank für die Unterstützung!


Fabian

von Hagen R. (hagen)


Lesenswert?

>Kann man mit dem Delphi-Tool in der Kommandozeile einzig nur das EE-Prom
>schreiben und lesen jeweils über Hex-Dateien ohne dass das Flash
>angefasst wird?

Müsste eigentlich gehen. Du musst als Flashfile dann einen Leerstring 
angeben, zb. so

AVRootloader.exe -PCOM1 -B115200 -Dc:\test\ -EMy.EEP -F -Apc

Allerdings eben nur schreiben, das Lesen ist nicht vorgesehen. Diese 
Funktion habe ich gleichmal in die ToDo Liste aufgenommen da ich 
anscheinend diese Funktion übersehen habe einzubauen.

Du bist also an einem Linux Kommandozeilen Tool am schreiben. Wird dies 
alle Funktionen meiner PC-Software umsetzen oder nur den EEPROM lesen 
und schreiben ? Ich wäre nämlich daran interssiert das unter Linux alle 
Funktionen des Bootloaders unterstützt werden.

Gruß Hagen

von Fabian F. (fabi1973)


Lesenswert?

Hallo Hagen,

für meinen Anwendungszweck muss ich das EE-Prom auch lesen können(read 
modify write).

Zunächst habe ich (auch aus zeitlichen Gründen) nur vor das EE-Prom zu 
unterstützen (Funktional geht das aber derzeit nur mit 512Bytes auf nem 
Atmega168 bei fixer Baudrate von 19200).
Da ich mit dem PortMon einfach nachgeguckt habe, was dabei abgeht und 
erst dadurch step by step interpretiert habe was jeweils im einzelnen 
passiert ist der erste Ansatz super quick n dirty... Allerdings bin ich 
gerade etwas am Aufräumen und Umstrukturieren. Ein Update des Flashes 
wäre eigentlich langfristig durchaus interessant auch für meinen 
Anwendungsbereich.

Dann habe ich gestern Abend noch wxWidgets näher beleuchtet... da gibts 
auch Designer dazu um Frontends zu "Malen".
Mein bisheriges GUI für den speziellen Anwendungsbereich ist noch in 
GTK+ flach in C implementiert und kommuniziert nun über Dateien mit dem 
Kommandozeilentool.

Meine zur Verfügung stehende Zeit ist aber (leider) eher Begrenzt, daher 
ist es ungewiss wie weit ich da noch weiter komme.

Als Kommunikation mit der Seriellen habe ich mir den AvrDude Code 
serial_posix.c genommen um schnell zum Zug zu kommen. Das passt aber 
teilweise auch nicht so ganz in meine Vorstellung, funktioniert aber.

Für die Parameter wollte ich noch wenigstens "optarg" (eine lib) 
einbauen um hier wenigstens etwas sauberer zu werden.


Gruß

Fabian

von Rudolf S. (rudolfschenker)


Lesenswert?

Hallo,
ich bekomme ab und an diese fehlermeldung,
nach 6-7mal versuchen geht es dann einwandfrei,
ich benutze bluetooth spp.

gruss rudolf.

 > Connecting on port COM4...
 > Device connected
 > Program...
 > execute compiled data
 > selected options in compiled file:
 > - programming FLASH
 > - FLASH data are encrypted
 > - erase FLASH during programming
 > Cmd.SetAddr.ReadByte() ICOM: read error.
 > Device disconnected

von Hagen R. (hagen)


Lesenswert?

@Rudolf:

sieht nach Timing Poblemen aus. Da du über BT gehts und bisher du der 
Erste bist kann man schwer konkrete Tipps geben. Der Bluetooth Stack 
unter Windows ist ebenfalls so eine "Krücke" wie viele der USB-RS232 
Treiber. Ich empfehle dir also mal die Werte in der AVRootloader.INI bei 
[Timeouts] zu erhöhen. Anfangen mit dem Wert Base=50 und diesen mal auf 
100 setzen.

Beim nächsten Mal bitte mehr Angaben posten, ist bischen dürftig deine 
Fehlermeldung. Dazu erstmal in AVRootloader.ini [Timeouts] Options=1 
setzen.
Diese Debugoption wird im Protokollfenster mehr Infos anzeigen lassen, 
wie zb. auch die Baudrate, den AVR, ob 1-Wire oder 2-Wire usw. die du 
benutzt und hier leider nicht verraten möchtest. Übrigens, da mit dieser 
Debug-Option düfte jetzt seinen 50'zigsten Geburtstag feiern, also 
zumindestens so oft wurde das hier im Thread schon besprochen ;)

Gruß Hagen

von Thilo M. (Gast)


Lesenswert?

Bei mir lag's daran, dass der Quarz nicht recht anschwingen wollte und 
daher keine vernünftige Reaktion vom µC kam.
Setzen der CKOPT-Fuse brachte Abhilfe.

von H.Joachim S. (crazyhorse)


Lesenswert?

Hallo Hagen,

jedes Kind bekommt neue Wünsche :-)
Siehst du irgendeine Möglichkeit, das Ganze auch über CAN zum Laufen zu 
bringen? Ist leider die einzige Schnittstelle, die ich habe.

PC<->CAN-Dongle<->CAN-Bus<->MCP2515<->Mega32

von Hagen R. (hagen)


Lesenswert?

CAN ist physikalisch RS485 ähnlich. RS485 wurde schon praktisch 
umgesetzt. Das verbleibende Problem beim CAN wie auch zb. DMX ist die 
Protokollschicht. Wenn du die Möglichkeit hast den "normalen 
Protokoll-Betrieb" temporär zu deaktivieren und solang der Bootloader 
arbeitet auch deaktiviert zu belassen, dann geht mein Bootloader relativ 
einfach für diese Systeme anzupassen.

Ich empfehle immer folgende Vorgehensweise:
PC-Software möchte einen AVR flashen und sendet das AppCmd aus der INI. 
Dieses AppCmd wurde als CAN/DMX etc.pp. Packet formatiert. Es aktiviert 
in allen AVRs einen Silent-Mode. Dieser Mode deaktiviert das normale 
Protokoll und bleibt solange aktiviert bis sich 2 Sekunden auf dem Bus 
nichts mehr gerührt hat (automatische Umschaltung in den normalen 
Protokollmode).
Wurde das AppCmd empfangen so starten alle AVRs ihren Bootloader.
Jeder AVR hat ein eigenes BootSign und auf das wird nur lesend im 
Bootloader gewartet. Wurde das richtige BootSign empfangen startet der 
eine AVR seinen Bootloader durch und übernimmt die Kontrolle über den 
Bus. Alle anderen AVRs starten nach einem Timeout ihre normale 
Applikation durch. Diese setzt ihren Receiver/Driversource bei einem 
RESET in den Silent-Mode, warten also die 2 Sekunden Ruhe auf dem Bus 
ab.
Mein Bootloader wird innerhalb von 2 Sekunden (WDT Timeout) solange er 
connected ist immer irgendwas über den Bus senden. Dh. wurde 2 Sekunden 
lang nichts über den Bus gesendet dann heist dies eindeutig das die 
Connection getrennt wurde und der Bus wieder frei ist.

Ergo braucht man nur ein Start Kommando und das wäre in diesem Falle das 
konfigurierbare AppCmd. Ein Stop Kommando ist nicht nötig durch den 2 
Sekunden Timeout und dieser stellt auch sicher das sich nicht alles 
irgendwie tot rennt, eg. blockiert.

Statt mit dem BootSign als eindeutige ID zu arbeiten geht das natürlich 
auch mit zb. der CAN Node ID. In diesem Moment müsste aber das AppCmd 
dynamisch um diese ID ergänzt werden so das nur die AVRs in ihren 
CAN-Drivern den Bootloader starten mit der gleichen ID. Das würde eine 
Änderung in meiner PC-Software bedeuten. Der erste Vorschlag würde nur 
eine Änderung in deiner Applikationsoftware, eg. CAN Driver, bedeuten.

Wir gehen also von folgendem aus:
- AVRs haben schon deine Anwendung drauf
- Anwendung enthält einen CAN Driver
- CAN Driver hat einen Silent-Mode in dem er nur wartet bis der Bus 2 
Sekunden still ist, danach akzeptiert er wieder CAN Packete
- CAN Driver wartet auf AppCmd Packete und startet Silent Mode und 
Bootloader
- aus dem RESET startet die Anwendung den CAN Driver im Silent Mode
- AVRs haben lange und unterschieldiche BootSigns
- Bootloader und CAN benutzen gleiche Baudrate

Somit wird wenn es der PC-Bootloader signalisiert der komplette Bus 
unter Kontrolle des Bootloader gesetzt und dann läuft darüber eine 
einfache RS232/RS485 halbduplex Kommunikation.

Im Falle das auf dem AVR noch nicht deine Anwendung geflasht wurde wird 
der Bootloader die ganze Zeit nur lauschend am Interface hängen. Bis er 
das Bootsign empfangen hat. Also auch nur ein geringes Risiko von 
Bus-/Protokollkonflikten.

Wie und ob das mit einem intelligenten CAN-Treiber geht kann ich nicht 
beurteilen. Wichtig ist nur das er das AppCmd Packet erkennt, dann durch 
AVR deaktiviert wird, er also alle Daten 1 zu 1 durchlässt.

Ich weiß das dies nicht der beste Vorschlag sein kann, aber es ist auf 
jeden Fall der am einfachsten zu realisierende Vorschlag mit den 
geringsten Änderungen. Besser wäre die PC-Software umzuschreiben und an 
das jeweilige Protokoll anzupassen. Aber das bedeutet Aufwand und in 
meinem Falle auch die nötige Hardware um das alles zu testen. Mal 
abgesehen von meiner Zeit ;)

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Sehe gearde das der MCP2515 ein CAN->SPI Wandler ist. Das dürfte dann 
schwieriger sein da die AVR Bootloader Software umgeschrieben werden muß 
auf SPI statt RS232/RS485. Würde man ohne das CAN Protokoll, eg. Frames 
und Packets, arbeiten können wäre diese noch relativ einfach möglich. 
Denn dazu müsste man nur die Pin/Ports und UART Routinen getc/putc 
umschreiben. Dh. sowas wäre dann wie bei einem UART->SPI Wandler Chip 
der 1 zu 1 die UART auf SPI mappt.

Gruß Hagen

von Sven K. (Gast)


Lesenswert?

Hallo Hagen,

wäre es nicht möglich drei Funktionen im PC Programm zu schreiben
und als ByteIN, ByteOUT, RTS auszuführen, die dann exportiert werden ?
Dann könnte sich jeder eine DLL schreiben, die dann einfach die
Funktionen kurz vor der Hardware auf ein anderes Interface umbiegt.
Somit müsste man nichts mehr an der PC Software ändern ?

In der Anwendung hätte man dann

procedure DLLLoad();
function ByteIN(...) : Boolean;
function ByteOUT(...) : Boolean;
function RTS() : Boolean;
procedure DLLFree();

Somit könnte man auch den CAN-Bus mit relative kleinem Aufwand
programmieren.

Gruß Sven

von Hagen R. (hagen)


Lesenswert?

@Sven:

ganz so einfach ist das leider nicht :(

Konzeptionell denke ich habe ich einen besseren Weg beschritten, der 
auch die nötige Komplexität berücksichtigt. Wer es also möchte und ein 
bischen Ahnung von ActiveX/COM/DCOM Interfaces hat kann die 
AVRootloader.DLL benutzen. Mit ihr hat man nun die Möglichkeit ein 
eigenes ICOM = Kommunikationsinterface vorzugeben. Dh. die komplette 
Bootloader Protokollschicht ist weiterhin gekapselt und für das ICOM 
Kommunikationsinterface existieren klar vorgegebene Schnittstellen die 
man nur programmieren muß.
Grundsätzlich könnte schon jetzt ein anderer Programmierer über diesen 
Weg deine simple DLL zusammenbauen.

Aber auch das wird im Falle des Problems CAN->SPI nicht wirklich viel 
weiterhelfen. Denn grundsätzlich müssten alle Daten in Packete gekapselt 
werden die mit den entsprechenden Headern versehen werden müssen. Diese 
Kapselung der Daten und die Daten in deren Headern bestimmen an welche 
CAN Node diese Packete adressiert sind.

Es muß, wenn man es wirklich richtig machen möchte, das komplette 
Bootloader Protokoll neu geschrieben werden. Sowohl die PC-Software wie 
auch AVR Software.

Das was bei deinem Vorschlag und meiner AVRootloader.DLL nämlich fehlt 
ist das Kenntlichmachen wann ein solches Packet beginnt und endet. Denn 
nur so könnte die externe DLL oder eben das custom ICOM Interface im 
AVRootloader.DLL auf Protokollebene erkenne wann ein Header mit 
Adress-/Datengröße Angaben zu erzeugen ist und wann ein Packet zu Ende 
ist und mit einer CAN/DMX Prüfsumme zu versehen ist.

Nun kommt noch das Problem hinzu das die maximale Packetgröße ebenfalls 
vom Protokoll abhängig ist. Das könnte dazu führen das ein Datenblock zu 
groß für das Protokoll ist und dann transparent durch das ICOM bzw. 
deine DLL in kleinere Packete zerstückelt werden muß. Auch hier muß man 
dann dynamisch Header/Prüfsumme davor/danach einbauen.

Schlußendlich ein Weg der die Sache nicht vereinfacht sondern 
verkompliziert im Vergleich zu einer Lösung die direkt die AVR Sourcen 
und PC Sourcen und Protokoll direkt verändert.

Ich denke für ein Hobbyprojekt hat sich mein Bootloader in eine relativ 
universelle und professionelle Richtung weiterentwickelt. Irgendwan 
kommt man aber an einen Punkt der auf Grund der ehemaligen Konzeption 
nicht mehr überschritten werden kann, bzw. es keinen Sinn macht noch 
weiter zu gehen. Nun CAN-SPI wäre wohl dieser Punkt.
Wenn es die packetbasierte und adressierbare Protokollschicht nicht gäbe 
wäre auch die Änderung auf SPI/I2C usw. im AVR Bootloader Source noch 
einfach umzusetzen. Solange die physikalische Verbindung RS232/485 
konform und auf PC-Seite ein Mapping vom virtuellen COM Port zu einem 
physikischen Dongle existiert ist das alles noch in einem vertrettbaren 
Aufwand von 1-2 Tagen umsetzbar.

Nur mal zusammenfassend was schon an Protokollen geht:
* 1- oder 2-Wire in nachfolgenden Varianten
* RS232, RS485, USB-RS232, USB-RS485, Bluetooth-RS232, TCP/IP-RS232, 
TCP/IP-RS485, DMX
* alles mit oder ohne Pegelwandler, also physikalische oder logische 
Pegel

Damit werden allen wichtigen RS-Schnittstellen unterstützt und das 
verifiziert.

Selbst IRDA müsste schon gehen.

Gruß Hagen

von H.Joachim S. (crazyhorse)


Lesenswert?

Theoretisch geht das auch über CAN Byte für Byte, man müsste eben für 
jedes Byte einen kompletten Frame schicken. Sinnvoller wäre es, die 
messages auch mit 8 Byte zu füllen.
Die Hardware-Protokollschicht zu umgehen, ist unmöglich (behaupte ich 
jetzt mal)

von H.Joachim S. (crazyhorse)


Lesenswert?

Tja, habe mir schon gedacht, dass das aufwändiger wäre :-).
Ich werde mir wohl selber bisschen was tricksen, nur mit der 
notwendigsten Funktionalität.
Ist eh nur ein Notausgang, da die ganze Baugruppe komplett vergossen 
ist.  Eigentlich ist die Software fertig, aber man kennt das - 
irgendwann findet man doch einen Bug oder eine neue Funktion, die noch 
rein soll....
Mal schauen.

von Hagen R. (hagen)


Lesenswert?

>Die Hardware-Protokollschicht zu umgehen, ist unmöglich (behaupte ich
>jetzt mal)

Das hängt eben von der Hardware ab. CAN ist RS485 kompatibel und wenn 
der CAN Controller in der MCU als Software implementiert ist dann würde 
mein obiger Vorschlg auch gehen, denke ich mir so ;) So fit bin ich im 
CAN auch nicht, was ich aber in den par Minuten überlesen habe deutet 
darauf hin.

Das grundsätzliche "Problem" meines Bootloaders ist dann eben die 
Umsetzung in Assembler. Das schränkt die Portierbarkeit eben ein. Aber 
das war konzeptionell auch nicht so vorgesehen und in der 
Prioritätenliste war die Kompaktheit des Bootloaders viel wichtiger um 
möglichst alle programmierbaren AVRs auch unterstützen zu können. Ein 
komplexeres Protokoll verbraucht auch mehr Resourcen oder ist von 
spezieller Natur und nicht mehr breitbandig von vielen Usern nutzbar, 
ist einfach so. Zweitens kommt der Punkt hinzu das ich meine PC-Sourcen 
nicht frei verfügbar machen möchte. Das hat nichts mit "auf den Sourcen 
hocken" zu tun sondern ist aus meiner Sicht auch ein "Erfolgsgeheimnis" 
warum dieses Projekt überhaupt funktionieren kann. Irgendwann werde ich 
diese Sourcen rausgeben und somit die Verantwortung der Pflege und 
Weiterentwicklung abgeben. Aber meine Erfahrung sagt mir das solche 
Projekte die möglichst sauber und schnell weiterentwickelt werden sollen 
immer eine zentrale Führungsperson benötigen. Das ist ja das Problem mit 
den vielen OpenSource Projekten die an ihren administrativen Plänkeleien 
dann schlußendlich im Chaos geendet sind. (egal ob Software oder 
Hardware Entwicklungen, beste Beispiele lassen sich sogar hier im Forum 
finden ;)

Gruß Hagen

von H.Joachim S. (crazyhorse)


Lesenswert?

CAN in Software - das macht keiner freiwillig, dürfte auch schnell an 
die Grenzen des überhaupt machbaren kommen, vielleicht funktioniert es 
bei sehr kleinen Bitraten. Da denke ich gar nicht drüber nach.

Ich werde die CAN/SPI-Routinen in den Bootbereich packen und die nach 
einer Prog-Message anspringen. Und dann gibts für jedes Byte einen 
Frame, beinhaltet Adresse im Flash und Datenbyte. EEprom brauch ich 
nicht (bzw. kann ich das in der der "normalen" CAN-Kommunikation)

von Hagen R. (hagen)


Lesenswert?

>CAN in Software - das macht keiner freiwillig, dürfte auch schnell an

So meinte ich das nicht. Eher in Richtung CAN-Hardware ist in der MCU 
und kann konfiguriert werden, extern RS485 Bus.

>Ich werde die CAN/SPI-Routinen in den Bootbereich packen und die nach
>einer Prog-Message anspringen. Und dann gibts für jedes Byte einen
>Frame, beinhaltet Adresse im Flash und Datenbyte. EEprom brauch ich
>nicht (bzw. kann ich das in der der "normalen" CAN-Kommunikation)

Hier würde ich die Packetgröße auf die Größe pro FLASH Page oder eben 
zur Verfügung steheden SRAM Buffer hochsetzen. Alles andere bringt mehr 
Overhead für das Packethandling und reduziert die performance drastisch.
Das Adresshandling wird zb. in meinem Protokoll ebenfalls separiert. Dh. 
es gibt einen interen Adresszähler der mit eigenem Kommando gesetzt wird 
und ansonsten bei den jeweiligen Programmierfunktionen für 
FLASH/EEPROM/SRAM lesen/schreiben automatisch inkrementiert wird.

Das Mischen von Bootloader- und Anwendungscode erachte ich ebenfalls für 
nicht ganz so gut. Normalerweise sollte der Bootloader eigenständig zur 
Anwendung funktionieren und so wenig wie möglich spezielle Hardware 
Feature benutzen. Zb. IQRs verkomplizieren den Bootloader drastisch. 
Aber gerade IQRs sollten in der Anwendung für die Kommunikation benutzt 
werden.

Ich würde daher in der Anwendung einen egenen CAN Driver mit IQRs und 
Buffering benutzen. Dieser reagiert dann auf einen Bootloader Frame 
indem der Bootloader gezielt gestartet wird. Dieser wiederum arbeitet 
ohne IQRs per Polling oder wenn mit IQRs dann mit seinen eigenen und 
nicht den der Anwendung.

Baust du den Bootloader so das er mit den IRQs der Anwendung arbeitet 
dann hast du die komplette Funktionalität der geschützten Bootloader 
Sections ebenfalls deaktiviert. Dh. dein Bootloader ist nur noch ein 
Subsystem deiner Anwendung und jedesmal wenn sich gravierende Sachen in 
deiner Anwendungssoftware verändern, IRQs usw., ist der schon 
installierte Bootloader inkompatibel.

Gruß Hagen

von Sven K. (Gast)


Lesenswert?

Hallo Hagen,

zuerst mal meine Hochachtung vor den Details und Features
den Du ja schon in der ganzen Lösung eingebaut hast.

Zurück zu der CAN Geschichte:

Während ich dies schreibe enwickelt sich mein eigener Vorschlag zu 
nonsens.

Man braucht doch nur ein eigenes Gateway bauen, welches
nur RS232-CAN übersetzt. Damit läuft die ganze Applikation
und der Bootloader transparent. Am Gateway stellt man dann
eine Zieladresse ein und ein Reset Kommando o.ä. kann
durch Dein Interface erfolgen. Das spezielle Kommando kann
ja durch die normale Applikation im AVR implementiert sein
und den Bootloader Modus aktivieren, wie Du es vorgesehen hast.

Dann braucht man nur den Assembler Code etwas für die CAN
Unterstützung anfassen und das Gateway bauen.

Gruß Sven

von Hagen R. (hagen)


Lesenswert?

@Sven:

ansich wird das auch so gemacht, denoch

>Dann braucht man nur den Assembler Code etwas für die CAN
>Unterstützung anfassen und das Gateway bauen.

dieses "etwas" ist es was mich stört ;) Der Bootloader ASM Source 
erzeugt so kompakten Code das dieses "Etwas" an Änderungen schon ne 
ganze Menge sein wird. Das Bootloader Protokoll ist eben auch Timing 
abhängig, zb. Baudrate Detection, Connection Aufbau, Responsezeiten beim 
FLASH/EEPROM programmieren usw. Ein Packetorientiertes Protokoll nimmt 
man immer dann wenn diese exakten Timings nicht erforderlich sind und 
der Schwerpunkt auf Multiclients/server/host liegt. Dies ist 
konzeptionell ja bei meinen Bootloader (PPP) eben nicht so.

Der Gateway müsste nun eigenständig entscheiden können wo er Datenbytes 
erstmal in Buffern sammelt und dann den Frame drumherum bauen kann und 
wo er einem strikten Timing unterworfen ist und sofort auch kleinere 
Packete schnüren muß. Das geht ohne zusätzliche Infos von der 
PC-Software eben nicht. Wenn du hier den Thread verfolgt hast dann wirst 
du sehen das es größtenteils Timingprobleme sind. Wenn man also zb. den 
Startup des Bootloaders gezielter per Events oder eben zeitlich 
toleranter gestalten könnte wären dort weniger Probleme zu erwarten. Da 
er aber aktuell einer anderen Konzeption unterliegt, nämlich maximal nur 
250ms auf einen Connect zu warten, ergeben sich eben gewissen 
Timinganforderungen. Das wäre nur ein Beispiel, ein weiteres wäre zb. 
das es ~4ms dauert eine FLASH-Page zu programmieren, die PC-Software nun 
ihrerseits weiß wieviele Pages programmiert werden müssen (auf Grund der 
vorher gesendeten Daten) und nun ihre Timeouts entsprechend setzt um 
einen flüssigen Ablauf und möglichst schnelle Programmierzeiten zu 
bekommen.

Ergo ist meine Meinung das bei einem packetorientierten Protokoll sich 
auch der konzeptionelle Aufbau sowohl der PC-Software wie auch AVR 
Source stark verändert und es besser wäre dann gleich was Neues zu 
stricken. Nicht das es mit einer "Krampflösung" nicht funktionieren 
könnte aber effektiv betrachtet investiert man weniger Zeit und Nerven 
gleich von Anfang an bei der Neuentwicklung solche Anforderungen auch zu 
berücksichtigen.

Finally: ich meine das der jetzige Bootloader nicht dafür geeignet ist 
und es sich auch nicht lohnt diesen in diese Richtung weiter zu 
entwickeln. Davon abgesehen werde ich nicht bereit sein meine Zeit dafür 
zu opfern.

Gruß Hagen

von ARV (Gast)


Lesenswert?

Wie man die ACY-file ohne Anschließen MCU zu vorbereiten?

von Hagen R. (hagen)


Lesenswert?

Geht nicht und ist Absicht. Die PC-Software benötigt bestimmte Angaben, 
wie AVR Signatur und installierte Bootloaderversion um das ACY File 
daraufhin kompilieren zu können. Angedacht war das nach der Kompilation 
bei der Verschlüsselung auch noch live überprüft wird ob das Passwort 
stimmt (wurde aber nicht implementiert da ein Angreifer so eventuell 
durch Trial&Error das Passwort durchprobieren könnte).

Wenn man das offline machen wollte so müsste die PC-Software die AVR 
Signatur, Bootloaderversion und Bootloadergröße per GUI beim Benutzer 
abfragen.

Es ist also von der Arbeitsweise immer so vorgesehen das der Entwickler 
ein aktuelles Gerät/Hardware vor sich hat und sein kompiliertes ACY auch 
gleich tested.

Gruß Hagen

von ARV (Gast)


Lesenswert?

Danke, Hagen!
Ich muß die verschlüsselte file ohne angeschlossen MCU generieren. Allen 
notwendig gegeben (passwort, signatur und dgl.m.) weiß ich und ich kann 
manuell einsetzen. Ob eine solche Möglichkeit existiert?

von Rolf L. (rluebess)


Lesenswert?

Hallo Hagen,
Erstmal grosses Danke!
richtig genial der loader.

Jetzt bräuchte ich noch genau sowas für den ATXMEGA128A1. Weiter oben 
hattest du glaub ich schonmal den Prozessor erwähnt. Gibt es da schon 
was konkretes?

Viele Grüße,
Rolf

von Hagen R. (hagen)


Lesenswert?

@Rolf, nein noch nicht.

von Arne H. (piowux)


Angehängte Dateien:

Lesenswert?

Hallo,
da ich ein entsprechendes Bootloader UI für Ubuntu brauchte, habe ein 
Programm geschrieben, welches den hier beschriebenen Bootloader bedienen 
kann. Es kann bis jetzt nur den Flash programmieren. Dies allerdings mit 
verschlüsselten .acy und unverschlüsselten .hex files. Außerdem wird 
auch nur der ATmega8 unterstützt. (Es wird aber nicht überprüft ob sich 
um einen solchen handelt.) Wahrscheinlich strotzt es vor Bugs. 
Allerdings funktioniert das Programmieren von einem Ubuntu 9.4 System 
aus.

Das Programm ist mit Lazarus geschrieben und lässt sich entsprechend 
auch wür win kompilieren.

Wenn man es mit den Parametern bootloader -nogui -tty -bd -file aufruft, 
kann man es auch normal über Kommandozeile aus zb der makefile heraus 
starten.

Ich dachte, dass vielleicht auch andere Interesse haben an dem Programm.

Viele Grüße,
piowux

von Arne H. (piowux)


Angehängte Dateien:

Lesenswert?

hier noch das Binary für Kompilierfaule..

von Arne H. (piowux)


Lesenswert?

@Hagen:

ja, ich kann mich ARV (Gast) nur anschließen. Es wäre klasse, wenn man 
das .acy file direkt ohne anschließen des AVRs generieren könnte. Bei 
mir hat das den Hintergrund, dass dein Programm unter Linux und Wine 
zwar läuft, aber die serielle Schnittstelle halt nicht angesprochen 
werden kann.
Für das Programmieren habe ich ja jetzt ein Programm. Nur das Erzeugen 
der acy Datei ist nicht möglich. Ich würde ungern immer die Virtual 
machine starten, nur um eine acy Datei zu erzeugen.
Vielleicht kann man das ein bisschen absichern, indem man die Bootinfo 
aus einer Datei liest, deren Zeitstempel nicht zu alt ist? So ist dann 
wenigstens halbwegs sichergestellt, dass der entsprechende Chip 
vorliegt.

Gruß,
piowux

von Hagen R. (hagen)


Lesenswert?

@Arne:

Ich wäre sehr daran interessiert wenn deine bisherige Arbeit weiter 
perfektioniert würde. Melde dich bitte bei mir per PN und wir können 
dann besprechen wie ich dich besser unterstützen kann (Sourcen usw.).

Zum Problem "offline ACY":
Ich habe es mal in meine Todo Liste aufgenommen. Es bestehen drei 
Lösungen für dieses Problem. Per GUI wählt man AVR, Bootloader Größe 
etc.pp. vor der Compilierung aus. Drückt man also auf den Compile Button 
erschiene ein Dialog. In diesem Auswahlelemente für die fehlenden Daten 
die auch automatisch von einem connected Device befüllt werden können. 
Alternativ dann von einem AVRootloader.asm, also dem aktuellen Source 
des Bootloaders, geparst werden können. Dieser Dialog eröffnet also die 
Möglichkeit entweder manuell, automatisch aus verbundenen Device oder 
ausgelesen aus einem AVRootloader.asm alle Parameter zu setzen. So würde 
ich mir diese Änderung vorstellen damit ich mit diesen Änderungen und 
dem verbundenen Aufwand gleich mehrere Fliegen mit einer Klappe 
erschlagen kann (lohnt ansonsten ja nicht). Ist halt bischen Arbeit da 
ich einiges am Basic Code verändern müsste, mal schauen.

Demnächst wollte ich sowieso noch ein weiteres Feature einbauen (merge 
zweier HEX Files um Bootloader HEX und App HEX in einem Rutsch 
programmieren zu können).

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

@Arne:

Habe mir mal deinen Source angeschaut. Weist du ob Lazaraus auch 
Interfaces unterstützt ? Wenn ja dann wäre es doch viel besser wenn du 
mein Interfaces Source gleich direkt benutzt da ich meine das dieser 
portierbar nach Lazarus sein müsste. Dieser Source beinhalted alles 
ausser dem GUI. Dh. die komplette Protokollebene und Kommunikationsebene 
wäre fast fertig. Fehlte nur noch das GUI und das wäre Fleißarbeit. Ich 
habe versucht möglichst Delphi VCL und Windows API entfernt zu arbeiten 
(geht bei den Kommunikationsinterface natürlich nicht so einfach).

Gruß Hagen

von ARV (Gast)


Lesenswert?

Hi, Hagen!
You have news concerning to "offline ACY"?
Sorry, but my Deutsch is much worse than English.

von Hagen R. (hagen)


Lesenswert?

@ARV: no sorry, upto date timing is critical.

von Timo (Gast)


Lesenswert?

Hallo zusammen!

Zuerst möchte ich mich für den tollen Bootloader und die darin steckende 
Arbeit bedanken!

Allerdings habe ich jetzt ein seltsames Problem und könnte ein bisschen 
Hilfe gebrauchen.
Zunächst (am Dienstag) habe ich den Bootloader für 1-Wire Betrieb mit 
nicht invertiertem Uart für einen Mega8 (8MHz, Autobaud, nicht 
verschlüsselt) kompiliert und auf den Controller geflasht. Zum 
Programmieren habe ich die Schaltung aus dem beigefügten Bild verwendet, 
direkt an eine echte RS232. Die Dioden waren BAT46, als Widerstand habe 
ich 3k3 verwendet, da grad kein 2k7 verfügbar war.

Zwei Mega8 konnte ich so problemlos (auf jeweils verschiedenen Pins) 
ansprechen und flashen. Zugriff aur Ram/EEprom ging auch (nachdem ich 
dann die BOOTRST Fuse programmiert hatte)

Am nächsten Tag wollte ich dann auch einen Mega32 mit Bootloader 
ausstatten, allerdings reagierte er nicht auf die Verbindungsversuche.
Zunächst dachte ich an ein Problem mit dem Controller, egal ob Software- 
oder Hadrwareseitig, also hab ich nochmal die M8 vom vortag angeklemmt. 
Hier tat sich diesmal aber auch nichts, egal mit welcher Baudrate ich es 
versucht habe.
Danach hatte ich befürchtet, dass es die Schnittstelle erwischt hat, 
darum habe ich im Terminal getestet, ob gesendete Zeichen am Eingang 
wieder reinkommen. Schnittstelle OK.
Mein nächster Verdacht war, dass das Windowsprogramm aus irgendeinem 
Grund nichts mehr sendet. Das habe ich dann mit dem Oszilloskop auch 
ausschließen können. Sauberer +-12V Hub.
Mit dem Programmieradapter am AVR Pin sieht man das gleiche Muster, 
allerdings eben im Bereich von 0-5V und mit nicht ganz so steilen, bzw. 
etwas verrundeten steigenden Flanken.

So langsam gehen mir jetzt aber die Ideen aus, was noch falsch laufen 
könnte. Hat jemand eine Idee?
Falls das hilft könnte ich versuchen, das Oszillogramm auf den Rechner 
zu kriegen und hochzuladen.

Gruß,
Timo

von Thilo M. (Gast)


Lesenswert?

Hallo Timo,
ich hatte auch Probleme mit dem mega32 (siehe weiter oben), allerdings 
nicht one-wire.
Das Setzen der CKOPT-Fuse brachte das Teil zum laufen, evtl. geht das 
bei dir auch?

von Timo (Gast)


Lesenswert?

Hallo Thilo,
CKOPT Fuse ist bereits gesetzt, hat bei mir aber leider keine 
Veränderung gebracht.
Am meisten wundert mich bei der ganzen Sache ja, dass es mit den Mega8 
am Anfang funktioniert hat.

von Hagen R. (hagen)


Lesenswert?

Ändere mal in AVRootloader.inc den Wert bei BaudTolerance von 3 auf zb. 
5 oder höher. Je nach MCU-Takt und ausgewählter Baudrate ist die 
Baudraten Toleranz von 3 zu optimistisch gewählt. Mein aktuelles Projekt 
hatte damit Probleme, tratt hier also zum ersten Mal als Problem auf, 
und eine Änderung auf 5 beseitigte es.

Gruß Hagen

von L. S. (lschreyer)


Lesenswert?

Ich erhalte seit einigen Tagen auf einmal diese Fehlermeldung beim 
Upload von Firmware:

15.08.09-10:49:30-578 > Connecting...
15.08.09-10:49:30-703 > Switch to 2-Wire mode
15.08.09-10:49:32-140 > Device connected
15.08.09-10:49:32-140 > Program...
15.08.09-10:49:32-234 > execute compiled data
15.08.09-10:49:32-234 > selected options in compiled file:
15.08.09-10:49:32-234 > - programming FLASH
15.08.09-10:49:32-234 > - FLASH data are encrypted
15.08.09-10:49:32-234 > - erase FLASH during programming
15.08.09-10:49:32-234 > - full verify FLASH after programing
15.08.09-10:49:32-328 > Cmd.SetAddr.ResCheck()  Error: Invalid checksum
15.08.09-10:49:32-328 > Device disconnected


Bisher ging es immer problemlos. Das komische ist: Meine eigene Software 
mit der DLL geht problemlos, nur die Avrootloader-Windows-Software gibt 
diese Meldung aus. Was könnte das bloß sein?

Louis

von Hagen R. (hagen)


Lesenswert?

Schwer zu sagen. Benutzt du das Versioning ?

Probiere doch erstmal ohne Verify zu arbeiten und schaue ob der Fehler 
dann immer noch passiert.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

15.08.09-10:49:30-578 > Connecting...
15.08.09-10:49:30-703 > Switch to 2-Wire mode
15.08.09-10:49:32-140 > Device connected

Das deutet auf eine alte Bootloader Version hin. Installiere bitte die 
neuste Version 6.

Erkennen kannst du das daran das er explizit auf 2-Wire-Mode umschaltet. 
Das hat die ältere Version so gehandhabt, die standardmäßig auf 1-Wire 
eingestellt ist und beim Verbindungsaufbau erkennt das 2-Wire vorliegt. 
Die neue Version (ab Version 4 glaube ich) geht exakt andersherum vor. 
Standardmäßig 2-Wire und erkennt bei Bedarf 1-Wire.

Gruß Hagen

von L. S. (lschreyer)


Lesenswert?

Hallo Hagen,

versioning verwende ich nicht, ich habe einen Bootsign gesetzt um die 
verschiedene Hardware zu unterscheiden.

Die neueste Version zeigt dieselbe Meldung...

Ich habe nichts verändert, flashe die Datei schon seit Monaten. Ist 
schon seltsam, zumal es über die DLL geht.

Louis

von Hagen R. (hagen)


Lesenswert?

auch ohne Verify ? und BootSign korrekt ?

Gruß Hagen

von Frank L. (franklink)


Lesenswert?

abo*

von L. S. (lschreyer)


Lesenswert?

Args, ich bin noch nicht dazu gekommen das zu testen, wird noch 
nachgeholt.

Louis

von Vladimir (Gast)


Lesenswert?

Hallo Hagen,
danke für deinen exzellenten Bootloader!

Ich brauche eine zusätzliche Möglichkeit bei zwei gleichzeitig 
gedruckten Tasten am Gerät bei einschalten Bootloader starten.
Nur Assembler gehört nicht zu meinen Stärksten…

Tasten Abfrage habe ich so realisiert:

...
.include "AVRootloader.inc"
;.listmac
.list


.org BootStart
init:  cli
;-----------------------------
.def  tmp  = r28
.def  tmp1  = r29

   ldi   tmp, $00
   out   DDRA, tmp  ;PORTA als Eingang
   ldi   tmp, 0b11111100
   out   PORTA, tmp  ;PullUp

   in   tmp, PINA
   andi tmp, 0b10001000
   ldi   tmp1, 0b10001000
   eor   tmp, Tmp1
   ldi   tmp1, 0
   cpi   tmp, 0b10001000
   brne NoButtons
   ldi   tmp1, 1    ;wenn gedruckt, immer auf PC warten (tmp1=1)

NoButtons:    ;sonst starten wie immer
;-----------------------------
   clr    zerol

.if Use1Wire
u.s.w….

Frage:
was soll ich am Besten ändern und, wenn möglich, wie?
ich verwende "fixed baudrate, identifier scanning with timeout"
also in dem Fall timeout soll unendlich dauern?

Hochachtungsvoll

Vladimir

von Hagen R. (hagen)


Lesenswert?

Nachfolgend die zwei Stellen im ASM die du änderst:
1
check:  xwdr
2
        sbrs    PIND, PD0
3
        sbrc    PIND, PD1
4
        rjmpapp
5
6
; baudrate and identifier scanning
7
.if UseResetDelay    
8
abd:  
9
.endif
10
11
...
12
...
13
14
; identifier (BootSign) scanning with timeout and checksum
15
16
id1:     sbiw   xl, 1                ; UART getc with timeouts
17
         sbc    cmdl, zerol
18
         rx_1 
19
         brne   id1
20
id2:     breq   check; exit
21
id3:     sbiw   xl, 1
22
         sbc    cmdl, zerol
23
         rx_0
24
         brne   id3
25
         breq   check; exit
26
         rcall  getx
27
...
28
...


Bei Label check:
- Watchdog, falls eingeschaltet, zurücksetzen
- beide Pins abfragen, hier low-active
- wenn nicht beide gedrückt mit jmpapp die Anwendung starten

danach normale Baudrate Detection und BootSign Detection. Falls eines 
davon fehlschlägt Sprung nach Label Check: statt Label Exit:

Deine Tasterpins sollten per internem Pullup arbeiten und nach GND 
gezogen werden. Falls es nicht so ist musst du die sbrs/sbrc Abfragen 
umdrehen.

Wenn nicht beide Tasten gedrückt sind startet sofort deine Anwendung. 
Solange beide Tasten gedrückt sind wird auf einen gültigen Connect 
gewartet, ohne Timeout oder Watchdog RESET.

Gruß Hagen

PS: ich habe das jetzt nicht getestet sondern hier live eingetippt.

von Vladimir M. (wim)


Lesenswert?

Danke! Jetzt alles funkzioniert wie ich wollte.
Nach deinem Vorschlag ich habe das so gemacht:

.org BootStart
init:   cli
        clr    zerol
;-----------------------------
        ldi   r28, $00
        out   DDRA, r28       ;PORTA als Eingang
        ldi   r28, 0b11111100
        out   PORTA, r28      ;PullUp

        ldi   r28, 0
        sbis  PINA, PA7       ;Pruefen, ob PfeilNachUnten gedruckt ist
        sbic  PINA, PA3       ;Pruefen, ob PfeilNachOben gedruckt ist
        rjmp  NoButtons
        ldi   r28, 1          ;Sonst warten auf PC unendlich (r28=1)
        sbi    PORTD, PD6     ;Led "OK" ein
NoButtons:
;-----------------------------

...
...

; fixed baudrate, identifier scanning with timeout
        ldi    cmdl, byte1(Baudrate)
        ldi    cmdh, byte2(Baudrate)
        movw  baudl, cmdl
;-------------------------------------
        rjmp  abd
abd0:   cpi    r28, 1
        brne  exit
;-------------------------------------
abd:    movw  xl, zerol
        ldi    cmdl, byte3(BootDelay / 6)
ab1:    ldi    parah, (BootInfo - BootSign) * 2
        ldi    zl, byte1(BootSign * 2)
        ldi    zh,  byte2(BootSign * 2)
ab2:    rx_1
        rjmp    ab2
ab3:    sbiw  xl, 1
        sbc    cmdl, zerol
        rx_0
        brne  ab3
        ;breq  exit
;-------------------------------------
        breq  abd0
;-------------------------------------
        rcall  getx
        xlpm  r0, z+
        cp    r0, paral
        brne  abd
        dec    parah
        brne  ab2

.endif
; send info about chip/bootloader

von Hagen R. (hagen)


Lesenswert?

Bedenke das mit deiner Lösung du mit beiden gedrückten Tasten in die 
Baudrate/Bootinfo Schleife reinkommst aber nur mit einem Connect oder 
eben RESET wieder raus. Bei meinem Vorschlag bleibt der Bootloader so 
lange in dieser Schleife wie entweder beide Tasten gedrückt sind oder 
ein Connect erfolgte. Dh. ist der AVR noch in dieser Schleife, also ohne 
gültigem Connect, und werden die Tasten losgelassen so startet die 
installierte Anwendung.

Gruß Hagen

von Vladimir M. (wim)


Lesenswert?

Du hast recht. Aber genau das war mein Ziel. In einigen Fällen beim 
Update passieren unerwünschte Fehler. Dann weiteres Update ist nicht 
möglich. Hauptprogramme existiert nicht mehr und Kunde kommt nicht in 
Bootloader. Jetzt, wenn so was passiert, Kunde trotzdem hat Möglichkeit 
Bootloader starten.

von alex (Gast)


Lesenswert?

Hallo Hagen,

Dein Bootloader ist echt super.
Habe ihn schon bei meheren Geräten eingesetzt.
Jetzt will ich ein Konsolenprogramm für Linux schreiben.
Habe in diesem Thread gelesen das jemand schon mal angefangen hat.
Will das ganze in C schreiben. Vielleicht später auch mal eine einfache 
GTK Gui. Aber Vorrang hat erst mal das Konsolenprogramm.
Könntest du mir dafür die nötigen Infos geben wenn es geht.

MFG Alex

von (Gast)


Lesenswert?

Hi Hagen !

Genialer Loader, sehr schnell !

Ich verwende Bascom, kann dort die AVRootloader.exe als
Programmer einbinden. Übergeben wird dann :

AVRootloader.exe -PCOM1 -B115200 -SBOOTLOADER -DD:\Projekte\GPS\gps3dec\ 
-F{FILE} -Aepc

Für {FILE} setzt Bascom dann GPS.hex automatisch ein.

Wenn ich nun auf "Flash" klicke startet der AVRootloader und
löscht den Flash des Atmels. Danach sollte er dann ja den
Flash programmieren, aber das macht er nicht. Ich muss per
Hand auf "Program" klicken, dann flasht er artig den Chip.

Mit der Option -Aepc sollte er aber doch den kompletten Vorgang
automatisch ausführen, oder? Mache ich da was falsch ?

Matthes

von (Gast)


Lesenswert?

PS.

- ist eine 1Wire Verbindung
- per Hand funktioniert alles bestens

von Hagen R. (hagen)


Lesenswert?

probiere mal -Apc, der Bootloader wird dann so flashen als wäre die 
Checkbox "erase during programming" angehackt. Es kommt letztendlich 
auf's Gleiche raus nur eben mit dem Unterschied das es mit dieser Option 
schneller ist.

Denoch sollte er alle Kommandos auch ausführen wenn sie als Parameter 
angegeben wurden. Entweder mal wieder einen Bug eingebaut oder die 
interne Funktion .DoEraseFlash() gibt einen Fehler zurück. Sobald eine 
der angegebenen Parameter einen Fehler auslösst wird der komplette 
Vorgang der Auswertung der Parameter abgebrochen.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

@alex,

hier im Forum anmelden dann kannst du auf einen Link neben meinem Namen 
klicken und mir eine PN schicken. Ich antworte dann auf die EMail und 
schon können wir kommunizieren.

Gruß Hagen

von D. M. (misterdima)


Lesenswert?

Grüß Hagen!

Erst Riesige "Danke Schön" für deinen Bootloader, ist einfach Klasse.

Nun mein Problem:

Ich verknupfe deine DLL V2 mit eigener Anwendung, ich möchte EEPROM 
auslesen mit Function ReadEeprom aus dem AVRootIntf  und dann in einem 
File speichern. Aber BufOut ist immer leer. Was mache ich  falsch?


Hier ist eine Stück vom Code

procedure TForm1.Button8Click(Sender: TObject);
var
  EBuffer: pointer;
  BufOut : array of byte;
begin
  SetLength(BufOut,64);
  EBuffer := Addr(BufOut);
  FNameEEPROM := ExtractFilePath(ParamStr(0)) + 'temp1.eep';
  if FLoader.Mode = moDisconnected then FLoader.DoConnect;
  if FLoader.Command.ReadEeprom(EBuffer, 64) then
    begin
      Hex_File_Write;
    end;
  if FLoader.Mode = moConnected then FLoader.DoDisconnect;
end;

von Hagen R. (hagen)


Lesenswert?

Versuche folgendes
1
procedure TForm1.Button8Click(Sender: TObject);
2
var
3
  Buffer: array of Byte;
4
begin
5
  with FLoader do
6
    if DoConnect(True) then
7
    try
8
      try
9
        SetLength(Buffer, 64);
10
        if Command.ReadEeprom(@Buffer[0], Length(Buffer)) then
11
        begin
12
          FNameEEPROM := ExtractFilePath(ParamStr(0)) + 'temp1.eep';
13
          Hex_File_Write;
14
        end; 
15
      except
16
        on E: Exception do
17
          ShowMessage(E.Message);
18
      end;
19
    finally
20
      DoDisconnect;
21
    end;
22
end;

1.) Codeschutzblöcke mit try finally end
2.) DoConnect(), DoDisconnet() kann rekursiv benutzt werden, wichtig ist 
nur für jedes erfolgreiche DoConnect() muß ein DoDisconnect() 
aufgerufenw werden, ergo Punkt 1.) Schutzblock einrichten
3.) try except Block, du bist der On-Top-Caller und damit der 
On-Top-Fehler/Ausnahmen-Behandler
4.) Niemals Addr() verwenden, obsolete. Wenn dann mußt du bei 
dynamischen Arrays -> das sind Zeiger auf Records die Zeiger auf Daten 
enthalten, das erste Datenelement mit Addr() ermitteln. Also zb. 
Addr(Buffer[0]) kurz geschrieben also @Buffer[0]. Das dynamische Array 
könnte ja auch mehrdimesional sein.
5.) Aktionen, also vorbereitender Programcode immer nur zum Zeitpunkt 
ausführen wenn er nötig ist


Gruß Hagen

von Christian R. (cradi)


Lesenswert?

Hallo Hagen,

ich möchte mich für den Bootloader und die umfangreiche Doku bedanken.
Ich bin recht neu im Thema AVR unterwegs. Gestern habe ich es geschafft, 
den Loader erfolgreich auf einem Mega 8 zu installieren. Ich habe 
Anfangs etwas Probleme gehabt, da ich nicht wusste, dass bei einem MAX 
232 und bei meinem USB Seriell Wandler mit Atiny 2313 (ist auf dem Board 
von Ulrich Radig drauf) das UART Siganl umgekehrt werden muss.
Aber jetzt geht es, somit kann ich nun auch meinen 666p in Angriff 
nehmen.

Also, vielen Dank für Deine Arbeit, und dafür, dass Du dies alles 
öffentlich stelltst.

Gruß
Christian

von Hagen R. (hagen)


Lesenswert?

Danke, und
1
.equ  UseUartInvert    = 1      ; invert UART levels (for RS232 drivers such as MAX232)

so steht's im AVRootloader.asm ;)

Was ist 666p ?

Gruß Hagen

von Christian R. (cradi)


Lesenswert?

Hallo Hagen,

ja, ich habe den Kommentar dann auch gesehen. Ist also wirklich sehr gut 
dokumentiert, nur lesen muss man(n) alles :-))

Beim 666p habe ich  mich vertippt muss nachtürlich ein 644p sein.

Gruß
Christian

von D. M. (misterdima)


Lesenswert?

Grüß Hagen!

Danke für schnelle Antwort und deine Tips, den Code habe ich 
Ausprobiert, genau das, was ich brauchte.

von Achim (Gast)


Lesenswert?

Hallo Hagen,
tolles Projekt, tausend Dank für Deine Arbeit!!!

Ich würde gerne in Delphi eine kleine App zu Deiner DLL schreiben, mit 
der ich dass EEProm modifizieren kann (lesen/schreiben), aber leider 
krieg ich keinen connect.

Wenn ich bei GetAppCmdResponse '' zurückgebe, geht die Anwenndung baden 
und meldet irgendwann zuviel Exeptions "Integer divide by zero 
at0x0037c8e2". Wenn ich ' ' zurückgebe geht das zwar gut aber Connect 
hab ich trotzdem nicht.

Ich bräuchte das Verhalten der AVRootloder.exe, die ja auf Reset meines 
ATTiny wartet.

Wäre toll, wenns einen Tip gäbe.

von A. M. (Gast)


Lesenswert?

Hat sich erledigt....
Ich mach halt mein eigenes Interface über RS232.

von Manuel (Gast)


Lesenswert?

Hallo Hagen,

herzlichen Dank für dein tolles Projekt, leider habe ich nich gewisse 
Startschwierigkeiten...

Es tut mir leid dich trotz der umfangreichen Doku damit zu behelligen.

Folgender Aufbau:
Ein Atmega644 mit max232 an D0 un D1 angeschlossen.

.include "m644Pdef.inc"
.equ  UseWDR      = 1
.equ  UseAutobaud    = 1
.equ  UseVerify    = 1
.equ  UseE2Write    = 1
.equ  UseE2Read    = 1
.equ  UseSRAM      = 0
.equ  UseCrypt    = 1
.equ  UseCryptFLASH           = 1
.equ  UseCryptE2    = 1
.equ  UartInvert    = 1

.equ  RX_PORT      = PORTD
.equ  RX      = PD0
.equ  TX_PORT      = PORTD
.equ  TX      = PD1

.set  XTAL      = 8000000
.set  BootDelay    = XTAL/4

BootCodeSize habe ich gesetzt.
Compilieren und flashen hat ohne Probleme geklappt.

Fuses:
SPIEN gesetzt
BootFlash size=512 words Boot start address=$7E00
BOOTRST gesetzt
sonst alles aus.

Leider meldet mir AVRootloader immer "Error: no Device found".
Angeschlossen ist das ganze an einen Com am Mainboard.
Die Taktquelle ist der interne 8MHz Oszillator. Kann der zu ungenau 
sein?
Ich kann übrigens mit HTerm Daten vom Controller empfangen.

Hat vielleicht jemand eine Idee was das Problem verursacht?

Vielen Dank,
Manuel

von Hagen R. (hagen)


Lesenswert?

1. BootCodeSize auf 0 setzen
2. neu kompilieren
3. BootCodeSize auf Wert aus AVRStudio setzen
4. neu kompilieren
5. schaue im Messsagewindow von AVRStudio nach welche Boot Fuses du 
setzen sollst
6. flashen
7. Fuses setzen

Takt kann nicht das Problem aus Sicht des Bootlloaders sein da du die 
AutoBaud benutzt, das sollte ausreichend kurzzeit stabil sein.

- neuste Version ?
- AVRootloader.INI alles richtig ?

Gruß Hagen

von Manuel (Gast)


Lesenswert?

Hallo,
danke fuer die schnelle Antwort.

1-4 habe ich gemacht,
5: Please program Boot Fuse to First Boot Start !
Welche ist das? Die einzige die mir AVRStudio in diese Richtung anbietet 
ist BOOTRST, welche auch gesetzt ist.

Version sollte passen, 6.0; habe das letztmoegliche hier aus dem thread 
gezogen.

In der ini habe ich testweise
ConnectTrials=30
Connect=100
gesetzt; Sonst unveraendert gelassen.

Vor dem Compilieren habe ich noch make password ausgefuehrt und 
gespeichert.


Gruss Manuel

von Hagen R. (hagen)


Lesenswert?

Es gibt first, second, third und fourth Bootstart ;)
in AVRStudio gibt es eine DropDown Auswahl mit, na rate mal, vier 
Einträgen.
Wenn also zb. second Bootstart gemeint ist dann stellt man in dieser 
DropDown Liste den 2. Eintrag ein.

Ansonsten sieht alles richtig aus nach deinen Beschreibungen.

- COM Port in Windows Anwendung richtig ?
- das BootSign richtig eingestellt ?
- hast du mal die Debug Option probiert und dir dann das Protokoll 
angeschaut ?

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

> "Error: no Device found"

Diese Meldung kann eigentlich nur kommen wenn der COM Port auf AUTO 
steht. Setze den COM Port auf den an dem der AVR dran ist und probier 
dann einfach den Connect Button. Die Software verbleibt dann so lange im 
Connect bis du es manuell abbrichst.

Gruß hagen

von Manuel (Gast)


Lesenswert?

Ja, mit den ComPort Einstellungen habe ich schon gespielt, leider ohne 
Erfolg.
BOOT-Sign habe ich gelassen wie es war (BOOTLOADER).
Das Message Fenster bleibt stumm, auch bei Debug=1 in [System].
Kann es sein, dass es an meinem Port am PC liegt?
Mir ist frueher schon aufgefallen, dass HTerm empfangene Zeichen nur 
blockweise anzeigt, da scheint irgendein Puffer im Spiel zu sein. 
Vielleicht ist das sendeseitig genauso?
Waere super wenn das doch noch laufen wurde.

Viele Gruesse und schoenes Wochenende,

Manuel

von Hagen R. (hagen)


Lesenswert?

Debug=1 ist veraltet. Probiere [Timeouts] Options=1.
Du müsstest dann im Protokoll Fenster wesentlich mehr Infos sehen. Poste 
diese hier.

Gruß Hagen

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Hallo,

ich habe ein Problem.
Ich habe den Bootloader auf einen Atmega8 aufgespielt (ja ich habe das 
richtige Include ausgewählt). Nach viel Probieren bin ich nun soweit, 
dass ich über die Software Connecten kann. Jedoch heißt es bei Device 
name, es sei ein ATtiny87.
Ich habe dann versucht, aus dem Tut das erste Beispiel aufzuspielen.
Aber das Programm (AVRootloader 6.0) sagt, es fehlt ein RJMP to MAIN 
oder sowas.

Gerade ist ein neues Problem aufgetaucht.
Er braucht nun sehr lange um zu connecten, und wenn es klappt, dann nur 
sehr kurz.
1
40 Seiten lang  27.11.09-20:55:53-642 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
2
dann
3
27.11.09-20:55:53-642 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
4
27.11.09-20:55:53-730 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
5
27.11.09-20:55:53-819 > received data   $93 07 06 08 30
6
27.11.09-20:55:53-828 > Timer created
7
27.11.09-20:55:53-833 > Device connected
8
27.11.09-20:55:54-084 > send keepalive
9
27.11.09-20:55:54-338 > send keepalive
10
27.11.09-20:55:54-598 > send keepalive
11
27.11.09-20:55:54-864 > send keepalive
12
27.11.09-20:55:55-114 > send keepalive
13
27.11.09-20:55:55-378 > send keepalive
14
27.11.09-20:55:55-644 > send keepalive
15
27.11.09-20:55:55-902 > send keepalive
16
27.11.09-20:55:56-158 > send keepalive
17
27.11.09-20:55:56-424 > send keepalive
18
27.11.09-20:55:56-679 > send keepalive
19
27.11.09-20:55:56-938 > send keepalive
20
27.11.09-20:55:57-203 > send keepalive
21
27.11.09-20:55:57-453 > send keepalive
22
27.11.09-20:55:57-718 > send keepalive
23
27.11.09-20:55:57-722 > Timer released
24
27.11.09-20:55:57-725 > keepalive failed, terminate connection
25
27.11.09-20:55:57-772 > Device disconnected

von Manuel (Gast)


Lesenswert?

Hier die Ausgabe:
Das Teil sendet sporadisch irgendwelchen Mist zurueck.

1
27.11.09-20:57:27-453 > Connecting on port COM1...
2
27.11.09-20:57:27-453 > Timeout.Connect       = 100 ms
3
27.11.09-20:57:27-453 > Timeout.Base          = 50 ms
4
27.11.09-20:57:27-453 > Timeout.Erase         = 10 ms
5
27.11.09-20:57:27-453 > Timeout.Flash         = 15 ms
6
27.11.09-20:57:27-453 > Timeout.Eeprom        = 10 ms
7
27.11.09-20:57:27-453 > Timeout.Buffer        = 1 ms
8
27.11.09-20:57:27-453 > Timeout.AppCmd        = 0 ms
9
27.11.09-20:57:27-453 > Timeout.KeepAlive     = 250 ms
10
27.11.09-20:57:27-453 > Timeout.RTSPulse      = 0
11
27.11.09-20:57:27-453 > Timeout.RTSInterval   = 0
12
27.11.09-20:57:27-453 > Timeout.ConnectTrials = -1
13
27.11.09-20:57:27-453 > Timeout.MaxPacketSize = 0
14
27.11.09-20:57:27-453 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
15
16
.
17
.
18
.
19
20
27.11.09-20:57:42-765 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
21
27.11.09-20:57:42-937 > received data   $96 09 06 04 37 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2
22
27.11.09-20:57:42-937 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
23
27.11.09-20:57:43-125 > received data   $C2
24
27.11.09-20:57:43-125 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
25
26
.
27
.
28
.
29
30
27.11.09-20:57:44-171 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
31
27.11.09-20:57:44-343 > received data   $96 09 06 04 37 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2
32
27.11.09-20:57:44-343 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
33
27.11.09-20:57:44-531 > received data   $C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2
34
27.11.09-20:57:44-531 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
35
27.11.09-20:57:44-703 > received data   $C2 C2
36
27.11.09-20:57:44-703 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
37
27.11.09-20:57:44-875 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
38
39
.
40
.
41
.
42
43
44
27.11.09-20:57:49-109 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
45
27.11.09-20:57:49-281 > received data   $96 09 06 04 37 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2
46
27.11.09-20:57:49-281 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
47
27.11.09-20:57:49-468 > received data   $C2 C2
48
27.11.09-20:57:49-468 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
49
50
.
51
.
52
.
53
54
27.11.09-20:57:51-046 > send ident      $00 00 00 00 00 00 00 00 00 0D 42 4F 4F 54 4C 4F 41 44 45 52
55
27.11.09-20:57:51-171 > aborted by User

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Hallo zusammen,

hab mein Problem gelöst. Es lag an einer leeren 9V Batterie.
Das Programm ist echt super, großes Lob an dich.

gruß
Christopher

von Hagen R. (hagen)


Lesenswert?

@Manuel:

der Bootloader scheint zu verbinden sendet dann aber permanent den Feler 
$C2 zurück was heist CRC Fehler. Es sieht so aus als ob deine Hardware 
Kommuniaktion unsauber ist. Auf alle Fälle empfängt der AVR permanent 
irgendwelche Zeichen.

Antworten tut er auf alle Fälle korrekt, das kannst du an $96 09 06 04 
37.. erkennen.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

$9609 -> ATmega644
$06 -> Bootloader Version 6
$04 -> 4 FLASH Pages für Bootloader = BZ1 gesetzt
$37 -> $30 für alles Ok, $07 -> UseCrypt = 1, UseCryptFLASH = 1, 
UseCryptE2 = 1, UseVersioning = 0

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Was hast du bei AVRootloader.ini [Timeouts] -> Options stehen ?

von Christian R. (cradi)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe noch ein Problem mit dem Bootloader. Ich denke ich stelle mich 
nur dämlich an, aber ich finde es nicht raus.

Ich kann den Mega8 nur einmal über den Bootloader flashen. Danach 
springt er den Loader nicht an.

Er müsste doch, wenn die SW sendet bei einem Reset den Bootloader 
anspringen, oder?

Meines Fuses füge ich mal bei.
Der Mega8 läuft mit Quarz 12MHz. Es lauft dort ein Programm, welches 
Daten ADC Daten auf der seriellen Schnittstelle ausgibt. Die kommen auch 
am PC an.

Als Interface kommt ein FTD232 RL zum Einsatz, angeschlossen über 
Rxd/Txd.

Der erste Flash funktioniert über diese Verbindung.

Im Protokoll des AVRootloader.exe sehe ich, dass Daten gesendet werde, 
und das der AVR auch etwas sendet. Aber dies sind die Daten, die er auf 
der seriellen ausgibt.

Der Reset liegt auf einem Taster mit PullUp Widerstand, und funktioniert 
auch.

Wo ist mein Fehler?

Gruß
Christian

von Sven K. (Gast)


Lesenswert?

> Wo ist mein Fehler?

BOOTRST=Häckchen

Gruß Sven

von Christian R. (cradi)


Angehängte Dateien:

Lesenswert?

Hallo Sven,

danke für die Rückmeldung.
Leider geht es dann immer noch nicht.
Ein Reset des AVR löst weiterhin kein Connect mit dem AVROotloader aus.

Ich habe mal die Logdatei aus dem AVRootloader beigefügt.

Vielleicht kann damit jemand etwas anfangen.

Gruß
Christian

von Hagen R. (hagen)


Lesenswert?

@Christian:

kannst du mir sagen was 'Channel 5 value 1023' bedeutet ?
Das ist nämlich das was die PC-Bootloader Software über deinen COM Port 
empfängt.

Also am Bootloader liegt es nicht.

Gruß Hagen

von Christian R. (cradi)


Lesenswert?

Hallo Hagen,

das ist die Ausgabe des laufenden Programms. Es gibt nacheinander den 
ADC Wert der 8 Ports aus.

Aus meiner Sicht bedeutet dies, der Bootloader wird nach dem Reset nicht 
angesprungen. Nur beim ersten mal Flashen wird der Bootloader 
angesprungen.

Wenn ich also jetzt mit meinem Programmiergerät über die IPS 
Schnittstelle das HEX File des Bootloader flashe und im Anschluß über 
den AVRootloader das Programm übertrage geht es. Beim zweiten Versuch 
jedoch schon nicht mehr.

Gruß
Christian

von Hagen R. (hagen)


Lesenswert?

ich kenne nur zwei Probleme die solche Symptome verurschen

1.) BOOTRST nicht gesetzt
2.) nicht an die beschrieben Vorgehensweise beim Kompilieren gehalten.
- BootCodeSize=0 setzen
- neu kompilieren
- aus AVRStudio Message Fenster cseg [used] auslesen
- in BootCodeSize eintragen
- neu kompilieren

Ansonsten kann man keine weiteren Ausagen dazu treffen, wie im Thread 
hier schon mehrmals angesprochen, hast du nicht die nötigen Infos 
geliefert.

Gruß Hagen

von Christian R. (cradi)


Lesenswert?

Hallo.

ich habe jetzt nochmal ein wenige getestet, und jetzt geht es. Ich weiss 
aber nicht so richtig warum.

Vielen Dank für Eure Unterstützung.

Gruß
Christian

von Manuel (Gast)


Lesenswert?

Hallo Hagen,

habe bei [Timeouts] -> Options=1 stehen.

Heute Nachmittag werde ich das Teil mal an einem anderen Rechner testen.


Vielen Dank.
Manuel

von Manuel (Gast)


Lesenswert?

Also jetzt verstehe ich die Welt nicht mehr...

Nach viel rumprobieren schaffe ich es eine Verbindung herzustellen.
Ich benutze einen max232n mit Standardbeschaltung nach Datenblatt (5x 
1muF). Beschaltet ist pin13(max) mit pin3(com) und pin14(max) mit 
pin2(com). Andere Seite: pin11(max) mit pd1 und pin12(max) mit pd0.
Verbinde ich die Pind der Controllerseite habe ich ein schoenes 
Loopback. Funktioniert tadelos.
Versuche ich nun mit AVRootloader zu verbinden klappt das nicht, bis ich 
mindestens einen der Pumpelkos rausziehe, dann verbindet er sich sofort; 
es koennen sogar Programme uebertragen werden. Stecke ich die Elkos 
zurueck, bricht die Verbindung ab.

Was soll das? Ich bin kein voelliger Neuling auf dem Gebiet, habe sowas 
aber noch nie gesehen?

von MSP430 (Gast)


Lesenswert?

Hallo Manuel,

ich hatte schon ein ähnliches Problem mit dem MSP430.

Ich erinnere mich noch dunkel das sich bei der INIT Sequenz über den 
JTAG Programmer der RST Puls mit dem MAX232 gestritten haben. Der eine 
will runter der andere ist per Default auf high, oder umgekehrt...

von Manuel (Gast)


Lesenswert?

Das verstehe ich nicht, JTAG habe ich per fuse deaktiviert, ein Wechsel 
auf andere Controllerpins aendert nichts.
Wenn ich den Controller Daten ausgeben lasse ist es uebrigens genauso, 
mit Pumpelkos geht nichts; ziehe ich einen raus kommen sofort die Werte. 
Stecke ich ihn wieder ein klappt die Uebertragung weiterhin, bis zum 
reset des Controllers, dann geht das Spiel von vorne los.
Am Chip liegt es nicht, wurde bereits getauscht.

Das kann doch nicht so schwer sein, als ich den Chip die letzten Male 
verbaut habe hats immer auf Anhieb geklappt. Fallen euch noch 
Fallstricke ein, die ich uebersehen habe?

von Hagen (Gast)


Lesenswert?

Einzige Erklärung meinerseits: dein Elko brückt den TX des MAX. Dh. du 
meinst du hast diesen richtig angeschlossen, schließt ihn aber am TX 
Eingang des MAX an und baust so einen schönen Tiefpass für die 
Datenleitung. Zumindest würde das das beschriebene Verhalten erklären.

Gruß Hagen

von Manuel (Gast)


Lesenswert?

Das wäre schön, dann würde ich die Sache verstehen...

Es ist egal welchen Pufferelko ich rausziehe (können auch beide sein). 
An den Vout kann ich nachvollziehen, dass die Ladungspumpen arbeiten.
Wie gesagt, Loopback funktioniert mit Elkos, Übertragung zum AVR aber 
nur ohne Elkos.
Geisterhaft...

von Robert Z. (robertz)


Lesenswert?

Hallo Hagen.

Hagen Re schrieb:

> Ich benutz eigentlich zwei Arten um aus der Anwendung in den Bootloader
> zu springen. Das ist sehr hilfreich beim Automatischen Programmieren des
> AVRs. Bei den ATtinys überwache ich per PinChange ISR den RX Pin und
> nutz eine ISR wie nachfolgende
>
>
1
> // Pinchange ISR für PB6, bei LowLevel springen wir den Bootloader an
2
> __attribute__ ((naked)) ISR(PCINT_vect) {
3
> 
4
>     if (PINB & (1 << PB6)) {
5
>         asm volatile("reti");
6
>     } else {
7
>         asm volatile("rjmp  __vectors");
8
>     }
9
> }
10
> 
11
> int main(void) {
12
> 
13
>     MCUSR  = 0;
14
>     WDTCR  = (1 << WDE) | (1 << WDCE);
15
>     WDTCR  = 0;
16
> // RX Pin auf Eingang mit Pullup
17
>     DDRB  = 0;
18
>     PORTB = (1 << PB6)
19
> // PinChange on PB6, Bootloader Pin
20
>     GIMSK  = (1 << PCIE1);
21
>     PCMSK1 = (1 << PCINT14);
22
>     sei();
23
> 
24
> .. blabla
25
>     while (1) {
26
>     }
27
> }
28
>
>
> Das hat den Vorteil das man die laufende Anwendung durch die PC-Software
> automatisch in den Bootlaoder kommt. Da es ohne Watchdog per direktem
> RJMP geht kann man über den SRAM Befehl der PC-Software den aktuellen
> Inhalt des SRAMs und IO/PORT Bereiches auslesen und analysieren.
>


Leider kann ich kein Assembler, würde aber gerne grob verstehen, was du 
damit meinst. Wenn ich einen Attiny ohne Hardware UART habe, stehen mir 
doch auch keine UART Interrupts zur verfügung. Was bedeutet in diesem 
Fall "PinChange"?
Bascom könnte ich verstehen. Da funktioniert der Befehl ISCHARWAITING() 
z.B. nicht beim Attiny mit Software UART. Ich kann nur mit Inkey() das 
momentan empfangene Zeichen lesen oder mit waitkey() solange das 
Programm anhalten, bis ein Zeichen empfangen wird und dieses einlesen. 
(Soweit ich das verstaden habe)

Bei "meiner" Watchdog Lösung gibts das Problem, dass die Verbindung 
häufig erst nach einigen Sekunden hergestellt wird, oder auch mal gar 
nicht. Vermutlich weil die restlichen 4 Pins permanent damit beschäftigt 
sind, einen Schrittmotortreiber zu füttern und ADC Signale zu empfangen. 
Dann reagiert die Serielle Schnittstelle gar nicht.
Vielleicht käme ich mit der Alternative zum Watchdog weiter.

Viele Grüße
Robertz

von Hagen R. (hagen)


Lesenswert?

PinChange = Pin Change Interrupt so wie im Datenblatt beschrieben. Man 
wartet also auf verändeerungen an einem Pin, hier also der RX Pin des 
Bootloaders und ruft den Bootloader aus der Anwendung auf. Wenn du in 
deiner Anwendung mit IRQs arbeitest hat dies den Vorteil das deine 
beschtriebenen Wartezeiten wegfallen. Ich vermute mal du benutzt in 
deienr App eherr das Polling.
Der Watchdog wird dann benutzt um einen echten RESET des AVRs zu 
bewerkstelligen und damit den Bootloader definiert zu starten. Das ist 
besser als ein direkter Sprung zum Bootloader aus der Applikation.

Also:

1.) schreibe eine ISR für den Pin Change IRQ
2.) in dieser ISR prüfst du den RX Pin auf Veränderung und aktivierst 
den WDT mit anschließdender Endlosschleife. Somit schlägt der WDT zu und 
reset den AVR.
3.) in deiner Main aktiviere den Pin Change IRQ und setze die Pin-Maske 
für den PinChange IRQ korrekt. Also auf welchen Pin die PinChange ISR 
reagieren soll.
4.) in deiner Main aktiviere die Interrupts mit SEI().

Das von dir zitierte Beispiel arbeitet zwar mit dem PinChange aber nicht 
mit dem Watchdog sondern direktem Sprung zum Bootloader.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Falls du eher der HW-Typ bist und die SW nicht gebacken bekommst kannst 
du auch per HW einen RESET auslösen lassen. Die PC-Software unterstützt 
die Konfiguiration des DTR/DSR Pin der RS232. Diesen Pin kannst du an 
den RESET des AVRs legen. Jedesmal wenn nun die PC-Software einen 
Connect versucht pulst sie die DTR/DSR Leitung der RS232 und somit den 
RESET Pin des AVRs.

Wie es konkret geht steht hier im Thread, Readme's und AVRootloader.ini 
beschrieben.

Gruß Hagen

von Nora L. (nudl)


Lesenswert?

Hallo,

ich arbeite mit dem AT90USB1287 auf einem AT90USBKey Board und wollte 
gerne Deinen Bootloader ausprobieren. Leider hat das Board aber keine 
RS232-Schnittstelle sondern nur USB (und JTAG).
Das Kompilieren des Bootloaders und das Laden in den Flash hat auch 
geklappt, allerdings erkennt der PC das Device nicht (im Devicemanager). 
Vermutlich liegt das daran, dass eine USB-Kommunikation zwischen 
Bootloader und PC nicht vorgesehen ist sondern nur RS232 oder?
Kann ich den Bootloader trotzdem irgendwie verwenden bzw. gibt es eine 
Version mit USB? Oder sollte es eigentlich funktionieren und ich hab nur 
was falsch gemacht?

Danke für die Hilfe!

Gruß,

Nora

von Hagen R. (hagen)


Lesenswert?

Alle auf RS232 und RS485 basierten Schnittstellen gehen, nicht USB. Das 
müsstest du schon selbst programmieren.
Am besten dürfte es sein wenn du einen beliebigen Pin des AVRs als 
1-Wire-RS232 Bootloader Pin benutzt. Du brauchst dann nur bischen zu 
löten, siehe 1-Wire.png im ZIP und einen USB-Seriell Wandler.

Gruß Hagen

von matthes (Gast)


Lesenswert?

Hi zusammen,

ich setze den Rootloader seit einiger Zeit ein.
Läuft soweit prima!

Jedoch habe ich jetzt was ganz merkwürdiges:

2 identische Schaltungen mit Mega8L und Quarz 8Mhz,
3V3 UB und 1 Wire Mode.
Der einzige Unterschied zwischen den Beiden sind die
Prozessoren die aus unterschiedlichen Chargen stammen.
Eine Schaltung kann ich problemlos flashen, bei der
anderen kommt kein Connect zustande.
Flashe ich herkömmlich, also mit normalen Programmer,
läuft die Schaltung einwandfrei.
Fusebits sind natürlich richtig gesetzt, das hex des
Rootloaders ist natürlich immer das gleiche.

Kann mir dabei jemand helfen?

von Thilo M. (Gast)


Lesenswert?

Hi matthes,

ich hatte mal das Problem, dass der Quarz nicht recht anschwingen wollte 
und somit der Bootloader nur ab und zu funktionierte. Das Setzen der 
CKOPT-Fuse hat geholfen. Evtl. liegt's auch am Quarz? ;)

von matthes (Gast)


Lesenswert?

CKOPT habe ich auch schon probiert.
Auch alle Geschwindigkeiten der Schnittstelle.
Und die Startzeit des Atmel ......

von Hagen R. (hagen)


Lesenswert?

Ändere in AVRootloader.inc
1
.equ  BaudTolerance  = 3

zb. auf den Wert 5 um. Vielleicht "lindert es die Symptome" ohne die 
Ursache zu kennen.

Gruß Hagen

von Matthes (Gast)


Lesenswert?

Ok, danke, werde ich testen.

Gibt es noch eine Möglichkeit dem "Symptom" auf
die Schliche zu kommen?

von Thilo M. (Gast)


Lesenswert?

Du könntest die Prozessoren mal in den Schaltungen tauschen, dann weißt 
du zumindest, ob's der µC ist oder die Schaltung. ;)
Bei SMD natürlich etwas aufwändiger ...

von Achim (Gast)


Lesenswert?

Ich habe mal eine Frage: Das Windows Programm zeigt ja eine maximale 
Buffergröße des Bootloaders an. Wie finde ich heraus wie viel SRAM bei 
meiner Booloader-Konstellation für den Buffer übrig bleibt. Deine 
Software meint 472 Byte; ich haben aber keine Idee, wie Du das abfragst 
oder aus den Device-Parametern
berechnest.

Ach ja: BootloaderSize = Flash_PageSize * BootPages;

Stimmt das?

Vielen Dank für eine Erleuchtung!

Achim

von matthes (Gast)


Lesenswert?

Also, BaudTolerance auf 5 bringt auch nix.

Prozessor kann ich nicht über kreuz tauschen, da die
andere Schaltung wasserdicht vergossen ist.

Habe jetzt praktisch jeden Parameter ausprobiert,
egal was ich mache, es klappt nicht. Auch die Quarzfrequenz
stimmt. Ich gehe mal davon aus, das "faststartup" bei den
Fuses richtig ist. Habe da aber auch mehrere Einstellungen
versucht......

Auf allen anderen Schaltungen mit einem Mega8 die ich
auftreiben konnte funktioniert der Bootloader einwandfrei.

Ich mache mir nur Sorgen, wenn ich bei der nächsten Bestellung
nur solche "Ausreißer" bekomme ...........

von Thilo M. (Gast)


Lesenswert?

Da bleibt nur eins übrig:
zukünftig eine 100% - Prüfung vor dem Vergießen. ;)

von matthes (Gast)


Lesenswert?

neee, ich möchte das Problem schon lösen !

von Hagen R. (hagen)


Lesenswert?

>Ach ja: BootloaderSize = Flash_PageSize * BootPages;
>Stimmt das?

Ja.

(SRAM Size / FLASH_PageSize -1) * FLASH_PageSize ergibt maximale 
Buffergröße. Somit ist sichergestellt das 1. noch genügend SRAM für den 
Stack vorhanden ist und die 2. 8 bytes Prüfsummenblöcke auch noch 
reinpassen.
Maximal benutzt die Software also (SRAM Size / FLASH_PageSize -1) * 
FLASH_PageSize +8 bytes.

Gruß hagen

von Dennis P. (seedman)


Lesenswert?

Hallo Hagen,
erstmal vielen Dank für deinen genialen Bootloader.
Ich verwende folge Zusammenstellung:

Atmega8L (TQFP32) 8Mhz (extern)

Kommunikation mit dem PC über ein Bluetooth-Modul BTM-222.

Wird wie ein gewöhnlicher COM-Port behandelt.

Dein Bootloader in der Version 6.0

Mein Ziel: Atmega über Bluetooth flashen OHNE manuellen Reset per Knopf.


Mein Stand: Flashen mit externen Reset funktioniert jetzt einwandfrei 
nach langen Versuchen mit den Timeouts.

Dann habe ich die Watchdog Methode gewählt.

Diese Funktioniert auch soweit gut hatte bei mir bis jetzt aber den 
Nachteil, dass mein Hauptprogramm ungewollt alle 2 Sekunden resettet.

Daraufhin habe ich den Watchdog im Hauptprogramm deaktiviert, dann 
funktionierte aber wie erwartet nicht mehr der Bootloader-Reset über die 
PC Software. Und ein Watchdog-Reset alle 2 Sekunden möchte ich nicht im 
Hauptprogramm verwenden.

Jetzt würde ich gerne die PinChange Funktion nutzen um meinen Atmega8 zu 
resetten.
Weil der BTM-222 hat zwar ein RTS/CTS Pin kann diesen aber nicht nutzen.
Sprich ein Reset über ein RTSPulse kann ich leider auch nicht nutzen.

Muss ich dann nur ein Codeschnipsel in mein Hauptprogramm einfügen um 
ein PinChange zu erreichen?

Das BTM-222 verwendet mit dem Atmega8 ein 2Wire Modus ohne Pegelwandler 
aber mit deiner UARTInvert option.

Verstehe ich es richtig, dass deine PC-Software über AppCMD z.b. den 
Wert 0x55 ans Hauptprogramm schickt und der Atmega dann über PinChange 
resettet.


Sorry,... ich bin noch recht neu in der MCU-Programmierung und weiß 
jetzt nicht welche Lösung ich verwenden soll...


P.S. Dein Test-Sourcecode im Ordner Test lässt sich bei mir im 
AVR-Studio 4.18 mit dem AVR-GCC Compiler nicht compilieren. Da kommt 
immer ein Fehler von der ld.exe

Über eine Hilfe würde ich mich sehr freuen. :-)

Gruß Dennis

von Matthes (Gast)


Lesenswert?

Hi Dennis,

wie du weiter oben gelesen hast, habe ich einen Atmel der
nicht so richtig will. Was verwendest du für Timeouts?
Ich habe auch schon mit denen gespielt, evtl. sind diese
aber noch zu eng eingestellt?

von Dennis P. (seedman)


Lesenswert?

Ich habe die Timeouts in der INI nur bei BASE geändert. Auf 100ms.
Das funktioniert sogar über Bluetooth 100% zuverlässig allerdings nur 
per RESET-Taster.

Da ich aber Bluetooth verwende, nervt mich der Reset-Taster.

Ich möchte demnach einen Reset per Software durchführen, bekomme das 
aber nicht gebacken!

Reset via RTS-Signal ist leider auch ausgeschlossen, weil das BTM-222 
unterstützt diese Funktion nicht.

Jetzt bleibt nur noch Watchdog oder ein "Jump to Bootloader" übrig.

Nur mir fehlt ein Lösungsansatz. Das Beispiel im Ordner Test verstehe 
ich nicht so ganz.

Zumal wie ich jetzt herausgefunden habe besitzt der Atmega8 keine 
PinChange Funktion über "PCINT", der 8er hat nur den externen INT0 und 
INT1 Pin.

Gruß
Dennis

von Hagen R. (hagen)


Lesenswert?

Du hast mehrer Möglichkeiten:

1. Polling des RX Pins des Bootloaders in deiner Anwendung. Falls der RX 
pin toggelt dann über Watchdog Reset den Bootloader starten

2. PinChange oder Ext. Int. am RX Pin benutzen und auf Toggeln der RX 
datenleitung warten.

3. schreibe UART Funktionen für deine Anwendung. In der Empfangsroutine 
wartest du auf eine von dir festlegbaren Command String, zb. sowas wie 
"bootstart". Wenn du den empfängst kannst du einen Response String 
zurück senden, zb. "startboot" und wiederum per Watchdog Timeout einen 
Reset zum Bootloader durchführen. In der AVRootloader.ini setzt du das 
Topic AppCmd=bootstart und AppCmdresponse=startboot. Setze [Timeouts] 
AppCmd=20.

Der PC-Bootloader sendet nun vor jedem Connect Versuch den String 
"bootstart" an deine Anwendung im AVR. Dort reagierst du indem du 
"startboot" sendest und den WDT startest. Die PC Software wartet bis sie 
"startboot" also das AppCmdresponse empfangen hat, fügt ein 20 
Millisekunden Delay ein und macht mit dem normalen Connect zum 
AVRootoader im AVR weiter.
Somit hast du also den Bootloader im AVR softwaremäßig gestartet.

Wenn AppCmdResponse nicht benutzt wird, also leer ist, dann wartet die 
PC Software nicht auf eine Bestätigung Seitens deiner UART Routinen 
sondern macht gleich mit dem AppCmd delay und dem Connect weiter.

Letztere Methode ist mit ihrem Handshaking relativ stabil und sicher hat 
aber den Nachteil das die Baudrate in deinen UART Routinen meistens 
hardcoded ist, dh. die AutoBaud Funktion die im Bootloader drinnen ist 
steht dir nicht zu Verfügung.

Gruß Hagen

von CJ (Gast)


Lesenswert?

Hallo,

ich bin gerade dabei den AVRootloader auf meinem ATmega8 in Gang zu 
bringen, leider funktioniert es bisher nicht:
Ich habe die AVRootloader.hex laut Anleitung erstellt (AVR-Studio, mit 
"m8def.inc" sowie der richtigen Portbeschreibung für den ATmega8, also 
PD0 und PD1).
Die hex-Datei habe ich mit Ponyprog auf den ATmega8 geladen.
Bei der Fusebits bin ich mir 100%ig sicher:
BOOTSZ1 = 1 (kein Häkchen)
BOOTSZ0 = 0 (Häkchen)
BOOTRST = 0 (Häkchen)
Der Code hat nur 432Bytes (<256Words), also sollten die Fusebits 
eigentlich passen, oder?
Wenn ich nun die Verbindung mit AVRootlaoder aufbauen möchte findet er 
leider keine Device

im Protocol steht:
29.12.09-15:28:04-687 > Connecting on port COM1...
29.12.09-15:28:05-796 > Connecting on port COM41...
29.12.09-15:28:06-875 > Connecting on port COM42...
29.12.09-15:28:15-546 > Error: no Device found

Die Kommunikation über die RS232 funktioniert aber sicher, hab eben grad 
getestet.

Mache ich grundsätzlich irgendwas falsch, oder ist zumindest mein 
vorgehen korrekt? oder hat zufällig einer einen konfigurierten 
Bootloader fürn ATmega8 mit passenden Fusebits herumliegen?

Vielen Dank für Eure Hilfe!

Schöne Grüße
CJ

von Achim (Gast)


Lesenswert?

Hagen Re schrieb:
> (SRAM Size / FLASH_PageSize -1) * FLASH_PageSize ergibt maximale
>
> Buffergröße. Somit ist sichergestellt das 1. noch genügend SRAM für den
>
> Stack vorhanden ist und die 2. 8 bytes Prüfsummenblöcke auch noch
>
> reinpassen.
>
> Maximal benutzt die Software also (SRAM Size / FLASH_PageSize -1) *
>
> FLASH_PageSize +8 bytes.

Vielen Dank Hagen, aber bitte hilf mir doch nochmal:

Bezogen auf meinen ATTiny84 wäre das dann:
(512/64 -1)* 64 =448 Bytes Buffergröße
Mit Deinem Programm bekomme ich aber folgendes:

Connection                     : 1-Wire
Device name                    : ATtiny84
Device signature               : 1E930C
SRAM size                      :    512 Byte
EEPROM size                    :    512 Byte
FLASH size                     :   8192 Byte
FLASH size for application     :   7232 Byte
FLASH pagesize                 :     64 Byte
Bootloader size                :    960 Byte
Buffersize for data            :    472 Byte
SRAM start address             :     96
Bootloader version             :      6
Use bootsection                :     No
Versioning supported           :    Yes
Cryptography supported         :    Yes
FLASH data must be encrypted   :    Yes
EEPROM data must be encrypted  :     No
Bootloader information         :
Application software version   : 3.2.2.0
Application version address    : 0x001C3A

von Hagen R. (hagen)


Lesenswert?

Die PC-Software geht von SRAM_Size - PageSize + 24 aus. Ergibt 512 -64 
+24 = 472 Bytes. Ganz genau genommen geht sie immer davon aus das 
SRAM_Size mod PageSize = 0 ist also immer ohne Rest teilbar. Am 
korrektesten wäre also die Formel (SRAM_Size div PageSize -1) * PageSize 
+ 24.

Das ist der vom Protokoll her gesehen maximale Buffer der benutzt wird. 
Wird Verschlüsselung benutzt so muß man die 512 Bytes erstmal in x 
PageSize Buffer unterteilen. Damit für den Stack noch was übrig bleibt 
ziehen wir erstmal PageSize ab und erhalten so den minimal nutzbaren 
Datenbuffer = 448 Bytes. Das ist die maximal nutzbare Größe für die 
Daten im FLASH/EEPROM. Bei der Entschlüsselung wird im SRAM noch 
zusätzlich 3 XTEA-Buffer a 8 Bytes benötigt. Der erste XTEA Datenblock 
ist intern das Feedback Register, der 2. Datenblock a 8 Bytes ist das 
Ausgaberegister. Der 3. 8 Bytes Buffer liegt dann am Ende des SRAMs und 
enthält den zu entschlüsselnden Prüfsummenblock. Vor diesem liegen nun x 
Pages a PageSize Bytes an FLASH/EEPROM Daten. Somit ergibt sich das wir 
den SRAM erstmal in 64 bytes (Pagesize) Blöcke aufteilen. Somit kommt 
man auf Max. Buffersize = SRAM_Size - Page_Size + 24. Es verbleiben dann 
40 Bytes für den Stack.
Dieser Buffer wird aber nur so groß benötigt wenn mit der 
Verschlüsselung gearbeitet wird, ohne Verschlüsselung fallen die 24 
Bytes weg.
Bei der Verschlüsselung sieht es also so aus: Feedback | Output | 
Datenblock 1 | Datenblock 2 | ... | Datenblock x | Prüfsummenblock.
Alle diese Blöcke sind 8 Bytes groß. Die Anzahl x dieser Datenblöcke ist 
immer x = (SRAM_Size - Page_Size) / 8.
Wird nun entschlüsselt so "wandern" die Bedeutung dieser 8 bytes Blöcke. 
Am Anfang wird das Feedback Register mit den Datenblock 1 XOR verknüpft. 
Dann wird dieser Block mit XTEA halb entschlüsselt und dieses 
Zwischenresultat mit dem Feedback Register erneut xor-verküpft. Nun die 
zweite Hälte der XTEA Entschlüsselung durchgeführt und in den als Output 
markierten Datenblock gespeichert. Aus dem ehemaligen "Output" Block 
wird der nächste "Feedback" Datenblock und aus Datenblock 1 wird der 
neue "Output" Block. Nun beginnt wieder alles von vorne usw. Somit 
stehen die verschlüsselten Datenblöcke am Anfang der Entschlüsselung um 
8 bytes nach hinten versetzt im SRAM und nach der Entschlüsselung sind 
diese Daten um 8 bytes nach vorne kopiert wurden. Damit wird die 
Entschlüsselungsfunktion so wie erforderlich in ihrer Performance 
gesteigert und das gesammte System arbeitet wie ein "sliding Window" 
während der Entschlüsselung über den kompletten Buffer. Das erklärt die 
zusätzlichen 24 Bytes die man benötigt.

Gruß Hagen

von Achim (Gast)


Lesenswert?

Hallo Hage,
super vielen Dank für Deine ausführliche Antwort!!!
Ich verstehe ungefähr 30% davon, den Rest werde ich mir noch erarbeiten.

Ansonsten läuft Dein Bootloader bei mir einfach nur spitzenmäßigg, 
reibungslos, wie es sein soll. Vielen vielen Dank für Deine AArbeit!!!

Gruß Achim

von Manuel (Gast)


Lesenswert?

Hallo zusammen,

kann mir auf die Schnelle jemand verraten wie ich aus der Applikation 
direkt in den Bootloader springen kann?

Bei BootMode = 0 sollte das doch mit einem jmp gehen.

Es geht um einen Atmega644; das Datenblatt sagt, bei FirstBootStart 
beginnt die BootLoader Flash Section bei 0xfe00.

Warum bringt mich
asm volatile("rjmp 0xfe00") dann ins Hauptprogramm?


Vielen Dank.
Manuel

von Hagen R. (hagen)


Lesenswert?

Schaue dir mal den \Test\ Ordner im ZIP an. Dort zeige ich wie man mit 
WinAVR GCC in C den Bootloader startet. Entweder per direktem Jump oder 
viel besser mit dem WatchDog. Machst du einen Jump dann musst du 
sicherstellen das du alle HW und Ports usw. manuell so zurücksetzt das 
der AVR so wie nach einem RESET eingestellt ist. Nutzt du dagegen den 
WD-Timeout wird der AVR einen RESET machen und alles ist so wie es der 
Bootloader erwartet.

Gruß Hagen

von Kostadin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Hagen,

vielen Dank für dein AVRootloader, ich finde ihm TOP!

Ich habe es geschafft eine Verbindung zwischen dem PC und einem 
AT90USB1287 (AT90usbkey Plattform) zu kriegen. Als Verbidung habe ich 
den 1-Wire verwendet ( aber nicht mit 2,7 kOhm, sondern mit 2 kOhm 
Widerstand, ich hoffe,dass das kein Problem ist ;) ) Das einziges 
Problem ist, dass die Baudrate kann nicht mehr als 28800 eingestellt 
werden, keine Ahnung warum.

Ich habe kleine Anwednung, ein paar LEDs leuchten lassen, geschrieben 
und mittels dein Windows-Programm verschlüsselt und drauf geladen. Es 
ging ohne Probleme!

Das Problem ist, wenn ich eine großere hex-Datei auf dem µC laden will. 
Es funktioniert irgenwie nicht. Ich habe keine Ahnung warum nicht, habe 
alles durchgesucht, nochmal alles gelesen, aber nichts gefunden. Ich 
habe auch mit den Werten für Timeouts gespielt, aber wieder ohne Erfolg!

Vielleicht hättest du eine Idee woran mein Problem liegt? Ich hänge dir 
das Protocol an. In dem kann man sehen, dass ich zuerst eine kleine 
Anwendung erolfreich lade, dann versuche ich eine großere Anwendung( 
60kBytes) zu laden, aber es gibt einen Fehler.

Es ist egal, ob ich die Verschlüsselung benutze oder nicht, in beiden 
Fällen es funktioniert nicht.

Vielen Dank im Voraus! Wenn du andere Infos brauchst, sag einfach 
bescheid.

Gruß Kostadin

von Etumic E. (etumic)


Lesenswert?

Hallo,

ich habe jetzt auch versucht den Bootloader auf meinem Atmega8 zu 
verwenden. Leider bekomme ich keine Verbindung!

Meine Einstellungen:
1
.include "m8def.inc"
2
3
.equ  UseAutobaud    = 0      
4
.equ  UseResetDelay  = 1  
5
                  
6
.equ  RX_PORT      = PORTD  
7
.equ  RX           = PD0
8
.equ  TX_PORT      = PORTD  
9
.equ  TX           = PD1
10
11
.set  XTAL         = 12000000  
12
.set  BootDelay    = XTAL/4  
13
.set  BootBaudrate = 9600    
14
.set  BootVersion  = 6      
15
.set  BootCodeSize = 466

FuseBits:
BOOTSZ1  = 1
BOOTSZ0  = 0
BOOTTRST = 0

Wenn ich meinen Controller resette (Taste) dann empfange ich eine 0 
(Byte-WERT) mit dem Terminal.
Ist das richtig? Sendet der Bootloader eine 0 beim starten?

von Etumic E. (etumic)


Lesenswert?

Hat sich erledigt.
Ich hatte das Invertieren nicht gesetzt.

Ich bin begeistert von dem Bootloader. Mit AppCmd und Watchdog 
automatisch resetten. Funktioniert alles bestens.

TOP Bootloader

von Hagen (Gast)


Lesenswert?

@Kostadin:

du benutzt 1-WIRE-RS232 ? Laut Protokoll, ja, er bringt aber auch einen 
ICOM-Echo-Fehler was darauf schließen lässt das du eben nicht 1-Wire als 
Hardware benutzt. Bei 1-Wire muss das was die PC-Software an Daten 
sendet auch von der PC-Software wieder empfangen werden, das sogenannte 
Echo der Daten. Das wird durch mein RS232 1-Wire Treiber berücksichtigt. 
Das Echo wird wieder empfangen und mit den vorher gesendeten Daten 
verglichen. Sollten Unterschiede im Echo gefunden werden oder das Echo 
ganz ausbleiben so wird der ICOM-Echo-Error gemeldet.

Ich vermute also: entweder nutzt du keine 1-Wire Hardware und die 
PC-Software detektiert nicht den richtigen Modus, also 1-Wire statt 
2-Wire. Oder du benutzt 1-Wire Hardware und diese ist nicht stabil.

Gruß Hagen

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

Hallo euch allen,

ich bin schon seit einiger Zeit auf der Suche nach einem CAN-Bootlader
für den AT90CAN. Leider konnte ich dazu aber kein fertiges Projekt
finden.
Genauere Informationen gibt es unter fogendem Link:

Titel - Beitrag "CAN BUS Bootloader AT90CAN"

Ich hoffe es finden sich einige um dieses Projekt zu realisieren oder
die dabei helfen können.

Grüße martin

von swarner (Gast)


Lesenswert?

Hallo Hagen,

ich hab mal versucht, Dich via PM zu kontaktieren, was bisher nicht 
gelang. Wahrscheinlich ist Deine t-offline Addy nicht mehr aktuell.

Auf alle Faelle hab ich nen avrdude Patch, der Flash schreiben und 
verifizieren (implizit und bissl hingedreht auch explizit) kann.

Jetzt steht nur noch EEPROM schreiben (lesen muesste gehen) und 
Encryption an. Und genau bei der Encryption brauch ich Deine Hilfe. Wie 
funktioniert das Verfahren? Ich werde das dann fuer avrdude 
implementieren, damit der bootloader vollstaendig unterstuetzt wird. 
Ziel ist natuerlich die Aufnahme der Unterstuetzung in Mainline, womit 
dann alle wichtigen Systeme abgedeckt sein duerften.

Ich bin unter swarner ät mibtec punkt de zu erreichen.

Gruß,

Sascha

von Arne H. (piowux)


Lesenswert?

Hi Swarner,
deine Idee finde ich klasse! Ich habe auch mal ein Programm für den 
Bootloader geschrieben. Wahlweise Kommandozeile oder GUI. Das ganze ist 
in Lazarus geschrieben, sodass es auf vielen Plattformen funktioniert. 
Verschlüsseln kann es nicht. Dafür kann es aber schon verschlüsselte 
Dateien programmieren.
im Beitrag
Beitrag "Re: AVR-Bootloader mit Verschlüsselung"
ist der Quellcode. Ich hoffe er hilft dir weiter. Auf das alles bald im 
AVRDude erscheint, was richtig klasse wäre!

Viele Grüße,
piowux

von Hagen R. (hagen)


Lesenswert?

@Sascha: sorry aber zZ. bin ich gebunden mit anderen Projekten. Wenn 
deine Mail sich nur auf ein kleines Problem bezöge hätte ich sichderlich 
just in time auch geantwortet. Da du aber eine ausführliche 
Dokumentation von mir benötigst brauche ich mehr Zeit dazu, und die habe 
ich eben nicht. Ich schaue zu das ich die nächste freie zeit benutzte um 
dir alle infos sauber zusammen zu stellen.

Gruß Hagen

von swarner (Gast)


Lesenswert?

@Hagen: Danke fuer die Antwort. Solange Deine Mail Adresse richtig war, 
bin ich beruhigt :) Die Encryption eilt nicht, wahrscheinlich ist es 
sogar besser, wenn ich da inkrementell vorgehe. Also mach Dir da keinen 
Stress deswegen - ich bin noch laenger da.

@Arne: Danke fuer Deinen Code. Wenn ich wo Zweifel hab, kann ich jetzt 
nachsehen, wie Du es Dir gedacht hast :) Ich hab z.B. ganz vergessen den 
"RUN" Command zu nutzen ;)

Wegen Deines ATMEGA8-only-Poblems: Du brauchst glaub ich CPU abhaengig 
nur die RAM Puffergroesse. Wenn Du einfach die Pagesize nimmst, die du 
fuer die Bootloadergroesse eh brauchst (erase pages usw.), liegst Du auf 
der sicheren Seite (ok, muesstest Du je CPU die Pagesizes verwalten, 
alternativ nimmst Du die kleinste Pagesize, die vom Bootloader 
unterstuetzt wird, 32 Bytes. Das Flashen wird dadurch wesentlich langer 
dauern, aber immerhin kannst so alles flashen.) Ich musste genau 
deswegen dem dude noch ein sramsize in die Chip Config pflanzen - 
leider.

Gruesse

Sascha

von Etumic E. (etumic)


Lesenswert?

Hallo,

Der Bootloader läuft bei mir super mit Kabel.
Jetzt möchte ich über Bluetooth (BTM-222) flashen.

Leider bekomme keine Verbindung über Bluetooth.
Wie muss ich die Timeouts einstellen?
Base habe ich schon versucht zu erhöhen. 50, 100, 200

Es kann keine Verbindung aufgebaut werden!

Meine Einstellungen:

Connection                     : 2-Wire
Device name                    : ATmega16, ATmega16A
Device signature               : 1E9403
SRAM size                      :   1024 Byte
EEPROM size                    :    512 Byte
FLASH size                     :  16384 Byte
FLASH size for application     :  15360 Byte
FLASH pagesize                 :    128 Byte
Bootloader size                :   1024 Byte
Buffersize for data            :    920 Byte
SRAM start address             :     96
Bootloader version             :      6
Use bootsection                :    Yes
Versioning supported           :    Yes
Cryptography supported         :     No
Application software version   : not defined
Application version address    : 0x003BFC

[Timeouts]
Connect=0
Base=100
Erase=10
Flash=15
Eeprom=10
Buffer=1
AppCmd=0
KeepAlive=250
MaxPacketSize=0
RTSPulse=0
RTSInterval=0
Options=1

von Stefan R. (stefan09)


Lesenswert?

Hallo Hagen !

Ich hab mal zwei kurze Fragen zu UseSpecialWrite.
Da mein ganzes Projekt in ASM ist, hab ich den Aufruf folgendermassen 
programmiert:
1
ldi r18, low(Puffer)      ;Buffer
2
ldi r19, high(Puffer)
3
4
ldi r20, low(32)          ;size
5
ldi r21, high(32)
6
7
ldi r22, 0x00             ;Adresse die Überschrieben wird (0x0f00)
8
ldi r23, 0x0f
9
clr r24
10
clr r25
11
12
RJmp Flashend -5

Ist das so richtig ? (Denn bei mir funktionierts leider nicht)
Bin leider kein C-Profi, deshalb ist das Test-Project für mich nicht 
immer ganz so leicht zu verstehen !


UseSpecialWrite = 1 !
Muß ich sonst noch was einstellen oder ändern ?

Gruß

Stefan

von Hagen (Gast)


Lesenswert?

>>Ist das so richtig ?

Nein, benutze RCALL statt RJMP da ja die Bootloader Funktionen mit RET 
zum Aufrufer zurückkehren. Es sei denn dein obiger Sourceausschnitt wird 
selber per RCALL aufgerufen und du möchtest das die Bootloader 
Funktionen direkt zu derem Aufrufer zurückkehren sollen.

Desweiteren sollte der Offset -2 statt -5 sein. Im C Source ist dort -5 
weil die FLASH Adressen als Byteaddressen interpretiert werden in ASM 
aber als Wordadressen.

Deine Parameter->Register sind korrekt.

Aktiviere mal UseSpecialRead=1 und UseSpecialMsg=1. Dann schreibe einen 
Aufruf für UseSpecialMsg

RCALL FlashEnd-4

In R25 sollte nach Rückkehr der Funktion die Länge des Boot-Msg-Strings 
drinnen stehen und in r24:r23:r22 der Zeiger auf die FLASH Adresse an 
der die BootInfo steht. Nun kannst du damit die BootInfo aus dem FLASH 
lesen ,wenn die Security-Fuses so gesetzt sind das die App auf den 
Boot-FLASH zugreifen kann. Somit hats du erstmal eine reine ReadOnly 
Funktion und zerschießt dir nicht gleich den FLASH wie bei falschem 
Aufruf von WriteFlash().

Im nächsten Schritt benutze ReadFlash() um Daten aus dem FLASH in einen 
SRAM Buffer zu lesen. Wenn das geht mit WriteFlash() weitermachen und 
mit ReadFlash() verifizieren.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

@Etumic:

Die BTM-222 sind bischen schwer zu konfigurieren und kannst du 
sicherstellen das diese korrekt laufen ? Wenn ja wird es ein Timing 
Problem sein und da kann ich dir nur schlecht weiter helfen.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

@Stefan:

nochwas:
- alle diese Funktionen benutzen Byteadressen als FLASH-Zeiger
- r25 des 4-Bytes Zeiger auf die zu schreibende FLASH Adresse ist 
normalerweise 0x00 (es gibt ja nicht soviel FLASH in einem AVR). Benutzt 
du in r25 den Wert 0xAC als Magic Code kannst du in den Boot-FLASH 
schreiben, falls du die Securityfuses entsprechend gesetzt hast.
- in ASM ist FlashEnd = FLASH_SIZE_IN_BYTES / 2 -1, sollte also bei dir 
die Word Addresse sein.

Gruß Hagen

von Stefan R. (stefan09)


Lesenswert?

Hallo Hagen !

Vielen Dank für die Hilfe !
Es lag am Rjmp Flashend -5 !
Das sind halt die feinen Unterschiede zwischen C und ASM !

Fals nochmal jemand danach sucht:
Hier der Funktionierende Code für den Aufruf von UseSpecialWrite aus 
Assembler:
1
ldi r18, low(Puffer)      ;Puffer im SRam
2
ldi r19, high(Puffer)
3
4
ldi r20, low(32)          ;Anzahl der zu schreibenden Bytes
5
ldi r21, high(32)
6
7
ldi r22, Byte1(Adresse*2) ;Adresse im Flash die Überschrieben wird
8
ldi r23, Byte2(Adresse*2)
9
ldi r24, Byte3(Adresse*2) ;wird nur bei großen AVR's benötigt, sonst  
10
ldi r25, Byte4(Adresse*2) ;einfach auf 0x00 setzen
11
12
RCall Flashend -2         ;Rücksprung aus Bootloader mittels 'Ret'

Gruß

Stefan

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.