Ankündigung

Einklappen
Keine Ankündigung bisher.

ESP8266 KNX mit ETS

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • thesing
    antwortet
    Hallo Waldemar,

    der Code von Bernhard wird nicht einfach so übernommen, sondern extra eingearbeitet. Im ersten Schritt wird geändert, dass die ganzen TableObjects ihre Daten im nicht nochmal puffern, sondern die Daten direkt aus dem Flash bzw. aus dem Flashbuffer nutzen. Dabei wird erst mal das alte Interface zur Platform (getEepromBuffer()) genutzt. Einen Buffer im Ram in der Größe eines Eraseblocks (also die Größe die man im Flash auf einmal löschen muss. Das heißt je nach MCU mal Sector, oder Block, oder sonstwie.) braucht man eh. Die Eeprom-Emulationen nehmen davon aktuell (höchstwahrscheinlich) genau einen.
    Im nächsten Schritt wird dann die Memory-Klasse so erweitert, dass sie mit Eraseblocks und Flashpages usw. klar kommt. Das ist bei Bernhards Lösung alles in der SamdFlash-Klasse drin. Ich möchte das einmal im Stack drin haben, damit man das nicht für jede Platform neu implementieren muss. Dann gibt es in der Platform etwa:

    Code:
    virtual size_t flashEraseBlockSize(); // in pages
    virtual size_t flashPageSize();       // in bytes
    virtual uint8_t* userFlashStart();   // start of user flash aligned to start of an erase block
    virtual size_t userFlashSizeEraseBlocks(); // in eraseBlocks
    virtual void flashErase(uint16_t eraseBlockNum); //relativ to userFlashStart
    virtual void flashWritePage(uint16_t pageNumber, uint8_t* data); //write a single page to flash (pageNumber relative to userFashStart
    Ich bin mir noch nicht sicher, ob das dann eine FlashMemory-Klasse wird, oder es bei einer Memory-Klasse bleibt.
    Ebenso bin ich mir noch nicht sicher, ob ich Speicher wie EEPROM in der Platform in dem Ram laden will, oder ob die Memory-Klasse das machen soll. (Evtl. eine spezielle Memory-Klasse). Dazu kommt noch, dass bei ESP8266 der Flash z.B. nicht über den Speicherbus sondern per SPI angebunden ist. Da kann der Flash also nicht einfach über einen Zeiger gelesen werden, sonder muss auch byteweise geholt werden. Beim ESP32 ist es genau so, aber man kann den Speicher in den Adressraum mappen.

    Dann gibt es auch noch Leute, die gern den Flash aus dem Eeprom initialisieren wollen

    Kurz: Ich will das Thema nichtflüchtiger Speicher jetzt einmal richtig anfassen und dann möglichst eine Weile nicht anfassen müssen. Und dafür lasse ich mir auch die nötige Zeit.

    VG Thomas

    Einen Kommentar schreiben:


  • mumpf
    antwortet
    Hallo Thomas,

    ich wollte am WE jetzt mal wieder aufräumen und alles zusammen bringen, u.a. auch mit Deinem Stack "mergen" - da hab ich festgestellt, dass Du den memory-rework branch noch nicht im master hast. Derzeit gäbe es also entweder knx-rf oder flash. Gibt es dafür einen Grund? Planst Du, das noch zusammen zu bringen? Ist nicht eilig, ich hab je eine lauffähige Version, ich wollte nur wissen, ob sich da was auseinanderentwickelt...

    Gruß, Waldemar

    Einen Kommentar schreiben:


  • mumpf
    antwortet
    Hi,

    ich konnte jetzt erfolgreich den Segger JLink mit PlatformIO in Betrieb nehmen. Programmieren klappt, auch ohne den gesamten Flash zu löschen (die ETS-Daten bleiben also erhalten), Debugging geht auch - super.

    Was ich noch vermisse: Der Output über SerialUSB ist nicht wie erwartet im VSCode zu sehen. Kann mir hier jemand einen Tipp geben, was ich machen muss oder wo ich das nachlesen kann? Meine bisherigen Recherchen haben da nichts hervorgebracht...

    Danke und Gruß,
    Waldemar

    Einen Kommentar schreiben:


  • mumpf
    antwortet
    Hi Thomas,

    Zitat von thesing Beitrag anzeigen
    die Versionen, die ich meine habe nichts direkt mit der knxprod zu tun. Man kann im Sketch festlegen, welchen Hardwaretyp, welchen Hersteller, welche Firmwareversion usw. der Sketch hat. Ich würde nur prüfen, ob die Werte im Flash mit dehnen im Sketch übereinstimmen.
    da spricht natürlich nichts gegen - solange Du uns (zumindest mir) verrätst, wie man die Werte im Sketch festlegt... ich denke, das wird man dann ich der knx-demo finden.

    Zitat von thesing Beitrag anzeigen
    Man könnte zusätzlich noch in der knxprod einstellen, dass beim Programmieren via ETS geprüft wird, ob der HardwareType des Sketches zum HardwareType der knxprod passt.
    Ich bin da "indifferent", meinen check hab ich ja selber implementiert, und das auch nur als Selbstschutz, damit ich nicht versehentlich die falsche knxprod mit einer bestimmten Firmware nutze und mich dann wundere, dass nicht läuft (ist mir bereits passiert).

    Gruß, Waldemar

    Einen Kommentar schreiben:


  • thesing
    antwortet
    Hi Waldemar,

    die Versionen, die ich meine habe nichts direkt mit der knxprod zu tun. Man kann im Sketch festlegen, welchen Hardwaretyp, welchen Hersteller, welche Firmwareversion usw. der Sketch hat. Ich würde nur prüfen, ob die Werte im Flash mit dehnen im Sketch übereinstimmen.

    Die ApplicationVersion in der knxprod wird (AFAIK) nur von ETS genutzt. Man könnte zusätzlich noch in der knxprod einstellen, dass beim Programmieren via ETS geprüft wird, ob der HardwareType des Sketches zum HardwareType der knxprod passt. Andere Prüfungen gehen sicher auch. Standartmäßig prüft ETS zumindest ob der Manufacturer der richtige ist.

    VG
    Thomas

    Einen Kommentar schreiben:


  • mumpf
    antwortet
    Hi Thomas,

    ich würde ja gern was davon halten, aber ich weiß nicht, worauf Du Dich beziehst. Um welche Attribute welcher Elemente im XML geht es? Geht es um diese beiden?
    Code:
            <ApplicationProgram Id="M-00FA_A-..." [COLOR=#FF0000]ApplicationNumber="555" ApplicationVersion="11"[/COLOR] ProgramType="ApplicationProgram" ...>
    Wenn ja, dann bitte nur auf ApplicationNumber prüfen, nicht auf die ApplicationVersion! Ich verlasse mich ja explizit drauf, dass man über ReplacesVersions die Version kompatibel erhöhen kann ohne die Firmware ändern zu müssen. Da könnte man höchstens eine MinVersion prüfen. Aber wahrscheinlich geht es um was anderes, oder?

    Grundsätzlich bin ich dafür, dass man prüft, ob die Firmware (also der Sketch) zu einer knxprod passt, aber die vorgesehenen Upgradepfade (neue knxprod für bestehende Firmware) sollen immer noch gehen.

    Ich hab das bisher selber geprüft, indem ich den ersten Paremter in der ETS unsichtbar, mit einer konstante (magic value) vorbelegt immer mitschicke und in der Firmware prüfe, ob der erste Parameter dieses magic value enthält.

    Gruß, Waldemar

    Einen Kommentar schreiben:


  • thesing
    antwortet
    Aktuell schreibe ich beim Save am Anfang des Flashs ein paar Magic Numbers um beim Restore nach einem Restart zu erkennen ob der Speicher gültig ist. Zukünftig würde ich dort die PID_HARDWARE_TYPE und PID_VERSION vom DeviceObject schreiben wollen. Dann würde man zusätzlich prüfen, ober der Flash zum Sketch passt. Das setzt natürlich vorraus, dass man die Werte des DeviceObjects im Sketch entsprechend füllt. Was haltet ihr davon?

    VG
    Thomas

    Einen Kommentar schreiben:


  • mumpf
    antwortet
    Zitat von thesing Beitrag anzeigen
    Der Dpt ist im GroupObject derzeit nicht als Referenz (Dpt&) definiert
    Danke für die Aufklärung. Auf das & hab ich nicht geachtet. Das zeigt mal wieder meine C++-Lücken...

    Zitat von thesing Beitrag anzeigen
    Es würde schon Sinn machen jeden Dpt nur einmal zu instanzieren. Da hast du Recht.
    Wenn das nur 4 statt 6 Bytes bringt, ist das nicht so doll... da macht Dein Vorschlag mit dem weglassen des _datapointType und immer DPT mitgeben beim Aufruf der Value-Funktionen mehr Sinn.

    Zitat von thesing Beitrag anzeigen
    Allerdings mit #ifndefs damit man das bei einer "richtigen" IDE übersteuern kann.
    Da bin ich auch für, das man das dann einfacher in .git einchecken und muss es mit einer "richtigen IDE" nicht anfassen .

    Gruß, Waldemar

    Einen Kommentar schreiben:


  • mumpf
    antwortet
    Nanosonde:
    Ich kann Dir meine platformio.ini Datei hier mal zur Verfügung stellen, wenn Du magst.
    Das wäre toll, danke.

    Gruß, Waldemar

    Einen Kommentar schreiben:


  • thesing
    antwortet
    mumpf
    Der Dpt ist im GroupObject derzeit nicht als Referenz (Dpt&) definiert. Damit entspricht die Größe der Summe der Instanzvariablen. In c++ ist eine struct eine Klasse nur public membern. Bei mir ist der Dpt ein Klasse mit nur public-Membern. Also praktisch das gleiche, aber nicht so deklariert.

    Es würde schon Sinn machen jeden Dpt nur einmal zu instanzieren. Da hast du Recht.

    Bei Punkt (a) müsste man in der GroupObjectTable schon eine Liste von (asap, callBack) haben um die richtigen Callbacks ermitteln zu können.

    Vielleicht sollten wir für Listen entweder die STL nutzen, oder ein eigenes Template hinzufügen.

    Da niemand ein Problem mit einer config.h hat, wird es dann darauf hinaus laufen. Allerdings mit #ifndefs damit man das bei einer "richtigen" IDE übersteuern kann.

    Einen Kommentar schreiben:


  • Nanosonde
    antwortet
    PlatformIO und J-Link war einfach einzurichten. Ich nutze das alles unter Windows 10 64-Bit.
    Ich kann Dir meine platformio.ini Datei hier mal zur Verfügung stellen, wenn Du magst.

    Zitat von mumpf Beitrag anzeigen
    Ich fände die Möglichkeit, beides zu nutzen, am schönsten (also Thomas #ifndef-Vorschlag).
    Ich würde die config.h jetzt nicht unnötig mit #ifndefs usw. zupflastern.
    Derjenige, der das vom Build Prozess aus steuerbar benötigt, kann sich das ja einfach selbst mit zwei Zeilen hinzufügen.
    Von daher würde ich dort wikrlich nur die #defines mit ein wenig Doku wozu das ist, da rein packen.

    Einen Kommentar schreiben:


  • mumpf
    antwortet
    Hi Nanosonde,

    ich bin von PlatformIO auch begeistert und habe mir gestern den Segger J-Link EDU bestellt. Falls ich das nicht vernünftig eingerichtet bekomme, würde ich mich nochmal an Dich wenden

    Zitat von Nanosonde Beitrag anzeigen
    einfacher ist vermutlich wirklich eine einfache globale config.h.
    Ich fände die Möglichkeit, beides zu nutzen, am schönsten (also Thomas #ifndef-Vorschlag).

    Gruß, Waldemar

    Einen Kommentar schreiben:


  • Nanosonde
    antwortet
    Hi!
    Ich würde auch für eine globale config.h plädieren.
    Projekte wie FreeRTOS und BTstack nutzen sowas auch, um internes Feintuning usw. für den Stack einzustellen.

    (Die Arduino GUI ist für mich keine IDE ;-) )

    Ich habe PlatformIO mit VS Code zum ersten Mal für die KNX-RF Implementierung genutzt und bin begeistert.
    Auch das Debugging in VS Code mit einem Segger J-Link EDU klappt super und hat echt geholfen.
    Die #defines setzt man dort in der zentralen Datei "platformio.ini".

    Der Arduino Build Prozess ist beschrieben.

    Für die Linux-Plattform könnte man ja das CMakeFileLists.txt entsprechend anpassen, um #defines unterzubringen.


    ABER: einfacher ist vermutlich wirklich eine einfache globale config.h.
    Da könnte ich dann auch die PIN-Definitionen für RF unterbringen. Und welches SPI Device zu nutzen ist.

    Einen Kommentar schreiben:


  • mumpf
    antwortet
    Hi Thomas,

    Zitat von thesing Beitrag anzeigen
    Ich denke da könnte man in der Tat etwas sparen:
    danke für Deine ausführliche Antwort, ich muss nur mal ein paar Sachen mit meinen Worten formuliert nachfragen, um zu checken, ob ich Dich richtig verstanden habe...

    Erstmal um mein Unwissen auszuräumen und was zu lernen:
    Punkt (e): Dpt ist doch eine Klasse mit 3 short, also 6 Byte lang. Ich dachte, wenn man eine Instanz kreiert, dann wird die dynamisch in Speicher erzeugt (6 Bytes) und die Referenz darauf (also   _datapointType ) ist technisch ein Pointer, also weitere 4 Byte. Mit meinem Vorschlag wollte ich die Referenz belassen, aber die immer gleichen Instanzen (z.B. 120-mal DPT(1,1)) vermeiden. Ich ging davon aus, ich würde dann nur 6 statt 120*6=720 Bytes verbrauchen. Natürlich hätte man immer noch 120*4 Byte referenz auf diese Instanz. Um beim Beispiel zu bleiben: Vorher sind es 120*(4+6)=1200 Byte, hinterher 120*4+6=486 Byte. Du sprichst vom struct, den habe ich aber nirgendwo gesehen. Als struct wären es dann ja 120*6=720 Byte, da man sich die ganzen Pointer spart. Wie gesagt, diese Rückfrage ist nur, um mein Bild zurechtzurücken...

    Ansonsten habe ich Deine Antwort so verstanden, dass man komplett _datapointType weglassen könnte, wenn man alle Methoden, die darauf verweisen (eben die erwähnten value-Methoden) entfernt. Was bedeutet, dass man beim Aufruf immer den DPT mitgeben muss. Ich schau mir das an, aber ich könnte mir ein #define vorstellen, das den _datapointType und alle davon abhängigen Methoden ausblendet. Das wären dann (je nachdem, ob ich oben richtig liege) 6 oder 10 Bytes weniger, dafür weniger Komfort beim Aufruf.

    Punkt (d) sind wir uns ja einig, Punkt (c) würde ich nicht anfassen wollen (für nur 1 Byte). Punkt (b) müsste auch nicht sein, wenn man Punkt (a) hinbekommt.

    Zu Punkt (a) aber auch noch eine Verständnisfrage:
    Zitat von thesing Beitrag anzeigen
    Zusätzlich macht man noch ein globales Callback auf der GroupObjectTable (für Leute die viele GroupObjects haben und auf jedem ein UpdateCallback haben)
    Den Teil verstehe ich: Nur ein Callback, da das KO ja als Parameter mitgeschickt wird, muss man im callback sowieso anhand der asap dispatchen. Das wäre neu, keine Seiteneffekte.

    Zitat von thesing Beitrag anzeigen
    Den könnte man los werden wenn man die UpdateHandler in der GroupObjectable verwaltet. (etwa stumpf als Liste) Die würde man dann bei einem Update durchgehen und die Callbacks aufrufen.
    Hier habe ich ein Problem: Entweder man muss dann in der Liste das Pärchen (asap, callback) halten oder wieder ein Array von callbacks machen, was keinen Vorteil bringt. Und einfach stumpf alle callbacks aufzurufen würde eine Verhaltensänderung mit sich bringen, denn zur Zeit wird ja nur das KO aufgerufen, dass einen Callback zugewiesen hat. Die Liste (asap, callback) würde letztendlich mehr Speicher verbrauchen, sobald mehr als 2/3 aller KO einen callback haben.

    Mein Vorschlag: Über ein #define den callback aus dem GroupObject entfernen und dann nur noch den globalen callback zu lassen. Dispatching passiert dann auf Applikationsebene und alles ist gut. Das wären dann weitere 4 Bytes gespart.

    Ich würde dann auf sowas hin arbeiten:
    Code:
        size_t asapValueSize(uint8_t code);
    #ifndef SMALLER_GROUPOBJECTS
        GroupObjectUpdatedHandler _updateHandler;
        Dpt _datapointType;
    #endif
        size_t goSize();
        uint16_t _asap = 0;
        ComFlag _commFlag = Ok;
        uint8_t* _data = 0;
        uint8_t _dataLength = 0;
        // GroupObjectTableObject* _table = 0; //is now class variable
    natürlich mit #ifndef an allen weiteren abhängigen Stellen + ein globaler _updateHandler. Damit wäre ein KO nur noch 5 Byte (+Daten) groß, oder?

    Gruß, Waldemar

    P.S.: Wäre der globale _updateHandler nicht als Klassenmethode im GroupObject besser aufgehoben? Anstatt in der GroupObjectTable?

    Einen Kommentar schreiben:


  • mumpf
    antwortet
    Hi Thomas,

    Zitat von thesing Beitrag anzeigen
    Scheinbar sollte ein #ifdef MEDIUM_TYPE == FOO nicht nötig sein, das der Linker die nicht benutzen Objectdateien nicht linken sollte.
    das habe ich irgendwo auch mal gelesen, es aber bisher nicht verifiziert. Ich muss mir mal die Kommandozeile für den Linker ansehen.

    Aber selbst wenn der Linker nur die benötigten object files linkt, sollte man über #ifdef/#ifndef absichern, dass man nicht versehentlich oder aus Unwissenheit Codingteile referenziert, die nicht gebraucht werden. Die Idee einer config.h, die überall includiert ist, finde ich gut (wenn man bei Arduino wirklich keine defines von außen mitgeben kann - ich dachte, das kann jede C/C++ Entwicklungsumgebung). Allerdings hätte ich in dem config.h nur ein paar #defines gesehen, die #ifdef/#ifndef stehen doch dann im restlichen Stack, oder?

    Ahh, jetzt hab ich es gepeilt! Du würdest config.h folgendermaßen aufbauen:
    Code:
    #ifndef MEDIUM_TYPE 
    #define MEDIUM_TYPE 0
    #endif
    So könnte man sowohl von außen konfigurieren (über Kommandozeile) wie auch über die config.h in der Arduino-IDE. Wäre super für eine Konfigurierbarkeit, da könnte dann auch Dein Vorschlag von oben mit   #define SMALLER_GROUPOBJECTS  rein.

    Jetzt, wo ich es versanden habe (korrigier mich, falls nicht):

    Gruß, Waldemar

    Einen Kommentar schreiben:

Lädt...
X