Archive: Month 12, Year 2013

Software-Reset aus dem Arduino Leonardo herauspatchen

19.12.2013 yahe arduino code hardware legacy security

Der Arduino Leonardo, der nun seit etwa einem Jahr auf dem Markt ist, besitzt dank seines ATmega 32u4 direkt die Möglichkeit, eine USB-Verbindung mit dem PC aufzubauen. Auf dem Arduino Uno war dafür ein separater Mikrocontroller zuständig. Durch diese Änderung hat sich jedoch auch die Art, wie Resets über den USB-Anschluss angestoßen werden, geändert. Dieser Reset ist inzwischen eine reine Software-Routine und kann falls nötig herausgepatcht werden.

Der Software-Reset wird ausgeführt, indem vom PC aus eine serielle Verbindung mit 1200 Baud aufgebaut und wieder geschlossen wird. Die auf dem Arduino Leonardo laufende Software interpretiert dies als Wunsch, einen Reset durchzuführen. Dieser Reset kann im Anschluss zum Beispiel genutzt werden, um einen neuen Sketch auf das Gerät zu laden. In Fällen, in denen mit Hilfe der Arduinos jedoch z.B. eine Kleinserie gefertigt wird, kann der Wunsch bestehen, das einfache Aufspielen von neuen Sketches zu unterbinden. Hierfür sollte man bei seinem Arduino-IDE Installationsverzeichnis einmal in die Datei "/hardware/arduino/avr/cores/arduino/CDC.cpp" blicken. In dieser findet sich die Funktion "CDC_Setup()", die folgenden Passus enthält:

if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r)
{
  // auto-reset into the bootloader is triggered when the port, already
  // open at 1200 bps, is closed.  this is the signal to start the watchdog
  // with a relatively long period so it can finish housekeeping tasks
  // like servicing endpoints before the sketch ends

  // We check DTR state to determine if host port is open (bit 0 of lineState).
  if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
  {
    *(uint16_t *)0x0800 = 0x7777;
    wdt_enable(WDTO_120MS);
  }
  else
  {
    // Most OSs do some intermediate steps when configuring ports and DTR can
    // twiggle more than once before stabilizing.
    // To avoid spurious resets we set the watchdog to 250ms and eventually
    // cancel if DTR goes back high.

    wdt_disable();
    wdt_reset();
    *(uint16_t *)0x0800 = 0x0;
  }
}

Um den Software-Reset zu deaktivieren, muss dieser Code einfach vollständig auskommentiert werden. Anschließend ist ein Reset nur noch durch Betätigung des Reset-Buttons oder durch manuelles Verbinden des RESET-Pins mit einem GND-Pin möglich. Natürlich ist es auch möglich, den Software-Reset später wieder zu aktivieren. Dazu muss der vormals auskommentierte Quelltextblock wieder einkommentiert und einmal ein Sketch durch einen rechtzeitigen manuellen Reset geflasht werden.


Zwei Arduinos miteinander verbinden

18.12.2013 yahe arduino hardware legacy

Derzeit arbeite ich mal wieder ein wenig an calc.pw, da der vorhandene Code für ein Arduino allein inzwischen zu umfangreich wird. Deshalb sehe ich mir derzeit an, wie ich den Programmcode auf zwei Arduinos verteilen kann. Es bestünde natürlich die Möglichkeit, auf ein anderes Mikrocontroller-Board zu wechseln, das ist jedoch mit höheren Aufwänden verbunden. Zudem verwendet selbst der Arduino Uno R3 mehrere Mikrocontroller (einen ATmega 328 für die Sketchausführung und einen ATmega 16u2 für die USB-Kommunikation).

Das erste Problem, das einem begegnet, ist das richtige Anschließen des zweiten Arduinos und die Kommunikation zwischen den beiden Arduinos. Beides lässt sich mit vier Verbindungen lösen:

  • der +5V-Pin von Arduino A wird mit dem +5V-Pin von Arduino B verbunden
  • ein GND-Pin von Arduino A wird mit einem GND-Pin von Arduino B verbunden
  • der RX-Pin (Pin 0) von Arduino A wird mit dem TX-Pin (Pin 1) von Arduino B verbunden
  • der TX-Pin (Pin 1) von Arduino A wird mit dem RX-Pin (Pin 0) von Arduino B verbunden

Anschließend kann man unter Verwendung der Serial-Schnittstelle Daten zwischen den beiden Arduinos hin und herschicken. Das funktioniert soweit auch ganz gut, hat aber ein kleines Problem: Es mangelt an einer ordentlichen Synchronisation zwischen den beiden Arduinos. Normalerweise übernimmt Arduino A die Führung, während Arduino B die Befehle von Arduino A ausführt. Hier muss jedoch dafür gesorgt werden, dass beide Arduinos wissen, dass der jeweils andere für die Kommunikation bereit ist. Erhalten jedoch beide gleichzeitig Strom, beginnt bei ihnen die Ausführung der Setup-Routine. Je nach Umfang kann sie jedoch bei dem einen früher fertig werden als bei der anderen. Vielleicht benötigt die eine auch Nutzereingaben, sodass nicht einfach nach einer kurzen Verzögerung die Arbeitsbereitschaft vorausgesetzt werden kann.

Zwei Arduinos miteinander verbinden

Die Lösung, die mir hierfür in den Sinn kam, ist, dass Arduino A, das die Führung übernimmt, einfach selbst bestimmt, wann Arduino B mit der Setup-Routine beginnen darf. Hierfür lasse ich Arduino A einfach den RESET-Pin von Arduino B steuern. Das sieht nun insgesamt wie folgt aus:

  • Arduino A setzt den Pin, der mit dem RESET-Pin von Arduino B verbunden ist, auf LOW
  • Arduino A führt sein Setup durch und startet dabei auch die serielle Kommunikation
  • Arduino A setzt den Pin, der mit dem RESET-Pin von Arduino B verbunden ist, auf HIGH
  • Arduino A wartet auf die Fertig-Meldung von Arduino B
  • Arduino B führt sein Setup durch und startet dabei auch die serielle Kommunikation
  • Arduino B sendet die Fertig-Meldung an Arduino A
  • Arduino A kann Befehle an Arduino B senden

*Arduino A weiß, dass Arduino B bereit ist, indem es eine entsprechende Fertig-Meldung zugesandt bekommt. Arduino B wiederum weiß indirekt, dass Arduino A bereit ist, da es nur dann läuft, wenn Arduino A das möchte.

Man sollte übrigens die Verbindungen zwischen den Datenpins (RX, TX) und RESET am besten mit einem Widerstand (1kΩ bis 10kΩ sollten problemlos funktionieren) absichern, um Überspannungen zu verhindern. In ersten, einfachen Tests hat es jedoch auch komplett ohne funktioniert.


Search

Links

RSS feed

Categories

administration (40)
arduino (12)
calcpw (2)
code (33)
hardware (16)
java (2)
legacy (113)
linux (27)
publicity (6)
review (2)
security (58)
thoughts (21)
windows (17)
wordpress (19)