Forum: Mikrocontroller und Digitale Elektronik Scriptengine für zrtos


von Matthias (ahamatta)


Lesenswert?

Das hat sicher schon einer gemacht...

Also, mir hat Java und WebAssembly nicht so gefallen und da dachte ich 
mir, ich mache nur eine VM und irgendwann ein LLVM Plugin.

Kann mir bitte einer sagen, ob das jetzt gleich in den Abfall kann? Sind 
halt entwurfstechnisch zwei Byte pro Instruktion 💩

https://github.com/ykat-UG-haftungsbeschrankt/agilertos/blob/main/zrtos_script.h

von Christoph M. (mchris)


Lesenswert?

404 page not found.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Dein Code enthält Bezeichner wie "zrtos_clist__each", also mit zwei 
Unterstrichen in der Mitte. In C ist das erlaubt, in C++ aber nicht 
(reserviert für die Implementation). Sollte es also entfernt die 
Möglichkeit geben, dass man den Code in C++ einbindet, müsstest du das 
ändern.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Christoph M. schrieb:
> 404 page not found.

Ihm hat bestimmt die Patentanmeldung, vor der Veröffentlichung, 
vergessen.

von Daniel A. (daniel-a)


Lesenswert?

Sieht so aus, als ob einfach die Datei umbenannt wurde.

von Matthias (ahamatta)


Lesenswert?

Daniel A. schrieb:
> Sieht so aus, als ob einfach die Datei umbenannt wurde.

Ja, hab die Datei umbenannt, da es doch eher eine VM als ein Script 
wurde.

https://github.com/ykat-UG-haftungsbeschrankt/agilertos/blob/main/zrtos_vm.h

von Matthias (ahamatta)


Lesenswert?

Niklas G. schrieb:
> Dein Code enthält Bezeichner wie "zrtos_clist__each", also mit zwei
> Unterstrichen in der Mitte. In C ist das erlaubt, in C++ aber nicht
> (reserviert für die Implementation). Sollte es also entfernt die
> Möglichkeit geben, dass man den Code in C++ einbindet, müsstest du das
> ändern.

Danke, das wusste ich nicht! Muss mal nachlesen, ob das auch in einem 
extern "C" kollidieren kann...

Man kann das schon alles in zrtosClist_each ändern, aber da sehe ich 
nach einer durchgezechten Nacht nur noch Buchstabensalat.

_ am Anfang und _t am Ende ist eigentlich auch reserviert. Ist halt eine 
schlechte Angewohnheit von mir. 🥺

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Matthias schrieb:
> Danke, das wusste ich nicht! Muss mal nachlesen, ob das auch in einem
> extern "C" kollidieren kann...

Ja, in extern "C" kommt ja kein C rein, sondern C++. Also gelten da auch 
die C++ Regeln.

Beitrag #7673005 wurde vom Autor gelöscht.
von Matthias (ahamatta)



Lesenswert?

Niklas G. schrieb:
> Matthias schrieb:
>> Danke, das wusste ich nicht! Muss mal nachlesen, ob das auch in einem
>> extern "C" kollidieren kann...
>
> Ja, in extern "C" kommt ja kein C rein, sondern C++. Also gelten da auch
> die C++ Regeln.

Hast Recht.

Scheinbar verwenden aber die C++ Compiler intern ^_[A-Z] für die 
identifier damit das nicht mit den alten C Quelltexten kollidiert.

Man müsste aus dem Schneider sein, wenn man auf ^__* und ^_[A-Z] 
verzichtet.

Da muss ich tatsächlich nacharbeiten.

Wenn das einer kommerziell einsetzen will und sich an den __ stört und 
auf Nummer sicher gehen will, kann ich das schon in paar Tagen 
umschreiben 😇

von Daniel A. (daniel-a)


Lesenswert?

Matthias schrieb:
> Wenn das einer kommerziell einsetzen will

LOL, als ob das überhaupt jemand einsetzen will.
Open Source (nach OSI) sowie Freie Software Nutzer werden es meiden, 
weil nicht Open Source / Freie Software. Und kommerzielle dürfen es 
nicht einsetzen, müssten also erst mit dir verhandeln. Gleichzeitig 
können die das auch selber, und es gibt auch schon längst fertige & weit 
verbreitete RTOS, die sogar Open Source sind, auch mit Support Angeboten 
usw.
Die einzigen die das Nutzen werden Microsoft sein um ihr CoPilot zu 
trainieren.

von Daniel A. (daniel-a)


Lesenswert?

Matthias schrieb:
> Also, mir hat Java und WebAssembly nicht so gefallen und da dachte ich
> mir, ich mache nur eine VM und irgendwann ein LLVM Plugin.

Also, du machst dir eine VM, die deinen eigenen Bytecode ausführt. Kein 
statischer Recompiler wie bei WASM möglich, und nicht einmal als JIT 
umgesetzt. Und du willst später mit LLVM code dafür generieren, den du 
dank LLVM auch gleich für deine native Plattform hättest generieren 
lassen können?
Was genau soll das bringen?

Naja, zumindest eine gute Übung um Erfahrung zu sammeln ist es.

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Daniel A. schrieb:
> LOL, als ob das überhaupt jemand einsetzen will.

Tja, er hat in ziemlich kurzer Zeit einen relativ vollständigen 
grundlegenden Scheduler geschrieben. Das ist von Kompetenz und 
Produktivität her schon ziemlich gut. Allerdings halt für AVR - der 
Markt für RTOSe für AVR dürfte ziemlich klein sein. Der für 
Bytecode-Interpreter für AVR noch kleiner. Aber es gibt sogar Leute die 
für Basic-Compiler Geld ausgeben, also wer weiß.

Der gezeigte Bytecode ist allerdings ziemlich minimalistisch, ob man 
damit wirklich eine geringere Codegröße als mit AVR-Opcodes oder auch 
ARM (Thumb) hinbekommt? Dazu bräuchte man direkte Integration von 
High-Level-Operationen, z.B. String-Operationen, direkten Zugriff auf 
Klassenmember/Funktionen ähnlich wie JVM, weil dieses Geschnippsel auf 
Maschinencode-Ebene schon einigen Platz wegnimmt.

Mit etwas mehr Gespür dafür, was der Markt braucht, kann das schon eher 
was werden. Wie wärs mit Unterstützung RISC-V? Oder Xtensa (ESP32)? 
Fokus auf IoT und Low-Power (tickless)? Direkte Integration von 
Internetprotokollen? Das ist kommerziell eher interessant...

Warum ist eigentlich alles in Header-Files, selbst die main()-Funktion 
in den examples?

: Bearbeitet durch User
von Matthias (ahamatta)


Lesenswert?

Könnten schon, __ ist in C++ verboten, weil das intern vom Compiler 
verwendet werden kann.

Angenommen man schreibt:
1
test.a__b = test__a__b
2
test__a.b = test__a__a

Dann hat man in C++ einen Namenskonflikt.

Der Namenskonflikt mit den alten C Quelltexten wird sehr sehr sicher 
unabhängig davon durch die Nutzung des Namensraum _[A-Z0-9]+test__a__b 
ausgeschlossen.

Ich habe das korrigiert, müsste jetzt passen.

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Matthias schrieb:
> weil das intern vom Compiler
> verwendet werden kann.

Eher von der Standardbibliothek.

Matthias schrieb:
> Dann hat man in C++ einen Namenskonflikt.

Wahrscheinlich nicht. Moderne Compiler können prinzipiell beliebig lange 
und beliebig aufgebaute Bezeichner verwenden (kein Limit auf 30 Zeichen 
o.ä.). Die Tücke ist, solche Dinge funktionieren in 95% der Fälle 
problemlos. Aber dann kommt in der nächsten Version des Compilers oder 
der Standard-Bibliothek ein reservierter Bezeichner in dieser Form dazu, 
und dann kompiliert der eigene Code nicht mehr (richtig). Die doppelten 
Unterstriche innerhalb eines Bezeichners sind vermutlich verboten damit 
implementationsspezifische Makros Bezeichner ohne Kollision 
zusammenbauen können (offsetof oder so?).

Matthias schrieb:
> Ich habe das korrigiert, müsste jetzt passen.

Du hast immer noch doppelte Unterstriche... Der Name 
"ZRTOS_ASSERT__STATIC" ist reserviert

von Matthias (ahamatta)


Lesenswert?

Niklas G. schrieb:
> Matthias schrieb:
>> weil das intern vom Compiler
>> verwendet werden kann.
>
> Eher von der Standardbibliothek.
>
> Matthias schrieb:
>> Dann hat man in C++ einen Namenskonflikt.
>
> Wahrscheinlich nicht. Moderne Compiler können prinzipiell beliebig lange
> und beliebig aufgebaute Bezeichner verwenden (kein Limit auf 30 Zeichen
> o.ä.). Die Tücke ist, solche Dinge funktionieren in 95% der Fälle
> problemlos. Aber dann kommt in der nächsten Version des Compilers oder
> der Standard-Bibliothek ein reservierter Bezeichner in dieser Form dazu,
> und dann kompiliert der eigene Code nicht mehr (richtig). Die doppelten
> Unterstriche innerhalb eines Bezeichners sind vermutlich verboten damit
> implementationsspezifische Makros Bezeichner ohne Kollision
> zusammenbauen können (offsetof oder so?).
>
> Matthias schrieb:
>> Ich habe das korrigiert, müsste jetzt passen.
>
> Du hast immer noch doppelte Unterstriche... Der Name
> "ZRTOS_ASSERT__STATIC" ist reserviert
So natürlich...
1
test.a__b = test__a__b
2
test__a.b = test__a__b

Ja, kann sein. Aber C++ gibt es schon ewig und man hat da nicht alles 
neu geschrieben, sondern nur Klassen um C gebaut. Trotzdem ist da nie 
was eingestürzt.

Auch gibt es keinen C++ Standard für C Programmierer. Die können sich 
freiwillig, oder wenn vom Auftraggeber gefordert, an C++ 
Namenskonventionen halten, müssen das aber eigentlich nicht.

Sry, ich muss meine Jalousien montieren. Mache da später wieder weiter!

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Matthias schrieb:
> So natürlich...

Ist trotzdem wahrscheinlich unproblematisch... Bis der Compiler 
"test__a__b" als reservierten Bezeichner einführt.

Matthias schrieb:
> Aber C++ gibt es schon ewig und man hat da nicht alles
> neu geschrieben, sondern nur Klassen um C gebaut.

Naja, viel C-Code ist extra so geschrieben dass er auch mit C++ 
funktioniert. Ich habe gesehen du hast ja auch extra das "this"-Keyword 
vermieden.

Matthias schrieb:
> Trotzdem ist da nie
> was eingestürzt.

"Citation Needed". Der Linux-Kernel kann z.B. überhaupt nicht als C++ 
kompiliert werden.

Matthias schrieb:
> müssen das aber eigentlich nicht.

Es ist aber clever für Aufwärtskompatibilität. Besonders wenn man es 
verkaufen möchte... Du kannst auch den RTOS-Code in C++ schreiben, das 
funktioniert wunderbar, und erspart Arbeit.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Niklas G. schrieb:
> Dein Code enthält Bezeichner wie "zrtos_clist__each", also mit zwei
> Unterstrichen in der Mitte. In C ist das erlaubt, in C++ aber nicht
> (reserviert für die Implementation.

Hast du da einen Link, dass alle Bezeichner mit __ irgendwo im Namen  im 
Namespace der C++ Implementation sind?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Hast du da einen Link, dass alle Bezeichner mit __ irgendwo im Namen  im
> Namespace der C++ Implementation sind?

https://en.cppreference.com/w/cpp/language/identifiers

> An identifier can be used to name objects, [...], and other entities, with the 
following exceptions: [...]
> * Identifiers [...] of one of the following forms are reserved:
>   * identifiers with a double underscore anywhere;
>   * identifiers that begin with an underscore followed by an uppercase letter;
> in the global namespace, identifiers that begin with an underscore.

> If the programmer uses such identifiers, the program is ill-formed, no 
diagnostic required.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ok, danke. Bezieht sich das auch auf Macros? Dann gehörten auch Macros 
beginnend mit nur einem _ zur Implementation.

von Daniel A. (daniel-a)


Lesenswert?

Noch eine Anregung zur Config und den Includes.

Ich packe bei mir die Includes gerne in ein Unterverzeichnis:
1
include/vendorprefix/someheader.h

Dann kann man das include Directory beim Kompilieren angeben:
1
cc -Iinclude/ somefile.c

Dann kann man in somefile.c die Includes so handhaben:
1
#include <vendorprefix/someheader.h>

Das ganze ist auch beim Installieren der headers nützlich. Unter Linux 
z.B. kopiert man einfach `include/vendorprefix/.` nach 
`/usr/include/vendorprefix/` oder `/usr/local/include/vendorprefix/`, 
und das Include oben geht auch einfach per `cc somefile.c`, also ganz 
ohne das -I.


Bei den Configs mache ich es oft so, dass ich in jeder Headerdatei 
zuallererst die eine config.h einbinde.

In der habe ich in der Regel sowas in der Art:
1
#ifndef VENDOR_PROJECT_CONFIG_H
2
#define VENDOR_PROJECT_CONFIG_H
3
4
// Where is the config? Has it been specified? Otherwise, can we search for it?
5
6
#if !defined(CONFIG_FILE) && defined(__has_include)
7
// Note: The following line mustn't be merged with the previous one
8
#if __has_include(<config.h>)
9
#define CONFIG_FILE <config.h>
10
#endif
11
#endif
12
13
// Include the config
14
15
#ifdef CONFIG_FILE
16
#include CONFIG_FILE
17
#endif
18
19
// Defaults
20
21
#ifndef SOME_OPTION
22
#define SOME_OPTION default value
23
#endif
24
25
#endif

__has_include gibt es in C++, und in C seit C23 (wobei C23 noch noch 
weit supportet ist, aber GCC und clang kannten es schon vorher als 
extension).
Wenn der Compiler es unterstützt, kann man dann einfach eine config.h in 
seinen include/ Ordner legen. Falls nicht, kann man es explizit mit `-D` 
setzen, z.B. `cc -D'CONFIG_FILE="/absolute/path/to/config.h"' myfile.c` 
oder `cc -I include/ -D'CONFIG_FILE=<config.h>' myfile.c`.

von Daniel A. (daniel-a)


Lesenswert?

Hmm 
https://github.com/ykat-UG-haftungsbeschrankt/agilertos/commits/main/ In 
die Commit Logs sollte man schon was reinschreiben. Die sind wichtig, 
wenn man später mal was suchen will.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Ok, danke. Bezieht sich das auch auf Macros?

Ich denke schon:

https://timsong-cpp.github.io/cppwp/n4950/lex.name#:character,underscore,in_identifier

> In addition, some identifiers appearing as a token or preprocessing-token are 
reserved for use by C++ implementations

Weil es auch im preprocessing tokens geht, gilt das wohl auch für 
Makros. Macht auch Sinn, denn Makros mit reservierten Namen können auch 
fies mit Bezeichnern in der Standardbibliothek kollidieren.

von Matthias (ahamatta)


Lesenswert?

Niklas G. schrieb:
> Es ist aber clever für Aufwärtskompatibilität. Besonders wenn man es
> verkaufen möchte... Du kannst auch den RTOS-Code in C++ schreiben, das
> funktioniert wunderbar, und erspart Arbeit.

Ich mache es erst mal fertig und dann muss das eh in die Arduino IDE und 
mit dem C++ harmonieren.

Müsste eigentlich eine Kleinigkeit sein, die __ zu entfernen, da fast 
alles mit zrtos_ anfängt.

Das Problem war, dass ich ohne Exception nicht aus dem Konstruktor raus 
komme und dann hab ich das bleiben lassen.

Klar, wenn alles Singleton sind bzw. bei der Initialisierung kein Fehler 
auftreten kann ist es wurscht....

von Matthias (ahamatta)


Lesenswert?

Kennt sich einer mit den LLVM-Backend aus? Ich habe mich daran versucht, 
aber das ganze Teil zu compilieren um da ein Backendplugin einzubauen 
dauert fast einen halben Tag??

Also, wollte ich einfach das LLVM IR übersetzen. Geht das so auch oder 
ist das dann so kompliziert, dass man doch lieber das als Backend 
implementiert?

Leider habe ich keine Zeit mehr, weil die Bilanz und Steuererklärung 
unbedingt fertig werden muss.

Hat da einer Lust drauf? Ist auch C++...
1
#include <string>
2
#include <iostream>
3
4
5
//#include <llvm/ADT/OwningPtr.h>
6
#include <llvm/Bitcode/BitcodeReader.h>
7
#include <llvm/IR/LLVMContext.h>
8
#include <llvm/IR/Module.h>
9
#include <llvm/Support/FileSystem.h>
10
#include <llvm/Support/MemoryBuffer.h>
11
#include <llvm/Support/ManagedStatic.h>
12
#include <llvm/Support/raw_ostream.h>
13
//#include <llvm/Support/system_error.h>
14
#include <llvm/Support/TargetSelect.h>
15
16
using namespace llvm;
17
18
int main()
19
{
20
//    llvm::InitializeNativeTarget();
21
22
    // read byte-code from file
23
    auto Buffer = llvm::MemoryBuffer::getFile("./test.bc");
24
    if (Buffer.getError()){
25
        llvm::errs() << "test.bc not found\n";
26
        return -1;
27
    }
28
  auto MemoryBuffer = Buffer.get().get();
29
    // generate corresponding LLVM module
30
    llvm::LLVMContext Context;
31
    std::string ErrorMessage;
32
    auto Module = llvm::parseBitcodeFile(*MemoryBuffer, Context);
33
    if (! Module)
34
    {
35
        llvm::errs() << ErrorMessage << "\n";
36
        return -1;
37
    }
38
  
39
    // create JIT execution engine and setup JIT, no function is complied yet
40
    //llvm::OwningPtr<llvm::ExecutionEngine> EE(llvm::EngineBuilder(M).create());
41
42
    // retrieve the Function IR object that represents sum
43
    llvm::Function* SumFn = Module.get()->getFunction("main");
44
  std::cout << SumFn;
45
  
46
47
  for(auto &Global : Module->get()->getGlobalList()){
48
    std::cout << Global.getName().data();
49
  }
50
51
  for(auto &Function : Module->get()->getFunctionList()){
52
    std::cout << Function.getName().data();
53
    for(auto &Args : Function.args()){
54
      std::cout << Args.getName().data();
55
      //std::cout << Args.getType().;
56
    }
57
  }
58
/*
59
    // trigger JIT compilation
60
    int(*Sum)(int, int) = (int(*)(int, int))EE->getPointerToFunction(SumFn);
61
62
    // call the original sum function via the JIT-compiled function
63
    int res = Sum(4, 5);
64
    llvm::outs() << "Sum result: " << res << "\n";
65
66
    // release the execution engine allocated memory that holds the function code
67
    EE->freeMachineCodeForFunction(SumFn);
68
    llvm::llvm_shutdown();
69
*/
70
    return 0;
71
}

Btw. nicht wundern, wenn beim AgileRTOS bzw zRTOS nichts mehr vorwärts 
geht. Mache bestimmt irgendwann weiter, gerade habe ich einfach nur 
keine Zeit dafür.

Ist halt scheiße, wenn man alleine über zwei Fahrräder schieben muss...

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.