Thomas Kortschack

Hobby- und Projekt-Website

CAN FD Interface

Nachdem ich privat meist nur mit Mikrocontrollern der Firma Atmel in Berührung gekommen bin, reizte es mich mir die Cortex-Familie anzusehen.

Zudem wollte ich einen Einstieg in KiCad finden, einer Open Source Software zur Entwicklung von Leiterplatten.

Idee

Aller Anfang ist schwer und so war ich anfangs doch sehr unschlüssig welchen Mikrocontroller ich zu den Testzwecken verwenden möchte. Letztlich kam bei mir die Überlegung auf, dass ich vor Jahren bereits einen CAN-Servodecoder (CAN 2.0B) entworfen habe, wobei es mittlerweile auch CAN FD gibt und ich das Bus-System recht interessant finde. Besonders weil man statt 8 Bytes nun bis zu 64 Bytes in einer CAN-Nachricht übertragen kann.

Um sich z.B. per PC in einen CAN-Bus einzuklinken, braucht man ein CAN-Interface. Da gibt es ein paar auf den Markt, wobei sicherlich vielen die CAN-Interfaces von Vector ein Begriff sind und neuere Modell auch CAN FD unterstützen. Leider besitze ich privat kein CAN-Interface, welches CAN FD unterstützt und mit älteren CAN-Interfaces anderer Hersteller hatte ich in der Vergangenheit durchaus meine Probleme hinsichtlich Treibern, mitgelieferten Bibliotheken bzw. Protokollbeschreibungen. Daher kam die Idee auf, das mal selbst zu versuchen.

Meine Entscheidung viel auf einen leistungsstarken Arm Cortex-M4 Mikrocontroller STM32G474CET6 von STMicroelectronics, der neben USB auch drei CAN FD Schnittstellen besitzt (kann natürlich auch klassisches CAN).

Schaltungsentwurf

In KiCad habe ich einen Schaltplan und einen Entwurf der Leiterplatte umgesetzt.

Board

Neben dem STM32G474CET6 Mikrocontroller sind die Bausteine für drei CAN FD Channels verbaut, wobei hierfür jeweils ein galvanisch getrennter CAN-Transceiver ISO1042 von Texas Instruments zum Einsatz kommt. Um den Transceiver auf der CAN-Seite mit Energie zu versorgen (Transceiver-side supply voltage) nutze ich jeweils einen DC/DC Converter TBA 1-0511 von TRACO Power.

Die Energieversorgung der Schaltung erfolgt direkt über USB. Einige LEDs habe ich platziert, um später u.a. pro CAN Channel die Datenübertragungen in Richtung RX, TX anzuzeigen bzw. bei Fehlern eine Rückmeldung zu geben. Vorgesehen habe ich auch zwei Tasten, wobei ich noch nicht ganz sicher bin, wofür ich die letztlich nutzen könnte (evt. Geräteidentifikation, Wechsel in einen Bootloader, ...).

Neben der SWD/JTAG Schnittstelle, die als Programmier-/Debugschnittstelle dient, habe ich zusätzlich die Datenleitungen RX und TX der seriellen Schnittstelle (UART) auf eine Stiftleiste gelegt. Eigentlich ist das nicht nötig, aber so kann ich mich auch mit einem vorhandenen 6-poligen USB/TTL-Adapterkabel einklinken (nur GND, RX, TX angeschlossen).

Gehäuse

Von vornherein habe ich das Board so ausgelegt, dass dies von der Größe in ein fertiges Gehäuse passt. Zugegeben hätte ich auch hier die Schaltung etwas kleiner machen und ein eigenes Gehäuse per 3D-Drucker (FDM) drucken können. Ob es sich jedoch lohnt ist eine andere Frage, zumal das Drucken eines solch großen Objektes aus mindestens zwei Halbschalen stundenlang dauern würde.

In KiCad lässt sich das Board inklusive Bauteile als STEP-Datei exportieren, die man in einer CAD-Anwendung importieren kann.

3D

Die Frontplatten für das Gehäuse möchte ich später gravieren und fräsen, wobei ich in der 3D-Zeichnung bereits Bohrungen eingezeichnet habe, die für die Tasten bzw. angewinkelten Lichtleiter der LEDs nötig sind. Sämtliche Beschriftungen fehlen hier natürlich noch.

Inbetriebnahme

Gerade für mich als Informatiker, der von Elektrotechnik nur bedingt Ahnung hat, ist es immer wieder spannend, ob nach der Platinenfertigung und Bestückung bei der ersten Inbetriebnahme soweit alle Bausteine richtig verdrahtet sind, nichts in Flammen aufgeht oder vielleicht aufgrund eines Schaltungsfehlers gar nichts funktioniert. Die erste Energiezufuhr erfolgte auch nicht direkt mittels USB-Kabel am PC, sondern über ein Labornetzgerät mit Strombegrenzung, wobei das alles recht gut ausgesehen hat.

Hinsichtlich der Softwareentwicklung habe ich mich für die auf die Eclipse basierende STM32CubeIDE entschieden, die auch einen Konfigurator enthält, um beispielsweise Pin- und Clock-Einstellungen zu setzen.

Pinout

Natürlich war dann recht schnell mein Interesse geweckt, mal irgendwas zum Leben zu erwecken und so versuchte ich mittels Funktionen HAL_GPIO_TogglePin und HAL_Delay eine LED blinken zu lassen. Nachdem man unter den "Debug Configurations" eine neue Configuration anlegt und dort z.B. einen ST-LINK bzw. SEGGER J-Link als "debug probe" konfiguriert, lässt sich nach einem Buildvorgang damit die Firmware flashen. Umso mehr freut es dann natürlich, wenn die LED auch blinkt.

Daraufhin folgten weitere Tests:

  • Lassen sich alle LEDs ansteuern? => Ja
  • Sind die Zustände der Tasten mittels HAL_GPIO_ReadPin Funktion abrufbar? => Ja
  • Lassen sich die Jumper ebenfalls mittels HAL_GPIO_ReadPin Funktion abfragen? => Ja
  • Lässt sich mittels HAL_UART_Transmit Funktion, USB/TTL-Adapterkabel und Terminal-Programm (z.B. HTerm) z.B. ein Text "Hallo Welt\r\n" empfangen => Ja

Um die drei CAN-Channel ausprobieren zu können, habe ich einen Testaufbau mit dem alten CAN-Servodecoder und der Märklin Gleisbox verkabelt und zudem das CAN FD Interface angeschlossen.

Testaufbau

Provisorisch habe ich beim Betätigen der Taste 1 am CAN FD Interface eine CAN-Nachricht (CAN 2.0B) mittels HAL_FDCAN_AddMessageToTxFifoQ Funktion gesendet, um den Servo mit der Adresse 1 zu drehen (CAN CS2 Protokoll 2.0). Wiederholungen an allen drei CAN Channels haben gezeigt, dass die CAN-Nachricht ankommt und der Servo sich in Bewegung setzt.

Fehlersuche

Leider musste ich feststellen, dass meine Schaltung ohne Debugger (Segger J-Link EDU bzw. ST-Link V3) nach dem Aus- und Wiedereinschalten nicht startet. Zunächst vermutete ich, dass ich vielleicht im Schaltplan einen Fehler gemacht habe, u.a. was den Reset-Pin (NRST) bzw. den PB8-Pin (BOOT0) angeht, der bei mir für CANFD1_RX genutzt wird. Mit dem Segger Ozone J-Link Debugger konnte ich im Assembler-Code während der Laufzeit jedoch feststellen, dass der Mikrocontroller in einer Endlosschleife läuft, die in einem externen Codeteil liegt und die main-Funktion und meine Codeteile deshalb gar nicht erreicht werden.

Ozone Disassembly.png

Für den J-Link hatte ich mir bereits mit einer 20-poligen Pfostenbuchse (2x10, RM 2,54 mm), einem Flachbandkabel und einer 10-poligen Buchsenleiste (2x5, RM 2,00 mm) ein eigenes SWD/JTAG-Debug-Kabel hergestellt. Auf dem Markt ist auch ein STLINK-V3SET erhältlich, welches ein Adapter-Board enthält und dort auch mein bereits genanntes SWD/JTAG-Debug-Kabel an den dort beschrifteten 20-poligen JTAG-Wannenstecker passt. Über den ST-Link V3 und dem STM32CubeProgrammer konnte ich im Anschluss die sogenannten Option Bytes einsehen und habe hier ein NUCLEO-G474RE Entwicklungsboards (STM32G474RET6) mit meinem CAN FD Interface (STM32G474CET6) verglichen. In meinem Fall ist es entscheidend, dass nSWBOOT0 (Software BOOT0) deaktiviert ist, was standardmäßig auch beim genannten NUCLEO-G474RE im Auslieferungszustand der Fall ist.

Option Bytes nSWBOOT0

Kleiner Haken, große Wirkung! Anders als bei Atmel/Microchip AVR Mikrocontrollern, bei denen man z.B. über Atmel Studio die Fuses direkt setzen kann, habe ich in der STM32CubeIDE keine Möglichkeit gefunden die Option Bytes eines STM32 Mikrocontrollers auszulesen bzw. zu ändern. Für alle STM32 Neueinsteiger/Umsteiger sei somit erwähnt, dass das relativ komfortabel mittels ST-Link und STM32CubeProgrammer funktioniert.

Offene Baustellen

Zum Testen der USB-Schnittstelle habe ich in der STM32CubeIDE unter "Pinout & Configuration -> Middleware" die Library USB_Device aktiviert, indem man dort z.B. die "Communication Device Class (Virtual Port Com)" einstellt. Für das Gerät steht dann im Betriebssystem eine virtuelle Schnittstelle zur Verfügung. Weitere Funktionstest habe ich hier aber noch nicht durchgeführt.