Bootloader stoppt Mikrocontroller

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Bootloader stoppt Mikrocontroller

      Hallo alle zusammen,

      Ich hab mal wieder ein Problem, dem ich alleine nicht herr werde.
      Dieses mal ist es etwas seltsam, denn wenn ich den Bootloader Code, der in der Bascom Hilfe vorhanden ist, auf meinen Mikrocontroller lade habe ich das Problem, dass bei gewissen Anweisungen das Program einfach stoppt.
      Wenn ich jetzt die $loader Anweisung weglasse, also den Code nicht in den Bootloaderbereich schreibe, wird der Code normal ausgeführt.

      Folgendes habe ich schon getestet:
      - dim > Funktioniert
      - config > Funktioniert
      - open > Funktioniert
      - Zuweisungen > Funktioniert
      - Berechnungen > Funktioniert
      - Schalten eines Ports > Funktioniert
      - Interrupts dis/enable > Funktioiniert
      - nop > funktioniert

      - Schleifen > Stoppt
      - Bedingungen > Stoppt
      - goto/gosub > Stoppt
      - wait/waitms/.. > Stoppt
      - print/printbin > Stoppt
      - inkey/waitkey > Stoppt

      - watchdog > versuch den Mikrocontroller neuzustarten nachdem er hängen bleibt, hat nicht funktioiniert
      (
      config watchdog = 1024
      start watchdog
      )

      Nachfolgend ist mein Testcode, welcher als Kopie der Bootloader Hilfe aus Bascom entstanden ist. Ich hab Hauptsächlich sachen weggekürzt, welche Compiler Code waren und den Com2 auf Com1 geändert. Auch hab ich den gesamten funktionalen Teil des Codes rausgenommen da ich nicht bis zu diesen Code im Programm komme. Auf das Problem bin ich gestoßen, weil der Bootloader keine Rückmeldung auf die 123 Befehle geliefert hat. Zuerst dachte ich, dass das waitkey()/waitkey(#1) probleme macht, dem war aber nicht so. Bin durch Tests draufgekommen, dass wenn ich ein "waitms 1" und ein "set Port" vor die erste waitkey() Anweisung gebe der Port nicht gesetzte wird.
      Ich habe auch schon ander Varianten versucht wo ich, den gesamten Bootloader Code rausgeworfen hab und nur die 2 Leds geschalten hab. Einmal immer vor einer Anweisung und einmal gleich danach, um zu Testen welche Anweisungen dazu führen das der Mikrocontroller hängen bleibt.

      BASCOM-Quellcode

      1. $prog &HEC , &HFF , &HDC , &HFC
      2. $crystal = 16000000
      3. $hwstack = 40
      4. $swstack = 40
      5. $framesize = 40
      6. $baud = 38400 'baud statt baud1 definiert da die Programmierung über Com1 Stattfindet und nicht Com2
      7. $timeout = 200000 'wie in der Bascom hilfe für bootlader angegeben bei 16Mhz wurde 200000 empfohlen
      8. $regfile = "m2561def.dat"
      9. $loader = &H1FC00 'Aus der Bascom Hilfe für Bootloader
      10. '#################################################################################################
      11. dim bStatus as byte
      12. dim bRetries as byte
      13. poLedYellow alias Porta.7
      14. poLedRed alias PortD.4
      15. '#################################################################################################
      16. 'Com2 wurde auf Com1 geändert, da der Bootloader auf Com1 lesen/schreiben soll und nicht Com2
      17. config Com1 = dummy, Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      18. open "com1:" for binary as #1
      19. '#################################################################################################
      20. disable Interrupts
      21. bRetries = 5
      22. '#################################################################################################
      23. set poLedRed
      24. waitms 1 '<-- Hier "stoppt" das Programm
      25. set poLedYellow 'Wird nie ausgeführt
      26. Testfor123:
      27. bStatus = Waitkey()
      28. '...
      Alles anzeigen

      Ich hoffe jemand von euch hat noch eine Idee.
      Danke schonmal für eure Zeit.
    • Setze mal Zeile 11 vor die erste Zeile.

      Ob das das Problem löst kann ich nicht sagen, aber der Compiler kann erst Stackwerte korrekt setzen, wenn der Compiler weis, welcher der verwendete Controller ist. Und damit wieviel Speicher er hat und wo der endet (höchste Adresse).
      Der Std. Controller wird ja im Setting eingestellt. Und der stimmt i.d.R. nicht mit dem verwendeten überein.

      Versuchs mal.
    • Hallo Prepe

      Das Problem mit Deinem Testcode ist:
      Deine LEDs sind nicht als Ausgang declariert.

      Soll der Bootlader auf 123 reagieren, so mußt Du die Resettaste drücken.
      Machst Du es wie beim "Nano" etc automatisches Reset per DTR über einen 100nF Kondensator - in Optionen Programmer DTR einschalten.
      Startet der Upload dann nicht, dann ist $timeout zu klein. Tipp 1/10 der Quarzfrequenz.
    • nolem schrieb:

      Hallo Prepe

      Das Problem mit Deinem Testcode ist:
      Deine LEDs sind nicht als Ausgang declariert.

      Soll der Bootlader auf 123 reagieren, so mußt Du die Resettaste drücken.
      Machst Du es wie beim "Nano" etc automatisches Reset per DTR über einen 100nF Kondensator - in Optionen Programmer DTR einschalten.
      Startet der Upload dann nicht, dann ist $timeout zu klein. Tipp 1/10 der Quarzfrequenz.
      Also die LEDs kann ich normal schalten die funktionieren ja. Wie gesagt Ports Set/Reset/Toggle funktioniert normal. Ich kann das Programm auch auf den Mikrocontroller hochladen. Wenn ich die "$loader = &H1FC00" anweisung wegmache und das Programm hochlade (was keinen sin machen würde wenn ich einen Bootloader haben will) würde der Mikrocontroller auch normal funktionieren.

      Ich will jetzt halt einen Bootloader haben, und ich habe halt den vorgefertigten Bootlader Code, der in der Bascom Hilfe ist genommen und für andere Geräte funktioniert der auch normal. Wenn ich jetzt aber den Bootloader auf das eine spezielle Gerät hochlade hängt sich der Mikrocontroller bei der Ersten Anweisung auf die einen "Jump" ausführen würde.
      Also wenn ich waitms 10 als Anweisung wie im Beispiel aufrufe, würde im Asambler Code ein Jump zu der Routine für die vom Compiler hinzugefügten Codezeilen für die Waitms Anweisung "Springen", aber anstatt den Waitms auszuführen bleibt er hängen. Das Gleiche passiert bei goto/gosub/for/loop until/while/print/printbin/waitkey/inkey/... also alle Anweisungen welche vom Compiler erzeugten Code nutzen würden. Fast schon so als würden die Libaries für die Funktionen verbuggt sein.
      Also er Code wird bis zu diesen Anweisungen richtig ausgeführt und sobald er eine von diesen Anweisungen ausführen würde bleibt er hängen.

      Das einzige das mich stört ist, dass die IF Anweisung funktioniert - zumindest wenn die Bedingung erfüllt ist, und kein Sprung ausgeführt wird.

      Ich hab auch schon mit einen anderne Programmer versucht und mit dem passt alles, Bootloader funktioniert. Jetzt hab ich nur das Problem von dem anderen Programmer hab ich nur noch den einen und der ist schon super alt und wird wohl bald den anderen alten Pogrammern folgen und nicht mehr funktionieren. Deswegen möchte ich, dass ich den Bootloader mit meinem neuen Programmer hochladen kann.
      Ich kann den gleichen Code aber auf ein anderes Gerät hochladen und es funktioniert mit beiden Programmern, aus irgend einen Grund will das Programm nicht richtig funktioieren, wenn ich es mit meinen neuen Programmer auf das spezielle Setup hochlade, aber alles andere funktioniert normal, wenn ich es auf andere Setups hochlade.

      Ich habe die Platinen auch schon geprüft und der einzige Unterschied ist das ich Com1 statt Com2 verwendet, aber bei einem Setup hab ich auch Com1 statt Com2 und dort funktioniert es normal.
    • Also wenn du den selben Code auf den selben Controller spielst, nur mit 2 unterschiedlichen Programmern, und bei der einen Variante funktioniert es und bei der anderen nicht, könnte es dann am Programmer liegen?

      Welche Programmer verwendest du denn?

      Es macht auch mal Sinn, den ganzen Bootloader einzustellen, so wie du ihn verwendest.
      Vielleicht ist ja dort doch was verrutscht.
    • Der neue Programmer mit dem der Fehler auftritt ist
      mySmartUSB light - AVR ISP Programmer
      und in Bascom verwende ich
      mySmartUSB light STK500 mode
      zum programmieren. (Bei allen anderen Geräten funktioniert das Bootloader hochladen einwandfrei, nur mit den Atmega2561 gibt es probleme)

      Der alte Programmer mit dem der Fehler nicht auftritt ist leider nicht mehr bekannt welche Marke,
      es wird vermutet das es dieser hier ist,
      aber in Bascom verwende ich
      USB-ISP Programmer
      zum programmieren. (Wird nur noch für 2 Geräte verwendet)

      Der alte Programmer soll ersetzt werden, weil nicht mehr bekannt ist welche Marke genau gekauft wurde.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Prepe ()

    • Prepe schrieb:

      und in Bascom verwende ich
      mySmartUSB light STK500 mode
      zum programmieren.
      Ist das jetzt über USB bzw. seriell oder per ISP-Schnittstelle?


      Prepe schrieb:

      $regfile = "m2561def.dat"
      Du benutzt ja den Controller "ATMega 2561".
      Ist das ein fertiges Board?

      Ich frag jetzt mal so dumm, weil ich hatte mal ein Controller, da war die ISP-Schnittstelle nicht die gleiche wie die SPI-Schnittstelle.
      Zum Programmieren mussten da andere Pins verwendet werden.

      Vielleicht kannst du das auch mal prüfen.
    • @Mitch64 das ist ein USB programmer.

      Algemeine zusätzliche Infos:
      Wir haben eine kleine Platine welche die ISP belegung von 1 RX, 2 VCC, 3 LED, 4 GND, 5 RESET, 6 GND, 7 SCK, 8 GND, 9 TX, 10 GND auf 6 Pins Mapped, bedeut wir nutzen alle Pins außer 3 LED, 4 GND, 6 GND, 8 GND. Soweit würde ich kein Problem damit sehen da alle benötigten Pins genutzt werden.

      Da ich keinen zugriff auf die Platienenpläne hab, habe ich am Freitag mit Multimeter die Verbindungen geprüft und alle Pins laufen auf die richtigen Pins des Mikrocontrollers. Mit einer ausnahme der VCC Pin ist mit dem OC0B Pin verbunden. Wird wohl ein Faulheitsfehler durch Copy/Paste sein, weil beim ATMega128 würde das auf den PEN Pin Mappen, welcher wenn ich mich nicht irre für die Programmierung gebraucht wird. Könnte das mein Problem sein? Aber warum funktioniert die Programmierung dan bei anderen Geräten, die den gleichen Mikocontroller drauf haben und gleich verbunden sind.

      Ich hätte mir vorstellen können das die 5V, die ich über den USB bekomme nicht ausreichen, da unser schlauer Designer alle Komponenten auf einer VCC Leitung hat, heißt das sobald ich den Programmer anstecke die GESAMTE Platine hochfahren würde. Da wir eigentlich mit einer 9V-14V Versorgung unsere Geräte betreiben könnte das zu Brownouts führen, aber wenn ich alles was nicht gebraucht wird vor der Programmierung abschließe, sodass nur noch der Mikrocontroller angeschlossen ist funktioniert es auch nicht.

      Ich hab auch mit externer Stromversorgung experimentiert und die VCC leitung des 10 Pol Kables getrennt, leider mit den gleichen Ergebnissen.

      Ich glaube ja das etwas bei den Einstellungen nicht passen wird, da ich den Mikrocontroller ganz normal programmieren kann und das hochgeladene Programm auch ohne Probleme funktioniert, sobald ich die $loader Anweisung rausnehme.
    • Das ist die typische 10 polige ISP Schnittstellenbelegung. Normal ist dabei der Pin 3 nicht belegt, unbenutzt. Okay, da hat wohl der Designer einen Pegel für LED hinzu gefügt, was nicht stört.
      Die Bezeichnung von Pin 1 lautet normalerweise Mosi, die für Pin 9 lautet normal Miso.

      Was nicht passt, somit nicht der sinngemäßen Norm entspricht, ist die Verwendung von Pin VCC! Dieser sollte normal direkt mit VCC verbunden sein, und nicht über einen Portausgang geschaltet werden. Wenn Du das entsprechend ändern könntest, wäre es ein normaler ISP Adapter zum programmieren.

      Was mir noch unbekannt in deinem Falle ist, der Bootlader kann in unterschiedlichen Adressbereichen/Zonen liegen. Das sollte über entsprechende Einstellungen/Anweisungen passen,passend gemacht sein. Je nachdem wie groß der Bootlader ist, sollte er in den entsprechenden Bereich programmiert sein, und die einsprungadresse passen. Ob das in deinem Falle passt, weiß ich nicht.
    • bitlogger schrieb:

      Was nicht passt, somit nicht der sinngemäßen Norm entspricht, ist die Verwendung von Pin VCC! Dieser sollte normal direkt mit VCC verbunden sein, und nicht über einen Portausgang geschaltet werden. Wenn Du das entsprechend ändern könntest, wäre es ein normaler ISP Adapter zum programmieren.
      Also ich hab mich da etwas flasch ausgedrückt also wir haben eine kleine platine die auf einer seite einen 10Pol Stecker hat an dem ich das 10Pol Kabel anhängen kann und das Mapped zu einem 6Pol Stecker den ich an der zu programierenden Platine anstecke. Die 6 verbundenen Stecker sind verbinden dann zu den Pins vom Mikrocontroller. Also der Pin über den die 5V kommen verbindet zu VCC, GND zu GND, RESET zu RESET, Mosi zu RXD0, Miso zu TXD0 und SCK zu SCK.
      Leider hab ich eben noch herausgefunden das die VCC Leitung auf der Platine des Gerätes auf den OC0B Pin am Mikrocontroller geht, was ich halt nicht verstehe wieso. Ich kann mir nur vorstellen das mein Designer einen Fehler gemacht hat und nicht geprüft hat ob die ATMega2561 die selben Pins hat wie ATMega128.

      bitlogger schrieb:

      Was mir noch unbekannt in deinem Falle ist, der Bootlader kann in unterschiedlichen Adressbereichen/Zonen liegen. Das sollte über entsprechende Einstellungen/Anweisungen passen,passend gemacht sein. Je nachdem wie groß der Bootlader ist, sollte er in den entsprechenden Bereich programmiert sein, und die einsprungadresse passen. Ob das in deinem Falle passt, weiß ich nicht.
      Also der Bootloader wird an die Richtige Addresse für den ATMega2561 geschrieben also &H1FC00 ist auch so in dem Datenblatt für den Mikrocontroller angegeben wenn man 1024 Word länge an Bootloader verwendet, was ich auch mache.
    • @bitlogger Ich weiß, aber bei diesem Gerät lesen wir über Com1 die Daten ein, was an sich kein problem darstellen sollte, da die Leitungen statt auf PB2 und PB3 auf RXD0 und TXD0 gelegt wurden. Deswegen mach ich ja config COM1. Ich hab ja auch ein open "com1:" und die waitkey und print gehen auch über COM1.

      Ich habe so das gefühl wir bewgen uns immer weiter von meinem Problem weg als auf eine Lösung zu. Nochmal tldr:

      Das Problem ist NICHT das ich die Daten nicht auf den Mikrocontroller bekomme. Mein Problem ist, dass sobald im Code ein jmp ausgeführt wird, also der Programmcounter sich außerhalb des standardablaufes ändert bleibt der Mikrocontroller hängen. Er macht keinen reset, watchdog hilft auch nicht, er bleibt einfach hängen und lässt sich nur noch Resetten, wenn ich den Strom vom gerät wegnehme.
    • Die $Loader-Angabe scheint ja zu passen für einen Bootloader mit 1024 Words code.

      Wie groß ist denn dein Bootloader tatsächlich?

      Versuch doch mal die Einstellung mit 2048 Words für Bootloader mit der Angabe:


      BASCOM-Quellcode

      1. $Loader = &h1F800
      Sollte das auch nicht tun, stelle doch mal deinen kompletten Bootloader hier rein.
      So dass man das Programm compilieren und prüfen kann.
    • Weil danach gefragt wurde. Das ist meine zurzeit vollständig zusammengekürze version des Bootloaders. Ich hoffe es hilft euch, es sollte aber keine probleme mit dem logischen ablauf geben und 1:1 das gleiche machen wie der Bootloader aus der BasCom Hilfe.

      BASCOM-Quellcode

      1. '####################################################################################################
      2. $regfile = "m2561def.dat"
      3. $crystal = 16000000
      4. $baud = 38400
      5. $timeout = 200000
      6. $prog &HEC , &HFF , &HDC , &HFC
      7. $loader = &H1F800
      8. $framesize = 64
      9. $swstack = 64
      10. $hwstack = 64
      11. '####################################################################################################
      12. Const Maxwordbit = 7
      13. Const Maxword = (2 ^ Maxwordbit) * 2
      14. Const Maxwordshift = Maxwordbit + 1
      15. Const TX_NACK = &H15
      16. Const TX_ACK = &H06
      17. '####################################################################################################
      18. Dim bProgState As Byte , bProgRetries As Byte , bBlockIndex As Byte , bProgBlockIndex As Byte
      19. Dim bBlockCSum1 As Byte , bBlockCSum2 As Byte , bProgBuffer(128) As Byte , bProgCSum As Byte
      20. Dim J As Byte , Spmcrval As Byte 'self program command byte value
      21. Dim Z As Long 'this is the Z pointer word
      22. Dim valueLow As Byte , valueHigh As Byte 'these bytes are used for the data values
      23. Dim Wrd As Word , Page As Word 'these vars contain the page and word address
      24. 'Externe Stromversorgung halten
      25. '- wird mit einem Knopf eingeschalten, und durch 3 sec drücken ausgeschalten
      26. '- Bootloder muss nur die Stromversorgung halten, bis fertig
      27. set Portc.3
      28. 'Externe Module abschalten (wird erst gebraucht, wenn ich den Bootloader vom Hauptprogramm aus anspringe, um sicherzustellen das die Module abgeschalten sind)
      29. reset Porte.6
      30. reset Porte.5
      31. reset Porte.4
      32. poLedData alias Porta.7
      33. poLedReady alias PortD.4
      34. poLedLoader alias PortB.7
      35. config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      36. open "com1:" for binary as #1
      37. disable Interrupts
      38. '####################################################################################################
      39. set poLedReady
      40. bProgRetries = 5
      41. 'Prüfen ob eine Programmierung stattfinen soll
      42. Loader_WaitProg:
      43. bProgState = waitkey(#1)
      44. print #1, Chr(bProgState)
      45. if bProgState = 123 then goto Loader_StartProg
      46. decr bProgRetries
      47. if bProgRetries > 0 then goto Loader_WaitProg
      48. 'Bootloader beenden und zur Reset Addresse springen
      49. Loader_End:
      50. reset poLedData : reset poLedLoader
      51. for J = 1 to 5
      52. toggle poLedReady : waitms 50
      53. next
      54. goto _reset
      55. 'Fehler in Bootloader anzeigen und beenden
      56. Loader_Error:
      57. for J = 1 to 10
      58. toggle poLedLoader : waitms 50
      59. next
      60. goto Loader_End
      61. 'Bootloader programmierung starten
      62. Loader_StartProg:
      63. set poLedLoader
      64. do
      65. bProgState = waitkey(#1)
      66. loop until bProgState = 0
      67. Spmcrval = 3 : gosub Do_spm 'Word im Flash reseten
      68. Spmcrval = 17 : gosub Do_spm 'Word Freigeben
      69. bProgRetries = 10 'Anzahl wiederholungen auf 10 setzten
      70. print #1, Chr(TX_NACK) 'nack für Prog Start senden
      71. 'Hauptteil der Bootloader Programmierung (Einlesen des Befehles vom PC)
      72. Loader_ProgMain:
      73. bProgState = waitkey(#1) 'Auf Status warten
      74. select case bProgState
      75. case 1 : goto Loader_ProgBlock 'Prog Block
      76. case 4 : goto Loader_ProgFinish 'Prog fertig, geladeses Program starten
      77. case 24 : goto Loader_Error 'Übertragung abgebrochen
      78. end select
      79. if bProgRetries > 0 then decr bProgRetries else goto Loader_Error
      80. waitms 1000
      81. print #1, Chr(TX_NACK) '
      82. goto Loader_ProgMain
      83. 'Datenblock von der zu programmierenden Datei einlesen und in den Flash schreiben
      84. Loader_ProgBlock:
      85. Incr bProgBlockIndex
      86. bProgCSum = 1 'Checksum startet bei 1
      87. bBlockIndex = waitkey(#1) : bProgCSum = bProgCSum + bBlockIndex 'Blocknummer einlesen
      88. bBlockCSum1 = waitkey(#1) : bProgCSum = bProgCSum + bBlockCSum1 'Checksum 1 einlesen
      89. for J = 1 to 128 'Block einlesen (128 Bytes)
      90. bProgBuffer(j) = waitkey(#1) : bProgCSum = bProgCSum + bProgBuffer(j)
      91. next
      92. bBlockCSum2 = waitkey(#1) 'Checksum 2 einlesen
      93. if bProgBlockIndex = bBlockIndex and bBlockCSum2 = bProgCSum then 'Daten Prüfen
      94. Gosub Writepage 'Daten in Flash schreiben
      95. print #1, Chr(TX_ACK)
      96. else
      97. print #1, Chr(TX_NACK)
      98. end if
      99. goto Loader_ProgMain
      100. 'Bootloaderprogrammierung Abschliesen
      101. Loader_ProgFinish: 'end of transmission, file is transmitted
      102. if Wrd > 0 then 'if there was something left in the page
      103. Wrd = 0 'Z pointer needs wrd to be 0
      104. Spmcrval = 5 : gosub Do_spm 'write page
      105. Spmcrval = 17 : gosub Do_spm 're-enable page
      106. end If
      107. print #1, chr(TX_ACK); 'send ack and ready
      108. goto Loader_End
      109. 'Datenblock in den Flash schreiben
      110. Writepage:
      111. toggle poLedData
      112. For J = 1 To 128 Step 2 'we write 2 bytes into a page
      113. valueLow = bProgBuffer(j)
      114. valueHigh = bProgBuffer(j + 1)
      115. !lds r0, {valueLow} 'store them into r0 and r1 registers
      116. !lds r1, {valueHigh}
      117. Spmcrval = 1 : Gosub Do_spm 'write value into page at word address
      118. Wrd = Wrd + 2 ' word address increases with 2 because LS bit of Z is not used
      119. If Wrd = Maxword Then ' page is full
      120. Wrd = 0 'Z pointer needs wrd to be 0
      121. Spmcrval = 5 : Gosub Do_spm 'write page
      122. Spmcrval = 17 : Gosub Do_spm ' re-enable page
      123. Page = Page + 1 'next page
      124. Spmcrval = 3 : Gosub Do_spm ' erase next page
      125. Spmcrval = 17 : Gosub Do_spm ' re-enable page
      126. End If
      127. Next
      128. waitms 10
      129. Return
      130. 'Flash schreibroutine
      131. Do_spm:
      132. bitwait Spmcsr.0, reset 'check for previous SPM complete
      133. bitwait Eecr.1, reset 'wait for eeprom
      134. Z = Page 'make equal to page
      135. shift Z, left, Maxwordshift 'shift to proper place
      136. Z = Z + Wrd 'add word
      137. !lds r30,{Z}
      138. !lds r31,{Z+1}
      139. !lds r24,{Z+2}
      140. !sts rampz,r24
      141. Spmcsr = Spmcrval 'assign register
      142. !spm 'this is an asm instruction
      143. !nop
      144. !nop
      145. return
      Alles anzeigen
    • 1. Frage:
      Zeigt dieser Bootloader aus Post #16 das gleiche Verhalten wie der aus Post #1? (Ich wollte eigentlich den gesamten Bootloader (ungekürzt) haben, um zu prüfen, ob der in den 1k Flash-Raum passt.)

      2. Frage:
      Warum setzt du die Fusebits bei jedem Flashen aufs neue? Stimmen die Werte überhaupt so wie in Zeile 9 angegeben?
      Spoiler anzeigen
      $prog &HEC , &HFF , &HDC , &HFC

      Ich würde die Zeile remmen und erst am Schluss einlesen lassen und ins Programm einfügen, wenn der Bootloader zur eigenen Zufriedenheit funktioniert, vorher nicht.

      3. Frage:
      Wozu ist das Wait in Zeile 177 gut?
      10ms ist beim Flashen über Bootloader recht lange, wenn man die Baudrate betrachtet.
      Wenn du kein Handshake verwendest, gehen da Daten verlohren.

      4. Frage:
      Was steht denn jetzt tatsächlich in den Fuse/Lockbits drin?
      Kannst du das mit dem Programmer auslesen und anzeigen und hier einstellen?
    • @Mitch64
      1. Bootloader P#1 und P#16 verhalten sich gleich ja. Mit dem alten Programmer funktionieren alles ohne probleme und mit dem neuen ist bei der ersten assambler jmp anweisung ende.
      2. Weil ich den Bootloader eigentlich nur 1 mal auf die Mikrocontroller lade und das halt mit dem Bootloader passiert damit die ganz sicher gesetzt sind
      3. Das ist der waitms der auch in der BasCom hilfe drinnen ist nur das ich halt die Led am Anfand der Routine toggle anstat vor und nach dem waitms
      4. Lockbits sind richtig gesetzt und entsprechen exact dem was mit der $prog Anweisung gesetzt wird.

      Hier der Originalcode meines Vorgängers. Wenn ich mich nicht irre ist es eine 1:1 kopie des von Bascom zur Verfügung gestellten Bootloaders mit kleinen Anpassungen in folgenden Zeilen:
      11: $baud statt $baud1 (weil wir Com1 nutzen nicht Com2)
      19-22: definierung HWS SWS und FS
      97: open "Com1:" als #1 hinzugefügt
      98: Com1 statt Com2 configurieren
      142-143: LED für Ausgabe Definieren
      144-145: Stromerhaltung setzten

      Vordefinierte LED Pins wurden auskommentiert Portb.2 und Portb.3 und die LED schaltungen wurden durch die definierte LED aus zeilen 142-143 ersetzt
      Weiters wurden alle waitkey und print abgeändert sodass sie auf COM1 zugreifen mit #1
      Musste alle Kommentare im Code löschen wegen 10k zeichenbeschränkung

      BASCOM-Quellcode

      1. $crystal = 16000000
      2. $baud = 38400
      3. $prog &HEC , &HFF , &HDC , &HFC
      4. '$regfile = "m8def.dat"
      5. 'Const Loaderchip = 8
      6. $hwstack = 128
      7. $swstack = 40
      8. $framesize = 40
      9. '$regfile = "m168def.dat"
      10. 'Const Loaderchip = 168
      11. '$regfile = "m16def.dat"
      12. 'Const Loaderchip = 16
      13. '$regfile = "m32def.dat"
      14. 'Const Loaderchip = 32
      15. '$regfile = "m88def.dat"
      16. 'Const Loaderchip = 88
      17. '$regfile = "m162def.dat"
      18. 'Const Loaderchip = 162
      19. '$regfile = "m128def.dat"
      20. 'Const Loaderchip = 128
      21. '$regfile = "m64def.dat"
      22. 'Const Loaderchip = 64
      23. $regfile = "m2561def.dat"
      24. Const Loaderchip = 2561
      25. #if Loaderchip = 88
      26. $loader = $c00
      27. Const Maxwordbit = 5
      28. Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      29. #endif
      30. #if Loaderchip = 168
      31. $loader = $1c00
      32. Const Maxwordbit = 6
      33. Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      34. #endif
      35. #if Loaderchip = 32
      36. $loader = $3c00
      37. Const Maxwordbit = 6
      38. Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      39. #endif
      40. #if Loaderchip = 8
      41. $loader = $c00
      42. Const Maxwordbit = 5
      43. Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      44. #endif
      45. #if Loaderchip = 161
      46. $loader = $1e00
      47. Const Maxwordbit = 6
      48. #endif
      49. #if Loaderchip = 162
      50. $loader = $1c00
      51. Const Maxwordbit = 6
      52. Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      53. #endif
      54. #if Loaderchip = 64
      55. $loader = $7c00
      56. Const Maxwordbit = 7
      57. Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      58. #endif
      59. #if Loaderchip = 128
      60. $loader = &HFC00
      61. Const Maxwordbit = 7
      62. Open "COM1:" For Binary As #1
      63. Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      64. #endif
      65. #if Loaderchip = 2561
      66. $loader = &H1FC00
      67. Const Maxwordbit = 7
      68. Open "COM1:" For Binary As #1
      69. Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      70. #endif
      71. #if Loaderchip = 16
      72. $loader = $1c00
      73. Const Maxwordbit = 6
      74. Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
      75. #endif
      76. Const Maxword =(2 ^ Maxwordbit) * 2
      77. Const Maxwordshift = Maxwordbit + 1
      78. Const Cdebug = 0
      79. #if Cdebug
      80. Print #1 , Maxword
      81. Print #1 , Maxwordshift
      82. #endif
      83. Dim Bstatus As Byte , Bretries As Byte , Bblock As Byte , Bblocklocal As Byte
      84. Dim Bcsum1 As Byte , Bcsum2 As Byte , Buf(128) As Byte , Csum As Byte
      85. Dim J As Byte , Spmcrval As Byte
      86. Dim Z As Long
      87. Dim Vl As Byte , Vh As Byte
      88. Dim Wrd As Word , Page As Word
      89. Dim Bkind As Byte , Bstarted As Byte
      90. Disable Interrupts
      91. 'Waitms 100
      92. Const Nak = &H15
      93. Const Ack = &H06
      94. Const Can = &H18
      95. 'Config Pinb.2 = Output
      96. 'Portb.2 = 1
      97. 'Config Pinb.3 = Output
      98. 'Portb.3 = 1
      99. Config Pina.7 = Output
      100. Beep Alias Porta.7
      101. Config Portc.3 = Output
      102. Set Portc.3
      103. Config Pine.6 = Output
      104. modul1 Alias Porte.6
      105. Config Pine.5 = Output
      106. modul2 Alias Porte.5
      107. Config Pine.4 = Output
      108. modul3 Alias Porte.4
      109. Reset modul1
      110. Reset modul2
      111. Reset modul3
      112. 'Config Pina.3 = Output
      113. 'Porta.3 = 1
      114. 'Config Pina.2 = Output
      115. 'Porta.2 = 1
      116. $timeout = 200000
      117. Bretries = 5
      118. Testfor123:
      119. #if Cdebug
      120. Print #1 , "Try " ; Bretries
      121. Print #1 , "Wait"
      122. #endif
      123. Bstatus = Waitkey(#1)
      124. #if Cdebug
      125. Print #1 , "Got "
      126. #endif
      127. Print #1 , Chr(bstatus);
      128. If Bstatus = 123 Then
      129. Bkind = 0
      130. Goto Loader
      131. Elseif Bstatus = 124 Then
      132. Bkind = 1
      133. Goto Loader
      134. Elseif Bstatus <> 0 Then
      135. Decr Bretries
      136. If Bretries <> 0 Then Goto Testfor123
      137. End If
      138. 'For J = 1 To 10
      139. ' Toggle Portb.2 : Waitms 100
      140. ' Toggle Beep : Waitms 100
      141. 'Next
      142. #if Cdebug
      143. Print #1 , "RESET"
      144. #endif
      145. Goto _reset
      146. Loader:
      147. #if Cdebug
      148. Print #1 , "Clear buffer"
      149. #endif
      150. Do
      151. Bstatus = Waitkey(#1)
      152. Loop Until Bstatus = 0
      153. For J = 1 To 3
      154. 'Toggle Portb.2 : Waitms 50
      155. Toggle Beep : Waitms 50
      156. Next
      157. If Bkind = 0 Then
      158. Spmcrval = 3 : Gosub Do_spm
      159. Spmcrval = 17 : Gosub Do_spm
      160. End If
      161. Bretries = 10
      162. Do
      163. Bstarted = 0
      164. Csum = 0
      165. Print #1 , Chr(nak);
      166. Do
      167. Bstatus = Waitkey(#1)
      168. Select Case Bstatus
      169. Case 1:
      170. Incr Bblocklocal
      171. Csum = 1
      172. Bblock = Waitkey(#1) : Csum = Csum + Bblock
      173. Bcsum1 = Waitkey(#1) : Csum = Csum + Bcsum1
      174. For J = 1 To 128
      175. Buf(j) = Waitkey(#1) : Csum = Csum + Buf(j)
      176. Next
      177. Bcsum2 = Waitkey(#1)
      178. If Bblocklocal = Bblock Then
      179. If Bcsum2 = Csum Then
      180. Gosub Writepage
      181. Print #1 , Chr(ack);
      182. Else
      183. Print #1 , Chr(nak);
      184. End If
      185. Else
      186. Print #1 , Chr(nak);
      187. End If
      188. Case 4:
      189. If Wrd > 0 Then
      190. Wrd = 0
      191. Spmcrval = 5 : Gosub Do_spm
      192. Spmcrval = 17 : Gosub Do_spm
      193. End If
      194. Print #1 , Chr(ack);
      195. 'Portb.3 = 0
      196. Waitms 20
      197. Goto _reset
      198. Case &H18:
      199. Goto _reset
      200. Case 123 : Exit Do
      201. Case 124 : Exit Do
      202. Case Else
      203. Exit Do
      204. End Select
      205. Loop
      206. If Bretries > 0 Then
      207. Waitms 1000
      208. Decr Bretries
      209. Else
      210. Goto _reset
      211. End If
      212. Loop
      213. Writepage:
      214. If Bkind = 0 Then
      215. For J = 1 To 128 Step 2
      216. Vl = Buf(j) : Vh = Buf(j + 1)
      217. !lds r0, {vl}
      218. !lds r1, {vh}
      219. Spmcrval = 1 : Gosub Do_spm
      220. Wrd = Wrd + 2
      221. If Wrd = Maxword Then
      222. Wrd = 0
      223. Spmcrval = 5 : Gosub Do_spm
      224. Spmcrval = 17 : Gosub Do_spm
      225. Page = Page + 1
      226. Spmcrval = 3 : Gosub Do_spm
      227. Spmcrval = 17 : Gosub Do_spm
      228. End If
      229. Next
      230. Else
      231. For J = 1 To 128
      232. Writeeeprom Buf(j) , Wrd
      233. Wrd = Wrd + 1
      234. Next
      235. End If
      236. 'Toggle Portb.2 : Waitms 10 : Toggle Portb.2
      237. Toggle Beep : Waitms 10 : Toggle Beep
      238. Return
      239. Do_spm:
      240. Bitwait Spmcsr.0 , Reset
      241. Bitwait Eecr.1 , Reset
      242. Z = Page
      243. Shift Z , Left , Maxwordshift
      244. Z = Z + Wrd
      245. !lds r30,{Z}
      246. !lds r31,{Z+1}
      247. #if(loaderchip = 128) Or(loaderchip = 2561)
      248. !lds r24,{Z+2}
      249. !sts rampz,r24
      250. #endif
      251. Spmcsr = Spmcrval
      252. !spm
      253. nop
      254. nop
      255. Return
      Alles anzeigen
    • Ich habe Grundsatzfragen. Ein Bord mit 2561 Prozesor habe ich nicht, wo bekomme ich dein Bord? Wäre eine Alternative zu Prozessoren wie Atmega 128 und ähnlich baugleiche.
      Nun, wie arbeitet eigentlich ein Bootlader genau. Was davon ist Anwendung, was ist Betriebssystem? Damit ein Bootlader funktionieren kann, benötigt er die entsprechenden Routinen für die Bauteile, die zum umsetzen benötigt werden. Welche außer Uart,Usart müssten das sein?

      Mich hat das Thema interessiert. Habe nur einen Atmega128 zum ausprobieren. Habe dem einen Bootlader für Atmega128 aufgespielt, per ISP Programmer. Dieser ist von MCS.
      Er erwartet ebenso eine Bootlader-Startbedingung über die serielle Schnittstelle, und bekommt auch Hex 7B (Dezimal 123) gesandt. Es tut sich aber auch da nichts. Irgendwie funktioniert das mit diesem Bootlader (bei mir derzeit auch nicht). Habe mir mal diesen Bootlader (128.bas) und deinen für 2561 per Bascom in einen Hexfile compilieren lassen, und dann den jeweiligen Hexfile von einem Disassembler übersetzen lassen.

      Dich wird nur deine Version für den 2561 interessieren. Ich habe, da kein 2561 verfügbar, die $Loaderanweisung raus lassen müssen. Das bedeutet, die Adressen beziehen sich dann auf den normalen Bereich, nicht den Bootloderbereich. Falls Du diese Disassembler-Version für den 2561 analysieren möchtest, kann ich dir den 67 KB Textfile senden.
      Ich analysiere derweil, (sobald ich für sowas Zeit habe, meine 128iger Version. (In dieser Version ist nichts, oder mir nichts bekanntes hinzu gefügt worden, müsste somit funktionieren)
      Da diese Version auch nicht reibugslos funktioniert, kann es an diversen Zusammenhängen, Verständnissen meinerseits hapern.

      In deiner Programmversion wird ein Code 123 bis zu 5 mal erwartet. Danach springt der Ablauf nicht in die Laderroutine, sondern zum Generellen Reset. nun, wenn dort ein Sprung zum Anfang vom Bootlader steht, dreht sich da alles im Kreise, kommt da nie raus. (Meine Meinung)
      Wird 123 innerhalb der Abfrage erkannt, wird zum Loderteil gesprungen. Dort wird zuerst gewisse Pages gelöscht. Soweit, so gut.
      Nur, womit kann denn das sinngemäße Betriebsystem (das z.B. den Uart usw bedient), erkennen ob ein 123 Code empfangen wurde? Das wäre die Voraussetzung!
      Passt also etwas nicht in der Anweisung, die den Uart bedienen soll?
    • Prepe schrieb:

      4. Lockbits sind richtig gesetzt und entsprechen exact dem was mit der $prog Anweisung gesetzt wird.
      Ich sehe das anders.

      Zum einen sperrst du dich beim Entwickeln des Bootloaders selber aus, wenn du alles mögliche sperrst (Lockbits), und zum anderen stimmt die von dir im Programm angegebene Bootadresse nicht mit dem überein, was in den Fusebits eingestellt ist. Stichwort Boot-Loader-Adresse ($Loader=..) und Bootloader-Größe.

      Lockbits setzt man sinnvoller weise erst, wenn der Bootloader zufriedenstellen funktioniert.
      Bis dahin braucht es keine $Prog ... Anweisung
      Man vergisst es zu ändern wenn man was ausprobiert.

      Du solltest das auskommentieren und die Lock- und Fusebits von Hand setzen (alles entsperren), bis der Bootloader korrekt arbeitet.

      Wenn du dann den fertigen Bootloader für eine Serie an Controllern verwenden willst, kannst du ja die Einstellung entsprechend mit $Prog in den Code schreiben.

      Ich vermute mal, dass du dich mit den programmierten Einschränkungen selber ausgesperrt hast und deswegen der Bootloader hängen bleibt.
      Kann natürlich auch daher kommen, wenn der Controller von einer anderen Adresse ausgeht als die tatsächliche Lokation vom Bootloader.


      bitlogger schrieb:

      Danach springt der Ablauf nicht in die Laderroutine, sondern zum Generellen Reset. nun, wenn dort ein Sprung zum Anfang vom Bootlader steht, dreht sich da alles im Kreise, kommt da nie raus. (Meine Meinung)
      Damit das nicht passiert, gibt es die Fusebits.

      Ein Reset bewirkt einen Sprung zum Bootloader an die Adresse, die in den Fusebits festgelegt ist (sofern das korrekt gesetzt ist).
      Ein Goto _Reset bzw Goto 0 ist kein Reset. Der Reset-Vector zeigt dann auf den ersten Befehl, der nach der Vectortabelle steht, wenn denn ein Programm (außer dem Bootloader) im Controller vorhanden ist. Und der Reset-Vector besteht aus einer JMP-Anweisung mit einem Sprung hinter die Vector-Tabelle.

      Damit ist klar, wenn man Goto 0 ausführt, dass dann an Adresse 0 die Anweisung gelesen (JMP adresse) und diese dann ausgeführt wird.

      Man kann sich das so vorstellen.
      Wenn der Controller einen Reset erkennt, schaut er in seinen Fusebits nach, ob das Fusebit "Reset-Vector = Boot-Vector" programmiert ist, wenn ja, holt er ebenfalls aus den Fusebits die Startadresse des Bootloaders und füttwert damit den Programmcounter. Der erste auszuführende Anweisung steht also an der Start-Adresse des Bootloaders.

      Der eigentliche Reset-Vektor an Flash-Adresse 0 hat damit nichts zu tun.
      Er ist nur für die Applikation relevant. Denn ab Adresse 0 steht erst mal die Vector-Tabelle des Programms, dem der Code folgt.
      Der 1. Vector ist der Reset-Vector, in dem ein JMP steht zur 1. Anweisung nach der Vector-Tabelle.

      Wird bei einem Reset erkannt, dass "Reset-Vector = Boot-Vector" nicht programmiert ist, wird die Adresse 0 in den Programmcounter geladen und die Anweisung an dieser Stelle ausgeführt.

      Daraus ergibt sich eigentlich schon das "Reset-Vector = Boot-Vector"erhalten, wenn im Bootloader ein Goto 0 ausgeführt wird, was dann passiert.