Python 3: Profiling von Skripten

Auf GitHub habe ich in einem Issue die Anfrage bekommen, die Software sei langsam. Ja, gefühlt ist die Software nicht die schnellste. Aber wie langsam genau? Und für die Optimierung wichtiger,  wo geht die Zeit verloren?

Das kann mit Profiling herausfinden. Ich will hier eine Lösung beschreiben, die ich für elegant und schnell halte, wobei es sich besseres/schöneres/… gibt.

Zunächst installiert man gprof2dot und dot:

pip3 install --user gprof2dot
sudo apt install dot

python3 bietet mit cProfile bereits ein Modul an, welches das Profiling eines Python-Skripts übernimmt. Mit folgendem Kommando startet man das Profilen des Skripts put_characteristic.py (mit dessen Parametern). Für das Module cProfile wird nur der Parameter -o genutzt, der die Ausgabedatei festlegt.

python3 -m cProfile -o profile.pstats \
        homekit/put_characteristic.py -f koogeek.json -c 1.8 -v false

Anschließend verwendet man gprof2dot und dot um eine mehr oder weniger übersichtliche Grafik zu erzeugen, welche aufzeigt, wo die meiste Zeit “liegen bleibt”. Das Ergebnis sieht in unserem Beispiel wie folgt aus:

Ergebnis eines Profilinglaufs

Allerdings muss man auch hier berücksichtigen, dass die Ergebnisse eines einzelnen Laufs nicht repräsentativ sind. Hier sollten mehrere Durchläufe hintereinander geprofiled werden. Allerdings kann man auch bei einem Durchlauf erkennen, das hier Zeroconf zum Auffinden des HomeKit Geräts und das Erstellen der Sessionkeys viel Zeit verbrauchen.

Bilder & Videos fürs Blog

Von Zeit zu Zeit will man in einem Blog Bilder und Videos veröffentlichen. Dabei würde ich gerne manches unter Kontrolle behalten. Deshalb dieser kurze Artikel, der einige Tricks verraten soll.

Bilder

Bilder erstelle ich inzwischen eigentlich immer mit einer Handy-Kamera. Dabei werden inzwischen über die Exif-Daten viele Informationen preis gegeben. Mobiltelefone fügen hier auch gerne Felder ein, die nicht jeden etwas angehen:

  • GPS Position der Aufnahme,
  • Informationen über das Gerät und
  • viele weitere

Einsehen kann man die Exif-Daten eines Fotos mit:

identify -verbose $BILD

Die Exif-Daten können (und sollten) mit folgendem Kommando entfernt werden:

convert $IN -strip $OUT

Für das Blog ist es ab und zu notwendig ein Bild in der Größe zu reduzieren (hier auf 50%):

covert $IN -resize 50% $OUT

Alternativ ist auch die Angabe der Größe in Pixeln (kann das Bild vergrößern):

covert $IN -resize 600@ $OUT

In beiden Fällen werden die Seitenverhältnisse bei behalten.

Videos

Da bei meinen Videos der Ton keine Rolle spielt, wird dieser mit folgendem Befehl entfernt:

ffmpeg -i $INPUT -an $OUTPUT

Oft möchte man das Video nach der Aufnahme um 90 Grad im Uhrzeigersinn drehen (transpose=2 für 90 Grad gegen den Uhrzeigersinn):

ffmpeg -i $INPUT -filter:v transpose=1 $OUTPUT

Einzelbilder können mit folgendem Kommando extrahiert werden:

ffmpeg -i $INPUT -ss $second -vframes 1 $OUTPUT.png

Einen Ausschnitt aus einem Video kann man mit folgendem Kommando erstellen:

ffmpeg -i $INPUT -filter:v crop=$WIDTH:$HEIGHT:$X:$Y $OUTPUT

Anschließend verwandelt man das Video in webm mit einer Bandbreite von 1 Mbit/s  (welches in WordPress direkt abgespielt werden kann):

ffmpeg -i $INPUT -vcodec libvpx-vp9 -b:v 1M $OUTPUT$.webm

 

FPGA: Eingabe über Schalter

Als weiterer Schritt mit dem FPGA Board nach der 7-Segment Anzeige soll die Möglichkeit darstellen ein Byte  über Schalter einzugeben. Zusätzlich soll noch ein Taster verwendet werden, um eine Eingabe gezielt vornehmen zu können. Auch hier gilt, dass auf teureren Boards wie dem Terasic Cyclone V GX Starter Kit entsprechende Hardware bereits vorhanden ist.

Hardware

Auf dieser Webseite wird beschrieben, wie Taster und Schalter einen einen Spartan-3A FPGA angebunden werden. Eine Adaption dieser Schaltung, bei der auch der Taster active low und zusätzlich mit einem Kondensator beschaltet ist, findet man hier:

Aufgebaut auf der üblichen Lochrasterplatine sieht die Platine dann so aus (hier wären die Schalter eine Nummer größer besser gewesen):

Die Pins auf der oberen Seite besitzen folgende Bedeutung:

PIN NummerBedeutung
Pin 0 (links)Switch 1 (Bit 7)
Pin 1 Switch 2 (Bit 6)
Pin 2 Switch 3 (Bit 5)
Pin 3Switch 4 (Bit 4)
Pin 4Switch 5 (Bit 3)
Pin 5Switch 6 (Bit 2)
Pin 6Switch 7 (Bit 1)
Pin 7Switch 8 (Bit 0)
Pin 8Taste
Pin 9VCC
Pin 10 (rechts)GNG

Ansteuerung

Leider sind real existierende Schalter und Taster aufgrund ihrer Bauform nicht frei von Prellen. In der Wikipedia wird Prellen als “mechanisch ausgelöster Störeffekt bei elektromechanischen Schaltern und Tastern bezeichnet: Statt des sofortigen elektrischen Kontakts ruft die Betätigung des Schalters kurzzeitig ein mehrfaches Schließen und Öffnen des Kontakts hervor.”

Exemplarisch zeigt das folgende Bild das Prellen des verwendeten Tasters:

Bilder, die die Situation noch besser verdeutlichen, finden sich im oben verlinkten Wikipedia-Artikel.

Das Entprellen des Tasters habe ich nicht selbst implementiert sondern eine Implementierung von eewiki.net verwendet. Die Theorie ist, dass geprüft wird, ob der zu entprellende Eingang über einen definierten Zeitraum konstant bleibt. In dieser Implementierung wird über einen 19 bit Zähler ein Zeitraum von 10.5 ms bei 50 MHz verwendet. Somit wird erst nach 10.5 ms der Wert des Eingangs weiter gegeben.

Nachdem der Taster zum Einlesen der Werte nun entprellt wurde, ist der VHDL Code nur noch wenige Zeilen lang:

library IEEE;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity byte_input is
  PORT(
    clk:      in std_logic;
    switches: in std_logic_vector(7 downto 0);
    button:   in std_logic;
    data:     out std_logic_vector(7 downto 0);
    act:      out std_logic
  );
end byte_input;

architecture sim of byte_input is
  signal s_button: std_logic;
begin
  act < = s_button;

  debouncer: entity work.debounce
    port map (
      clk => clk,
      button => not button,
      result => s_button
    );
	
  process(clk)
  begin
    if rising_edge(clk) and s_button = '1' then
      data < = switches;
    end if;
  end process;
end sim;

Es wird zu jedem Clock-Cycle überprüft, ob die Taste gedrückt wurde und wenn ja, der Eingang der Schalter als std_logic_vector(7 downto 0) ausgegeben.

Im GIT findest sich ein kleines Demo-Repository, welches die eingetasteten Werte auf den 2 Siebensegmentanzeigen ausgibt.

Rezension: “CPU-Design – Entwurf eines RISC-Prozessors in VHDL” von Kai-Uwe Mrkor

Der Autor des Buches “CPU-Design – Entwurf eines RISC-Prozessors in VHDL”, Dipl.-Ing. (FH) Kai-Uwe Mrkor, arbeitet zur Zeit an der Technischen Hochschule Brandenburg als Mitarbeiter Labordienst Fachbereich Informatik und Medien.

Inhalt

Das Buch beschreibt nach Einführungen in Prozessorarchitektur (Kapitel 2), Programmierbare Logikanordnungen (Kapitel 3) und den verwendeten FPGA Cyclone II von Altera (Kapitel 4) die Anforderungen an den im Verlauf zu implementierenden Prozessor in Kapitel 5 sowohl der Registersatz als auch die geplante Teilmenge des MIPS-Befehlssatzes.

In Kapitel 6 widmet sich der Autor detailliert den Aufbau eines RISC-Prozessors mit MIPS-Architektur. Dabei wird zunächst eine Implementierung mit einem Takt pro Befehl vorgestellt, die in mehreren Iterationen aufgebaut wird. Dies ermöglicht es dem Leser von arithmetischen und logischen Befehlen über unbedingte und bedingte Sprünge und Load/Store Befehle alle geplanten Op-Codes des Prozessors nachzuvollziehen. Im 2. Teil dieses Kapitels demonstriert der Autor wie eine Ein-Takt-Implementierung durch die Einführung von Zwischenergebnissen (Pipelining) deutlich beschleunigt werden kann.

Kapitel 7 erweitert die implementierte CPU um sinnvolle Peripherie. Angesprochen werden parallele und serielle Schnittstellen sowie Ausgabe über LEDs und Siebensegmentanzeigen.

Kapitel 8 vereint die Ergebnisse aller bisheriger Kapitel und demonstriert die Funktionalität mit kleinen Beispielprogrammen.

Empfehlung

Das Buch bietet eine gute Auffrischung zu den Themen rund um Rechnerarchitektur. Der Aufbau der verschiedenen Stufen der CPU wird schlüssig beschrieben und ist mit den herunter ladbaren Quellen gut nachvollziehbar. Das Buch ist definitiv eine Empfehlung für alle, die sich eingehender mit dem praktischen Aufbau einer CPU in VHDL beschäftigen wollen.

Bezugsmöglichkeiten

Die genauen Daten des Buches:
Kai-Uwe Mrkor: CPU-Design – Entwurf eines RISC-Prozessors in VHDL; epubli Verlag Berlin; ISBN 978-3-8442-6666-5; 2013

Bestellbar über Epubli und natürlich bei Amazon. Die zum Buch gehörenden Dateien sind direkt und http://www.prozessorentwurf.de/ abrufbar.

FPGA: Testen von VHDL mit vunit

Will man seine in VHDL erstellten Komponenten testen bietet sich eine Simulation mit anschließender Überprüfung der entsprechenden Signale an. Dies manuell durchzuführen ist zeitaufwändig und fehleranfällig.

Eine Lösung bietet VUnit in Kombination mit GHDL an. GHDL ist ein quell offener Simulator für VHDL Programme. Leider ist GHDL nicht in den Debian Paketquellen enthalten, da die IEEE Bibliotheken von Debian als unfrei eingestuft werden. Also müssen wir dieses Paket selbst bauen und installieren. Dazu bietet sich eine VM / ein Docker Container oder ähnliches an, da einige Pakete zum Erstellen des Pakets notwendig sind. Folgende Kommandos erstellen aus den Quellen von github ein installierbares Debian-Paket:

apt update
apt install git gnat build-essential zlib1g-dev checkinstall
git clone https://github.com/ghdl/ghdl.git
git checkout v0.35
cd ghdl
./configure --prefix=/usr/local
make
checkinstall -y --install=no --requires=libgnat-6 \
  --maintainer=ghdl@lusiardi.de --nodoc --pkglicense=GPLv2 \
  --pkgversion=0.35
dpkg -i ghdl_0.35-1_amd64.deb

Vorteil: dieses Paket kann über die gewohnte Paketverwaltung installiert und auch wieder deinstalliert werden. Natürlich sollte man immer das aktuellste Release oder auch den Master mit git auschecken.

Anschließend installieren wir VUnit mit

pip install -U vunit_hdl

Nun können mit einem kleinen Python-Wrapper in VHDL geschriebene Unit-Tests ausgeführt werden:

#!/usr/bin/env python2

from os.path import join, dirname
from vunit import VUnit

root = dirname(__file__)

ui = VUnit.from_argv()
lib = ui.add_library("lib")
lib.add_source_files(join(root, "*.vhd"))
ui.main()

Wie sieht aber nun ein solcher Unit-Test aus? Nehmen wir als Beispiel einen 4-bit Parity Generator:

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY four_bit_parity IS
    PORT (
        data: IN std_logic_vector(3 DOWNTO 0);
        parity: OUT std_logic
    );
END ENTITY;

ARCHITECTURE behavior_four_bit_parity OF four_bit_parity IS
BEGIN
    parity <= data(0) xor data(1) xor data(2) xor data(3);
END behavior_four_bit_parity;

Ein entsprechender Unit-Test könnte nun so aussehen:

library IEEE;
use IEEE.std_logic_1164.all;

library vunit_lib;
context vunit_lib.vunit_context;

entity four_bit_parity_tb is
    generic (runner_cfg : string);
end four_bit_parity_tb;

architecture sim of four_bit_parity_tb is
    SIGNAL d_in: STD_LOGIC_VECTOR(3 DOWNTO 0);
    SIGNAL p: STD_LOGIC;
    constant clk_period : time := 10 ps;
begin
    main : process
    begin
        test_runner_setup(runner, runner_cfg);
        while test_suite loop
            if run("0000") then
                d_in <= "0000";
                wait for 10 ps;
                check_equal(p, '0');
            end if;
            if run("0001") then
                d_in <= "0001";
                wait for 10 ps;
                check_equal(p, '1');
            end if;
        end loop;
        test_runner_cleanup(runner);
    end process;

    uut: entity work.four_bit_parity port map (d_in, p);
END sim;

Nun kann man mit ./run.py die Tests durchführen und erhält (hoffentlich) folgendes Ergebnis:

$ ./run.py 
Re-compile not needed

Starting lib.four_bit_parity_tb.0000
Output file: vunit_out/test_output/lib.four_bit_parity_tb.0000_86984b0155942bf3d3645c1aa56926538590d91f/output.txt
pass (P=1 S=0 F=0 T=2) lib.four_bit_parity_tb.0000 (0.6 seconds)

Starting lib.four_bit_parity_tb.0001
Output file: vunit_out/test_output/lib.four_bit_parity_tb.0001_fdfc81920e3c3468dfe6138ee1107bbf4bea3958/output.txt
pass (P=2 S=0 F=0 T=2) lib.four_bit_parity_tb.0001 (0.6 seconds)

==== Summary =======================================
pass lib.four_bit_parity_tb.0000 (0.6 seconds)
pass lib.four_bit_parity_tb.0001 (0.6 seconds)
====================================================
pass 2 of 2
====================================================
Total time was 1.2 seconds
Elapsed time was 1.2 seconds
====================================================
All passed!

Frohes Testen! Weitere Informationen zu VUnit und den vorhandenen Funktionen findet man in der VUnit Dokumentation. Etwas ist allerdings zu beachten, dass eventuell nicht alle VHDL Konstrukte, die durch GHDL in Tests akzeptiert werden schlussendlich auch durch z.B. Quartus II synthetisierbar sind. Hier sind also eventuell Nacharbeiten am eigentlichen VHDL-Code notwendig.

FPGA: 7 Segmentanzeige

Als Fortsetzung zu meinen ersten Gehversuchen mit VHDL und FPGAs soll nun ein 1-Byte-Display aus 2 Siebensegmentanzeigen entstehen. So etwas ist auf besseren FPGA-Boards meist bereits integriert, nicht jedoch auf dem preiswerten Basisboard. In diesem Artikel wird z.B. beschrieben, wie auf einem Digilent Basys 3 Artix-7 FPGA Board diese Anzeige aufgebaut ist und wie man sie in Verilog anspricht. Hier werden nun leichte Abwandlungen davon vorgenommen.

Hardware

Auf dem Basys 3 Board werden Siebensegmentanzeigen mit gemeinsamer Anode und PNP-Transistoren verwendet. In meiner Bastelkiste fanden sich aber nur 2 Siebensegmentanzeigen und NPN-Transistoren (BC 337-16). Zusätzlich benötigt man die passenden Vorwiderstände. Die Vorwiderstände für die LED Segmente ergeben sich R = U/I = 3.3 V / 0.002 A = 150 Ohm (die LEDs benötigen 20mA zum Leuchten). Für die Transistoren verwende ich einen Vorwiderstand von jeweils 4k7 Ohm (Hilfe bei den Berechnungen hatte ich von Dr. Kilian). Die vorgestellte Schaltung skaliert natürlich auch für mehr als 2 Siebensegmentanzeigen.

Fertig aufgebaut auf Lochraster sieht das dann so aus. Ja, 20mm Siebensegmentanzeigen sind eigentlich zu groß:

Aufgebaute Schaltung

Die Pins auf der linken Seite besitzen folgende Bedeutung:

PIN NummerBedeutung
Pin 0 / GND (oben)Anschluss für Masse
Pin 1 / S0Für die Auswahl der rechten Siebensegmentanzeige auf High
Pin 2 / S1Für die Auswahl der linken Siebensegmentanzeige auf High
Pin 3 / AAktiviert Segment A der ausgewählten Siebensegmentanzeige
Pin 4 / BAktiviert Segment B der ausgewählten Siebensegmentanzeige
Pin 5 / CAktiviert Segment C der ausgewählten Siebensegmentanzeige
Pin 6 / DAktiviert Segment D der ausgewählten Siebensegmentanzeige
Pin 7 / EAktiviert Segment E der ausgewählten Siebensegmentanzeige
Pin 8 / FAktiviert Segment F der ausgewählten Siebensegmentanzeige
Pin 9 / GAktiviert Segment G der ausgewählten Siebensegmentanzeige
Pin 10 / DP (unten)Aktiviert den Punkt der ausgewählten Siebensegmentanzeige

Zuordnung der Segmente A bis G und DP auf der Siebensegmentanzeige:

Zuordnung der LEDs

Ansteuerung

Die Trägheit des Auges wird bei dieser Schaltung ausgenutzt, da die beiden Siebensegmentanzeigen jeweils abwechselnd aktiviert werden (mit ca. 1 kHz).

Folgende VHDL Entity soll implementiert werden:

Entity byte_display Is
  Port (
    clk      : In std_logic;
    enable   : In std_logic;
    data     : In std_logic_vector(7 Downto 0);
    segments : Out std_logic_vector(1 Downto 0);
    leds     : Out std_logic_vector(6 Downto 0)
  );
End byte_display;

Der clk-Eingang wird dem globalen Clock-Signal verbunden und wird für die Umschaltung der einzelnen Siebensegmentanzeige verwendet. Der Wert data wird intern gespeichert, wenn enable eine steigende Flanke hat und bleibt solange angezeigt, bis ein neuer Wert gesetzt wird. Die beiden ausgehenden Bits in segments aktivieren jeweils mit high-Werten eine der beiden Siebensegmentanzeigen und die Bits aus leds jeweils die entsprechende LED.

Eine Siebensegmentanzeige kann hexadezimal ein Nibble (also ein halbes Byte oder 4 Bit) darstellen. Die Umsetzung dieser 4 Bit in die 7 LEDs der Anzeige wird in einer eigenen VHDL-Prozedur durchgeführt:

PROCEDURE display_digit(
    SIGNAL digit : IN std_logic_vector (3 DOWNTO 0);
    SIGNAL leds : OUT std_logic_vector(6 DOWNTO 0)
  ) IS
BEGIN
 CASE digit IS          -- GFEDCBA
   WHEN "0000" => leds <= "0111111"; -- 0 ABCDEF
   WHEN "0001" => leds <= "0000110"; -- 1 BC
   WHEN "0010" => leds <= "1011011"; -- 2 ABDEG
   WHEN "0011" => leds <= "1001111"; -- 3 ABCDG
   WHEN "0100" => leds <= "1100110"; -- 4 BCFG
   WHEN "0101" => leds <= "1101101"; -- 5 ACDFG
   WHEN "0110" => leds <= "1111101"; -- 6 ACDEFG
   WHEN "0111" => leds <= "0000111"; -- 7 ABC
   WHEN "1000" => leds <= "1111111"; -- 8 ABCDEFG
   WHEN "1001" => leds <= "1101111"; -- 9 ABCDFG
   WHEN "1010" => leds <= "1110111"; -- A ABCEFG
   WHEN "1011" => leds <= "1111100"; -- B CDEFG
   WHEN "1100" => leds <= "1011000"; -- C DEG
   WHEN "1101" => leds <= "1011110"; -- D BCDEG
   WHEN "1110" => leds <= "1111001"; -- E ADEFG
   WHEN "1111" => leds <= "1110001"; -- F AEFG
 END CASE;
END display_digit;

Hier werden jeweils ein Eingangs- und ein Ausgangssignal  mit einem VHDL-Case-When umgesetzt. Es sind sicher noch andere Schreibweisen vorstellbar.

Die Übernahme des Eingabebytes data bei steigendem enable-Bit wird durch einen eigenen Prozess umgesetzt:

PROCESS (enable)
BEGIN
  IF rising_edge(enable) THEN
    FOR i IN 0 TO 1 LOOP
      -- digits sind ein internes Signal
      digits(i) <= data(((4 * i) + 3) DOWNTO (4 * i));
    END LOOP;
  END IF;
END PROCESS;

Steigt hier das enable-Signal an, so teilt die For-Schleife das anliegende data-Signal in die beiden internen digits auf. Dabei hilft die gleichzeitige Zuordnung mehrerer Signale mit der DOWNTO Schreibweise.

Ein paralleler Prozess wechselt mit 1 kHz zwischen beiden Siebensegmentanzeigen hin und her und zeigt dort jeweils das aktuelle Nibble an:

PROCESS (clk)
  VARIABLE digit_cntr : INTEGER := 0;
  VARIABLE digit : INTEGER := 0;
BEGIN
  -- select proper digit
  IF rising_edge(clk) THEN
    digit_cntr := digit_cntr + 1;
    IF (digit_cntr > 50000) THEN
      digit_cntr := 0;
      digit := digit + 1;
      IF (digit > 1) THEN
        digit := 0;
      END IF;
    END IF;
  END IF;
 
 -- display the nibble
  IF (digit = 0) THEN
    segments <= "01";
    display_digit(digits(0), leds);
  ELSE
    segments <= "10";
    display_digit(digits(1), leds);
  END IF;
END PROCESS;

Den vollständigen Code inkl. Zählerbeispiel findet man in byte_display.zip (den Code zum Entprellen des Tasters habe ich dem eewiki entnommen, vielen Dank für den verständlichen Artikel). In den FPGA übertragen und korrekt verkabelt ergibt das folgendes:

Viel Erfolg und Spass beim Nachvollziehen!

Update 26.02.2018
Jetzt auch im GIT: https://git.lusiardi.de/jlusiardi/vhdl_7seg

FPGA: Erste Schritte

Um mal wieder über den berühmten Tellerrand zu blicken will ich mich mal mit etwas neuem beschäftigen. Die Wahl fiel auf FPGAs. Während des Studiums habe ich mich leider durch Wahl eines alternativen Praktikums um eine erste Erfahrung gebracht.

Für einen ersten Einstieg benötigt man nur Software, keine Hardware. Die Software (zumindest von Intel/Altera kann man gratis herunterladen. Dazu unten mehr. Da ich das am Anfang nicht wusste, habe ich über Amazon die im Folgenden genannten Produkte erworben.

Einkauf

Gesamtkosten: keine 30€, da der Klon deutlich günstiger als das Original mit fast 400€ ist.

Erste Erfahrungen

Zunächst sollen einige wichtige Erkenntnisse aufgeführt werden. Zu den beiden genannten Softwarepaketen:

  1. Der Cyclone II wird bis maximal Quartus II Web Edition 13.0sp1  unterstützt. Diese kann kostenlos mit einem myAltera-Account heruntergeladen werden (4.8GB). Nach der Installation sind es ca. 16 GB, wobei man hier beim Installationsumfang sicher sparen kann. Neuere Versionen unterstützen nur neuere FPGAs. Gestartet wird das Programm auf 64-bit Systemen über ./bin/quartus –64bit aus dem Installationsverzeichnis.
  2. JTAG einrichten: unter Ubuntu 17.10 benötigt man zusätzliche udev-Regeln (Datei /etc/udev/rules.d/usbblaster.rules):
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6001",MODE="0666"
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6002",MODE="0666"
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6003",MODE="0666"
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6010",MODE="0666"
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6810",MODE="0666"

    Diese ermöglichen den Zugriff auf für nicht root Nutzer. Anschließend kopiert man die Board-Descriptions nach /etc/jtagd:

    cp $INSTALLDIR/linux64/pgm_parts.txt /etc/jtagd/jtagd.pgm_parts
    

    Weiter Informationen findet man unter bitsnbites.eu.

  3. Mit ModelSim-Intel FPGA Edition 10.5c kann man auch im myAltera-Account herunterladen (3.1GB). Nach der Installation sind es ca. 7 GB. Vor dem Starten wird noch die Bibliothek freetype in Version 2.4.12 benötigt. Hinweise zur Installation liefert das Armadeus Project Wiki und ein Blog. Gestartet wird anschließend mit ./bin/vsim aus dem Installationsverzeichnis.

Spezifisch zu dem Basisboard gibt es noch folgendes zu sagen:

  1. Das Basisboard muss mit 5V über den entsprechenden Anschluss versorgt werden, sonst wird es nicht über den USB Blaster beim JTAG Scan erkannt. Hierbei liegen die 5V innen an! Es handelt sich um einen 2.1mm/5.5mm Hohlstecker. Update: Die Stromversorgung ist auch über P8 möglich, hier ist der 5V Pin weiter in Richtung Platinenmitte und GND Richtung Rand platziert.
  2. Wichtige Pins sind wie folgt belegt:
    Pin-NummerPin-Funktion
    Pin 3D2 (LED, Output)
    Pin 7D4 (LED, Output)
    Pin 9D5 (LED, Output)
    Pin 17CLK (50 MHz, Input)
    Pin 144Taster (Input)
    Pin 7310uF nach GND, 10K an Vcc
    Pin 26an 1.2V VCC angeschlossen
    Pin 27an GND angeschlossen
    Pin 80an GND angeschlossen
    Pin 81an 1.2V VCC angeschlossen
    Hier ist beim Anschluss von an weiterer Hardware entsprechend Vorsicht geboten.
  3. Der Schaltplan des Basisboards befindet sich u.a. hier:

    Schaltplan des Basisboards (Quelle: http://artofcircuits.com)

Erstes Projekt

Wir starten Quartus II und wählen den “New Project Wizard“. Zunächst wird das Projekt benannt:

Erster Schritt des Wizards

Anschließend kann man bereits existierende Dateien hinzufügen (wir haben allerdings noch keine):

Schritt 2 des Wizards

Die Auswahl des FPGAs (hier die Selektion für den FPGA auf dem Basisboard):

Schritt 3 des Wizards

Einige Informationen über den vorhandenen FPGA werden hier auch aufgezählt:

  • 8256 LEs (Logic Elements) sind die Basisbausteine, im Detail beschrieben auf Seite 2-2 im Cyclone II Architecture Dokument. Jeweils 16 davon werden zu einem LAB (logic array block) zusammengefasst (516 sind vorhanden).
  • 85 User I/Os (Ein/Ausgänge, die für den Entwickler verfügbar sind)
  • 165888 Bit Speicher in 36 M4K Blöcken
  • 36 9×9-Bit Mulitplizierwerke oder alternativ 18 18×18 Multiplizierwerke
  • 2 PLLs
  • 8 globale Takte

Nun hat man ein leere Projekt erzeugt. Mit  “File” und “New” erstellt man eine neue VHDL Datei.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity vhdl_example_1 is
 port( 
  clk: in std_logic;
  led: out std_logic
 );
end vhdl_example_1;
  
architecture bhv of vhdl_example_1 is
 signal count: integer := 1;
 signal tmp: std_logic := '0'; 
begin
 process(clk) begin
  if(clk'event and clk = '1') then
   count <= count + 1;
   if (count = 25000000 ) then
    tmp <= NOT tmp;
    count <= 1;
   end if;
  end if;
  led <= tmp;
 end process;
end bhv;

Diese speichert man unter dem Namen vhdl_example_1.vhd ab. Mit Processing und Start Compilation kann man das Übersetzen starten. Unter Assigments und Pin Planner starten wir die Zuordnung der unter Port definierten Ein-/Ausgänge. Folgende Zuordnung muss vorgenommen werden:

  • clk auf Location PIN 17
  • led auf Location PIN 3
Ausschnitt der konfigurierten Pins

Als letzten Schritt muss der FPGA noch ueber den JTAG Anschluss programmiert werden. Dazu verwendet man den unter Tools den Programmer. Zunächst wählt man unter Hardware Setup den USB-Blaster aus. Als Datei fügt man  output_files/vhdl_example_1.sof hinzu und als Device den FPGA des Basisboards. Anschließend kann man mit Start die Programmierung starten.

Einstellungen im Programmer

Sollte dies nicht (mehr) funktionieren, kann es helfen den USB-Blaster kurz vom USB zu trennen.

Hat alles funktioniert, sollte die LED D2 mit 1Hz blinken:

Update 2. März 2018 zum Thema alternative Stromversorgung.

Update 31. März 2018 zum Thema JTAG einrichten

Brother DCP-9017CDW und Linux

Das alte Faxgerät meines Vater ging leider kaputt und wurde zuletzt eh nur noch als Kopierer verwendet. Als Ersatz wurde ein Brother DCP-9017CDW auserkoren, da dieses Gerät:

  1. ein duplexfähigen Farblaser zur Ausgabe verwendet (trocknet einfach nicht ein),
  2. einen moderaten Anschaffungspreis besitzt,
  3. per WLAN auch mit Linux als Drucker verwendet werden kann und
  4. über ein einfaches Touch Display bedient werden kann.

Kurz um, das Gerät scheint das richtige zu sein, zumal auch eine Funktion “Scan2Email” auf der Funktionsliste steht. Leider sagt das Kleingedruckte “Benötigt Brother-Software” und verweist auf einen optionalen kostenlosen Download für Linux aus dem Brother Solutions Center. Ebenso leider existiert dann kein Download für Linux im Brother Solutions Center (Stand 25.12.2017). Ergo kein offizieller Weg für Scan2Email. Na danke.

Ohne Brother Software kann das Gerät allerdings auf (lokale) FTP-Server scannen. Lokal deshalb, da FTP als unsicher einzustufen ist (Link, Link, …).

Die Idee ist nun: vom Brother DCP-9017CDW wird in ein FTP-Verzeichnis pro Email-Adresse gescannt. Auf dem FTP-Server wird auf eingehende Dateien reagiert und diese per Mail versendet.

Folgende Software wurde ausgewählt:

  • vsftpd als FTP-Server,
  • mpack zum Versand der Dateien als Anhang,
  • exim4 mit Smarthost zum Versand der Mails und
  • incron zum Reagieren auf neue Dateien.

Zunächst erlaubt man dem vsftpd in seiner Konfiguration das Schreiben von Dateien (write_enable=YES) sowie lokale User (local_enable=YES). Somit kann auf dem DCP-9017CDW testweise auf den FTP-Server gescannt werden.

Anschließend exim so einrichten, dass er Mails nach außen versenden kann. Das passiert in diesem Szenario mit einem Smarthost. Dann sollte man testen, ob mpack auch Anhänge versenden kann:

mpack -s SUBJECT /PATH/TO/FILE MAILADRESSE

Kurz danach sollte die Datei als Anhang eintreffen.

Abschließend noch incron konfigurieren, damit auf neue Dateien reagiert werden kann:

  • den Nutzernamen, unter dem per FTP die Dateien abgelegt werden, in der Datei /etc/incron.allow vermerken
  • mit incrontab -e pro Verzeichnis bzw. Email Adresse eine Zeile der Form
    $PFAD IN_CLOSE_WRITE $Script $@/$# $MAIL

    eintragen

Das Script übergibt mpack die Datei und die Mailadresse und löscht die Datei nach dem Versand.

Et voilà, Scan2Mail funktioniert doch.

Urlaub in Südafrika 2017

Mein kleiner Reisebericht mit Bildern zu meinem Urlaub in Südafrika 2017.

Anreise (3.12. – 5.12.)

Eigentlich sollte das ja weniger als 24h zwischen Straßenbahnhaltestelle bis zur Landung in Johannesburg sein, aber der Reihe nach.

Bis zum 1. Boarding in Frankfurt lief alles glatt (Straßenbahn und ICE fuhren pünktlich, Check-In und Sicherheitsgedöns liefen gut), also rein in die Maschine. Direkt hinter mir eine Karlsruherin auf 8 Monatsweltreise.

Leider konnte die Maschine wegen technischer Probleme und einiger “we have to delay by 30 minutes” Ansagen wegen des Nachtflugverbots in Frankfurt nicht mehr starten. Dann eine Ansage, es würden Busse organisiert, wohin war unklar. Am Ende waren wir statt über den Wolken um 1 Uhr früh im Maritim (als einer der letzten bekam ich eine Suite). Allerdings war die Nacht viel zu kurz, die Busse kamen nach dem Frühstück gegen 9 und am Flughafen ging es zum Erneuten Check-In und Sicherheitsgedöns. Leider hoben wir wieder nicht wie geplant ab, da einige Passagiere nicht mehr eingecheckt hatten und so das Gepäck wieder aus der Maschine geholt werden musste. Also Abflug erst nach 15 Uhr Richtung Addis Abeba.

Up in the air

Der Flug dauerte rund 6,5h war dafür sehr ruhig und entspannend. Viele schöne Blicke aus dem Fenster auf die Alpen, den Balkan und Griechenland. Später dann Blicke auf helle Siedlungen in der Wüste und der Anflug auf Addis Abeba zwischen 2 Bergen hindurch war sehenswert.

Addis Abeba bei Nacht

Nach der Landung war unklar, ob direkt weiter geflogen würde oder wieder ein Hotel auf uns wartet. Es war ein Hotel, also raus aus dem Flughafen, ein nach Äthiopien mit Sondervisum auf der Boardkarte (nichts im Pass). Im Hotel um 1 Uhr noch ein Bier und ab ins Bett. Abfahrt zum Flughafen war um 6:40 und nur knapp 4h Schlaf. Es folgt 2 mal das Durchleuchten (Sicherheit wird großgeschrieben) und die Passkontrolle. Boarding war geplant ab 7:40 also alles mit Eile. Leider hakte es auch hier und Boarding war erst 8:30. Aber es ging immerhin (wenn auch mit 24h Verspätung) los nach Johannesburg. Auch dieser Flug war ruhig und relativ ereignislos.

Boing 787-8 der Ethiopian Airlines in Addis Abeba

Nach der Ankunft in Johannesburg die erste Überraschung: der Sommer fiel leicht ins Wasser. Nach Passkontrolle und dem ersten Stempel im Pass die nächste Überraschung: Gepäck weg… Na, das läuft ja super, immerhin mal angekommen. Waren ja nur 24h mehr als geplant.

Regen in O. R. Tambo / Johannesburg
Überflutungen in Johannesburg

Notfallshopping in der Southgate Mall in Johannesburg um wenigstens das Nötigste zu haben. Anschließend die Fahrt nach Potchefstroom in der Provinz Northwest.

Sunset after the rain

Zum Glück zeigte sich das Wetter auch noch von seiner schönen Seite, wie man am Sonnenuntergang gut erkennen kann.

Drakensberge & Golden Gate Highland NP (6.12. – 8.12.)

Am nächsten Tag die südafrikanische SIM-Karte erneut per RICA freischalten lassen, da der erste Versuch nicht erfolgreich war. Anschließend noch ein Paar Hosen und T-Shirt und ab auf den Weg zur Witsieshoek Mountain Lodge gemacht.

Der Weg führte durch den Golden Gate Highland National Park mit landschaftlich sehr schönen Felsformationen.

Panorama aus dem Golden Gate NP
Versteinerung in einem Restroom in der Nähe des Glen Reenen Campsite
Niedrig hängende Wolken (aufgenommen auf knapp 2000m ü. NN)

Weiter ging die Fahrt über Phuthaditjhaba zur Lodge. Diese befindet sich auf ca. 2200m ü. NN und auch hier befanden wir uns zunächst mitten in den Wolken. Das Wasser fiel beim Aufsteigen aus und so war das Wetter sehr ungemütlich und wir zweifelten an unseren Plänen für die Wanderung am nächsten Tag. Das Dinner im Restaurant war Entschädigung genug, landestypisch gab es Filetsteak mit Beilagen und dazu ein Windhoek Lager.

Am nächsten Früh erwiesen sich die Bedenken zum Glück als unbegründet. Zwar schien die Sonne nicht, aber die Wolken hingen höher als am Vortag und nach dem Frühstück sind wir aufgebrochen.

Der Name der Drakensberge (oder auch Drachenberge) ergibt sich aus den Bergen, die aus der Ferne wie die Rückenschuppen eines schlafenden Drachen aussehen. Zusätzlich sieht man viele “Dracheneier” wie dieses:

Ein Ei eines Drachen?

Zunächst begann die Wanderung bergab, da wir uns unterhalb der Wolken

Blick ins Tal
Blick auf die Tiefebene

bewegen wollten. Das hat sich zu 100% ausgezahlt, da wir dadurch ideales Wanderwetter hatten, nicht zu heiß, nicht zu feucht. Es gab hervorragende Aussichten vom Hochplateau in Richtung Tiefebene und in wunderschöne Täler.

Anfang eines ausgewaschenen Überhangs

Auf unserem weiterem Weg begegneten wir einheimischen Tieren und weiteren spektakulären Ansichten. Nach dem wir knapp 400 Höhenmeter abgestiegen waren, mussten wir diese entsprechend zur Lodge wieder aufsteigen. Auf diesen Höhen deutlich anstrengender, da die Luft hier bereits spürbar dünner ist, als auf den gewohnten knapp 200m ü. NN. Aber da mussten wir durch.

Krabbe im Wasser
Tausendfüßler

Am Nachmittag klarten die Wolken auf und ermöglichten einen Blick auf die Kulisse des Amphitheaters auf:

Blick aufs Amphitheater

Am 2. Tag erreichte uns die Nachricht, mein verlorenes Gepäck sei auf dem Weg nach Potchefstroom. Nach einem ausgiebigen Frühstück sind wir mit dem Auto zum Sentinel Car Park gefahren um dort noch eine kleine Wanderung zu machen. Hier gab es erneut geniale Aussichten, interessante Wolken und Tiere.

Blick auf den Parkplatz am Sentinel
Eine von vielen
Tief gehts hinab

Kurz vor der Abfahrt an der Lodge konnten wir noch einen Blick auf die von der Sonne beschienenen Felsen der Amphitheaters werfen:

Amphitheater in der Sonne

Auf dem Rückweg nach Potchefstroom haben wir beim Tanken in Clarens angehalten und von einer Maklerin noch ein paar Tipps für eine weiter kleine Runde bekommen. Auch hier wieder “wilde” Tiere und Felsformationen, aber seht selbst.

Überhang
Felsformationen
Flußkrebs
Dorfstraße

Der weitere Heimweg über die landesüblichen Dirt Roads mit kleinen Schlaglöchern mit Wasserfüllung hat uns dann noch an einem kleinen Sandsturm vorbeigeführt.

Im Golden Pond Guest Hause angekommen, stellt sich raus, dass das Gepäck nach der Landung in Johannesburg zunächst einen Umweg über Kapstadt eingelegt hat.

Pilanesberg Nationalpark (10.12.)

Nach einem Tag Pause in Potchefstroom ging es am 10. Dezember in den Pilansberge Nationpark. Da die Tiere die Mittagszeit normalerweise im Schatten der Büsche verbringen, ist es wichtig möglichst direkt nach Sonnenaufgang oder zumindest sehr früh durch die Gates des Nationalpark zu fahren. Wir sind deshalb kurz nach 5 Uhr los gefahren und waren ca. 7:30 im Nationalpark. Was man nicht vergessen sollte ist ein gutes Fernglas und eine gute Kamera.

Pilanesberg
Karte des Nationalparks (von https://www.pilanesbergnationalpark.org/de/map/)

Ganz wichtiges Schild kurz nach der Fahrt in den Nationalpark. Diesem ist definitiv zu folgen, da die Tiere hier frei laufend und nicht gezähmt sind. Sie sind höchstens tolerant gegenüber Fahrzeugen.

Warnschild

An einigen Stellen sind Hütten (Look outs und Hides) errichtet worden, dort ist das Aussteigen explizit erlaubt.

Blick ins Tal

Von den “Big Five” haben wir nicht alle erwischt, aber das ist auch relativ unwahrscheinlich. Gesehen und auch photographiert haben wir Nashörner und Elefanten sowie Löwen. Diese findet man auf den folgenden Bildern. Interessanterweise verzieht sich der König der Tiere sicherheitshalber wenn ein grasendes Nashorn auftaucht.

Löwe direkt neben dem Fahrweg
Nashörner und Elefanten
Nashorn
Elefante mit Jungtier

Am Mankwe Damm konnten wir neben einigen Vögeln auch noch Flusspferde (leider zu weit weg für die Kamera), viele Schildkröten und ein Babzkrokodil:

Schildkröte und Krokodil

Auf den weiteren Wegen durch den Park sahen wir noch eine Zebraherde mit Jungtieren und auch Giraffen, Impalas, Wasserböcke, Warzenschweine sowie viele weitere Tierarten.

Zebras
Giraffe
Eule
Impala
Warzenschwein

Ein Besuch in einem Nationalpark ist definitiv sehens- und empfehlenswert!

Erholungstag (11.12)

Nachdem wir erst kurz vor Mitternacht wieder in Potchefstroom waren, haben wir den Montag sehr ruhig verbracht. Unter anderem nochmals die NWU besucht, den Mietwagen aufgeräumt. Falls jemand in Potchefstroom ein Guest House sucht, so kann ich den Golden Pond empfehlen.

Rückflug (12.12-13.12)

Den Rückflug von Johannesburg nach Frankfurt möchte ich deshalb erwähnen, da er absolut problemlos war. Also ein schöner Kontrast zum Hinflug, der ja doch recht nerven aufreibend war.

Update 25.12.2017:
Alle Links auf https umgestellt.