• Noser.com
facebook
linkedin
twitter
youtube
  • NOSERmobile
    • Android
    • HTML 5
    • Hybrid Apps
    • iOS
    • Windows Phone
  • NOSERembedded
    • Medizintechnik
  • NOSERprojektmanagement
  • NOSERtesting
  • NOSERlifecycle
    • .NET Allgemein
    • Application Lifecylce Management
    • Apps
    • Architektur
    • ASP.NET
    • Azure
    • Cleancode
    • Cloud
    • Silverlight
    • Visual Studio / Team Foundation Server
    • Windows 8
    • Windows Presentation Foundation
  • NOSERinnovation
    • Big Data
    • Cloud
    • IoT
    • Operations Research
    • Augmented Reality
    • RFID, NFC, Bluetooth LE

Virtual pty/tty uart listener: Pitfalls on linux socat

02. März 2023
Sandro Klarer
0

As a hardware and embedded engineer you come across of a lot of good and bad tools (hardware and software). One of our team’s nifty tools is a tty uart listener and protocol decoder. It is basically two FTDI UARTs that connect there RX to any signal on the UART of interest. Nothing fancy, but together with our Python script for decoding all the messages, this tool is very helpful for real time logging/debugging. It looks like this:

tty uart listener HW setup

This tool works fine. Alternatively, we could use a logic analyser and implement a protocol decoder. A sales logic analyser, for example, would support this. But now we have a new challenge: A virtual serial connection to a maintenance tool on a computer. The maintenance tool is developed by a different department, but the serial protocol is the same. So for debugging purposes it would be great to use our Sniffer SW tool as it is. The approach is to create two virtual serial tty UART listeners on my Linux machine. This should look like this:

tty uart listener

tty uart listener virtual setup

Ok, creating virtual tty (pty) and redirecting them sounds like what socat is made for that. Lets give it a try.

UDP try

UDP seems to be the first choice as the UART packets are connectionless like UDP. However, this approach did not work.

               Port xx16    Portxx17
Virtual_A  =><==( o===========o )===== Virtual_B
           


socat commands:

sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVA00,nonblock UDP-LISTEN:11316,reuseaddr,fork
sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVB00,nonblock UDP-LISTEN:11317,reuseaddr,fork
sudo socat -d -d UDP:localhost:11316 UDP:localhost:11317

The listener connects only after receiving data. As both listeners are not receiving data, the connection is never established → try TCP

sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVA00,nonblock TCP-LISTEN:11316,reuseaddr,fork
sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVB00,nonblock TCP-LISTEN:11317,reuseaddr,fork
sudo socat -d -d TCP:localhost:11316 TCP:localhost:11317

OK, the TCP approach works.

sudo on the virtual tty

It’s a bit tedious to always use sudo prevelage to connect to the virtual port.

This post helps:  https://unix.stackexchange.com/questions/374916/how-to-use-virtual-serial-port-without-root-privileges

sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVA00,nonblock,group-late=dialout,mode=660 xxxx

Duplicate an UART stream

So, I want to duplicate a data stream. One stream as the normal data flow and the other to feed our debug tool :

           Port xx16    Portxx17
Virtual_ttyVA00 ----( o-->----o )----- Virtual_ttyVB00
                      o
                       \     Portxx18
                        ---->--o )---- Virtual_ttyVC00

And these are the socat commands for it:

sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVA00,nonblock,group-late=dialout,mode=660 TCP-LISTEN:11316,reuseaddr,fork
sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVB00,nonblock,group-late=dialout,mode=660 TCP-LISTEN:11317,reuseaddr,fork
sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVC00,nonblock,group-late=dialout,mode=660 TCP-LISTEN:11318,reuseaddr,fork
sudo socat -u TCP:localhost:11316 - | tee >(socat - UDP:localhost:11317) >(socat - UDP:localhost:11318) > /dev/null

It works fine. I can connect to my three UART ports and send and receive both streams. Great, I think I’m done. Just need to put it all together.

 

The missing functionality in TCP

After hours of trying to set this up, I have finally isolated the missing piece of why it does not work. It’s not possible to split it into two paths.

          Port xx16            Portxx17
Virtual_A  ----( o------>---------o )----- Virtual_B
                  o               o
                   \             /    
                    -----<-------

 

And these are the socat commands:

sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVA00,nonblock,group-late=dialout,mode=660 TCP-LISTEN:11316,reuseaddr,fork
sudo socat -d -d PTY,raw,echo=0,link=/dev/ttyVB00,nonblock,group-late=dialout,mode=660 TCP-LISTEN:11317,reuseaddr,fork

sudo socat -u TCP:localhost:11316 TCP:localhost:11317 
sudo socat -U TCP:localhost:11316 TCP:localhost:11317

One path works, but when you try to send on the other path, it tries to send on the read connection and fails.

 

Using the socat -x option

Finally, I tried the -x option. So I got all the traffic streamed to stderr. I used tee to duplicate my stream (line 2) and separated the two streams with sed (lines 3 and 4). It took me a while to figure out why xxd (which converts hex output to binary output) was not outputting anything, so I had to add stdbuf -o0 to make sure there was no buffer.

sudo socat -x PTY,raw,echo=0,link=/dev/ttyVA00,nonblock,group-late=dialout,mode=660 PTY,raw,echo=0,link=/dev/ttyVB00,nonblock,group-late=dialout,mode=660 2> \
(tee \
(sed -u -n '/>/{n;p;}' > >(stdbuf -o0 xxd -r -p > >(sudo socat - PTY,raw,echo=0,link=/dev/ttyVC00,nonblock,group-late=dialout,mode=660))) \
(sed -u -n '/</{n;p;}' > >(stdbuf -o0 xxd -r -p > >(sudo socat - PTY,raw,echo=0,link=/dev/ttyVD00,nonblock,group-late=dialout,mode=660)))

Solved, finally.

socat help: http://rpm.pbone.net/manpage_idpl_25675711_numer_1_nazwa_socat.html

SmartConnector: Low Power Anbindung im IoT Umfeld (VLLS3 Restore auf einem ARM Cortex KW40Z)

02. Dezember 2015
Sandro Klarer
0
Bluetooth, Cortex, freescale, IoT, Kinetis, KW40Z, M0+, SmartConnector

Für ein Projekt im Maschinenumfeld sollen mehrere IoT-Devices mit Bluetooth Anbindung eingesetzt werden. Als Anforderung steht ein Strombedarf von einigen uA. Der verwendete Mikrocontroller MKW40Z (mit Bluetooth) bietet hierfür den speziellen Betriebsmode  VLLS3 (Very Low Leakage Stop Mode) an. Dieser Mode schaltet dabei alle Peripherie Module und auch den Core aus. Einzig das RAM bleibt erhalten. Nach dem Aufwachen aus dem VLLS3  wird das Programm fortgeführt. Das Aufwachen erfolgt über den RTC. Die Anwendung läuft von einer Primärzelle und soll als weitere Anforderung eine Laufzeit von mehr als einem Jahr erreichen.

Low Power Berechnungen

Die Werte des Datenblattes für den VLLS3 Mode ergeben folgende Werte: (Der MKW40Z wird im DC/DC Buck mode betrieben)

Tabelle
Es wird somit ein Strom von 2.06 uA erwartet.
Umrechnung von Strom:-
3V auf 2.5V : Ix * 3V/2.5V
1.8V auf 2.5V: Ix * (1.8V /2.5V) *(1/n)

SW

Das Kinetis KSDK_1.3.0 Demoprogramm power_manager_hal_demo von Freescale liefert einen einfachen Einstieg in die VLLS3 Thematik. Das Demoprogramm tritt in den VLLS3 State ein, unglücklicherweise erfolgt jedoch das Aufwachen über die normale Reset Abfolge. Das heisst: Initialisieren von RAM, Stack Pointer SP, Variablen, etc. Dieses Verhalten ist alles andere als gewünscht, da der erhaltene RAM Speicher gar nicht genutzt wird und dadurch Zeit und Energie verloren geht.

Fluss_Demo

Bild 1: Programm flow in power_manager_hal_demo für VLLS3 mit RTC wakeup

Der gewünscht Programmablauf wäre jedoch:

Fluss_Soll

Bild 2: Gewünschter Programm flow mit VLLS3

Aus dem Datenblatt kann entnommen werden, dass beim einem Aufwachen aus dem VLLS3 Mode das Bit RCM_SRS[WAKEUP] gesetzt ist. Mit folgenden Schritten lässt sich das gewünschte Verhalten erreichen:

Vor dem VLLS3 Mode:

  • Speichern der CPU Register auf dem Stack
  • PC+XX (PC des weiterführenden des Programms) auf dem Stack speichern
  • Stack Pointer absolut in RAM speichern

Nach dem Aufwachen:

  • Unterscheidung ob POR Reset oder ein Wakeup
  • SP aus absoluter RAM Adresse lesen
  • PC zurückladen und setzen
  • Register zurückladen
  • HW neu initialisieren

Konkret sieht der Programmfluss nun so aus:

BildIst

Bild 3: Konkret Programmfluss mit VLLS3

Strommessung

Um die ca. 2 uA mit +/- 5 % Genauigkeit zu messen, wird auf folgende Schaltung zurückgegriffen:

Schema

Bild 4: Messschaltung

Somit entspricht 0.1 V gemesse Spannung einem Strom von 1 uA. Der Messbereich wird von der Diode begrenzt, was bei einer BAV99L maximal 0.4 V sind. Durch die Diode fliesst der Strom nur, wenn der uC im Run Mode läuft.

Messung:

VBattery = 2.5 V

Gemessene Spannung Vpeak: 267mV, Vlow: 138mV ->Vmittel: 202mV -> I = 2 uA, was genau den Erwartungen entspricht.

 

058

Bild 4: Strom KO Plot, bei einem VLLS3 Wakeup Intervall von 10 s

Fazit

Der VLLS3 Mode ist für Low Power Designs unverzichtbar. Da der Core abgeschaltet wird, ist das “Restoren” etwas aufwendiger. Es sind einige Zeilen Assembler Anweisungen für die Wiederinitialisierung zu schreiben.

Unglücklicherweise ist nach dem VLLS3 Mode das Debugging nicht immer möglich.

Unter IAR und mit JLink ist es möglich, wenn im unter settings\*.jlink folgenede anweisung hinzugefügt wird:

[CPU]
LowPowerHandlingMode = 1

Bemerkung

Achtung: Über Pullup Widerstände von Vbat(3V) auf Vcc (1.8V) kann ein Strom über die interne Schutzdiode fliessen. Dieser Strom verhindert ein Regeln von Vcc(1.8V) und Vcc(1.4V) und damit ist ein ordnungsgemässes Rückkehren aus dem VLLS3 Mode nicht mehr garantiert.

 

Tag Cloud

.NET android Angular AngularJs app Arduino ASP.Net automated testing Azure Big Data C# C++ Cloud continuous integration Elm Embedded gRPC Internet of Things IoT Java Javascript M2M OWASP Projektmanagement protobuf Python Raspberry Pi Reactive Programming REST Scrum Security Softwarequalität SPA Testen testing Testmanagement Teststrategie Visual Studio WebAPI windows WPF Xamarin Xamarin.Android Xamarin.Forms Xamarin.iOS

Archive

Current Posts

  • Virtual pty/tty uart listener: Pitfalls on linux socat
  • Akzente setzen mit der Android Splash Screen API unter .NET MAUI
  • Do You have Your Personal Space?
  • Automated provisioning with ARM Templates
  • Asynchrone Beobachtungen und Versprechungen in Angular

Last Comments

  • Hans Reinsch bei Der Safety-Plan: Die wichtigsten Antworten mit Checkliste
  • George H. Barbehenn bei Modeling Optocouplers with Spice
  • Noser Blog Touch-Actions in Xamarin.Forms - Noser Blog bei Mach mehr aus Animationen in Xamarin.Forms mit SkiaSharp
  • Noser Blog Focus on the Secure Storage service of Trusted Firmware (TFM) - Noser Blog bei First run of the Trusted Firmware (TFM) application
  • Noser Blog First run of the Trusted Firmware (TFM) application - Noser Blog bei Focus on the Secure Storage service of Trusted Firmware (TFM)

Popular Posts

Xamarin.Android Code Obfuscation

6 Comments

ManuScripts: Wenn jemand eine Reise tut... Funktionale Programmierung mit Elm - Teil 1 - Aufbruch

5 Comments

ManuScripts: Wenn jemand eine Reise tut... Funktionale Programmierung mit Elm - Teil 2 - Kein Picknick

4 Comments

Contact us

  1. Name *
    * Please enter your name
  2. Email *
    * Please enter a valid email address
  3. Message *
    * Please enter message
© 2013 NOSER ENGINEERING AG. All rights reserved. Datenschutz | Cookie-Richtlinie