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
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
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
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
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
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.
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
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
@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
>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
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.
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
@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
@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
@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
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
@ 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?
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!
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?
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
Ü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
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.
@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
>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.
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
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.
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
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
>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
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
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
Ü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
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
>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
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.
>..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
@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 ?
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
intmain(void)
2
{
3
cli();
4
5
// read MCUSR saved by bootloader
6
uint8_tlSavedMCUSR=*(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
// 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
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
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).
@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
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:
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.
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
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
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
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
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
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:
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
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
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.
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
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
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.
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
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:
@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
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.
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
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
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!
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
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
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
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
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
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:
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
>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
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
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
@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
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.
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
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
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
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
@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
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)
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.
>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
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)
>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
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
@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
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
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?
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
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
@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
@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
@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
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
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?
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.
Ä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
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
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
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
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
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
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.
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
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.
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
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
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
@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
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;
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
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
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
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.
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
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
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
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
> "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
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
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.
@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
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
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
@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
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
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
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
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?
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...
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?
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
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...
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
>asmvolatile("reti");
6
>}else{
7
>asmvolatile("rjmp __vectors");
8
>}
9
>}
10
>
11
>intmain(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
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
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
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
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
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?
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? ;)
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 ...
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
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 ...........
>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
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
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?
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
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
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
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
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
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
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
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
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
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?
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
@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
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
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
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
@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
@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
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
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
>>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
@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
@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
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'