Ankündigung

Einklappen
Keine Ankündigung bisher.

thelsing/knx (2453c3ce) demo-knx mit Pi Pico (rp2040) baut nicht "out-of-the-box"

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

    [Firmware] thelsing/knx (2453c3ce) demo-knx mit Pi Pico (rp2040) baut nicht "out-of-the-box"

    Hallo,

    bin neu hier und mache mich gerade daran eine nanoBCU mit dem Pi Pico und dem thelsing/knx Stack in Betrieb zu nehmen. Leider scheitere ich schon am Bauen des Beispielprojekts.

    Mit einem frischen Klon von thelsing/knx (2453c3ce) und dem darin befindlichen Beispielprojekt examples/knx-demo habe ich der Datei platformio.ini folgende Konfiguration hinzugefügt:

    Code:
    [env:piPico_tp]
    platform = raspberrypi
    board = pico
    framework = arduino
    lib_extra_dirs = ../../../
    lib_deps = knx
    build_flags =
    -DMASK_VERSION=0x07B0
    -Wno-unknown-pragmas
    Die Fehlermeldung des Compilers lautet dann folgendermaßen:

    Code:
    In file included from C:\users\xy\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedSSLClient.cpp :1:
    C:\users\xy\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedSSLClient.h:2 6:10: fatal error: QSPIFBlockDevice.h: No such file or directory
    Die voreingestellten Konfigurationen nodemcuv2_tp,esp32dev_tp,esp32dev_ip bauen ohne Fehler.

    Für ein paar hilfreiche Tipps wäre ich sehr dankbar. Und falls es irgendwo mehr Code-Beispiele für diese Kombination (thelsing/knx, nanoBCU, Pi Pico) gibt, würde ich mich über links sehr freuen. Das OpenKNX Wiki scheint mir eher auf Hardware zu fokussieren, aber vielleicht habe ich ja auch was übersehen.

    Vielen Dank schon mal!

    #2
    Hi Quartel,

    Du bist einfach zu früh dran . Wir sind hier noch schwer am Aufbauen der ganzen Toolchain für den PICO und sind noch nicht fertig.
    Ganz wichtig: Der knx-Stack nutzt nicht das mbed package für den Pico, sondern das von earlephilhower. Und auch das ist noch nicht fertig. Ein PR für die Aufnahme in PIO hängt noch an unvollständiger Debuggerunterstützung.

    Du kannst (auf eigenes Risiko) meine Modifikationen für PIO verwenden, um das Ganze zum Laufen zu bringen. Dazu musst Du in der platformio.ini folgendes hinzufügen:
    Code:
    platform = https://github.com/mumpf/platform-raspberrypi.git
    board = pico
    board_build.core = earlephilhower
    ; configure filesystem size. Default 0 Mbyte.
    ; board_build.filesystem_size = 1M
    ; inject core package.. not yet registered with PlatformIO
    ; registry, so pull working version directly from git / download page.
    ; note that download link for toolchain is specific for OS. see https://github.com/earlephilhower/pico-quick-toolchain/releases.
    platform_packages =
        mumpf/framework-arduinopico@https://github.com/mumpf/arduino-pico.git#beta
        maxgerhardt/toolchain-pico@https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.3.2-a/x86_64-w64-mingw32.arm-none-eabi-9d55fd1.220202.zip
    build_flags =
      ...
      -frtti
    (Die 3 Punkte ... bei build_flags sollen sagen, dass alles andere so bleibt, -frtti ergänzt werden muss).

    Damit läuft das bei mir. Und nicht wundern, beim ersten build lädt er das Internet runter , also auf eine kreative Pause von 20-30 Minuten einstellen.

    Gruß, Waldemar

    P.S.: Die anderen Sachen in der platformio.ini bleiben natürlich...
    Zuletzt geändert von mumpf; 07.04.2022, 11:33.
    OpenKNX www.openknx.de

    Kommentar


      #3
      Hi Waldemar,

      vielen Dank für deine schnelle Antwort. Ich dachte mir schon, dass es etwas mit mbed zu tun hat. Ich war nur verunsichert, weil Ing-Dom in diesem älteren Thread geschrieben hatte, dass es "absolut einsatzbereit" wäre. Natürlich ist mir aber auch klar, dass sich sowas ändern kann, wenn weiter daran gearbeitet wird.

      Ich habe deine Konfiguration übernommen und lasse VSCode gerade rödeln. Ich nehme an, das ist der Teil, den du mit "lädt er das Internet" runter bezeichnet hast.
      Ich melde mich später nochmal mit dem Resultat.

      Gruß, Quartel

      Kommentar


        #4
        Während des Builds wird der folgende Befehl ausgeführt

        git clone https://github.com/mumpf/arduino-pico.git --recursive --depth 1 --branch beta

        welcher viele Source klont und dann irgendwann mit diesem Fehler abbricht:

        Failed to recurse into submodule path 'pico-extras'

        Kommentar


          #5
          Zitat von Quartel Beitrag anzeigen
          Ich dachte mir schon, dass es etwas mit mbed zu tun hat. Ich war nur verunsichert, weil Ing-Dom in diesem älteren Thread geschrieben hatte, dass es "absolut einsatzbereit" wäre.
          Ist es auch, aber halt nicht mit Plattform I/O, sondern mit Arduino IDE + MS Arduino VSC Extension.
          Debugguing mit Picoprobe geht grundsätzlich auch, zickt aber bisweilen.

          knx-demo sollte ohne weiteres bauen.
          OpenKNX www.openknx.de | NanoBCU und OpenKNX-HW verfügbar

          Kommentar


            #6
            Das es mit Arduino IDE funktioniert, kann ich mit meinen bisherigen Versuchen bestätigen. 🙂

            Kommentar


              #7
              Mist... Sorry, ich hab Dir versehentlich mein Beta-Test geschickt. Bitte mach hinten das beta (und das #) weg.
              Zitat von mumpf Beitrag anzeigen
              mumpf/framework-arduinopico@https://github.com/mumpf/arduino-pico.git#beta
              Leider dauert es dann wieder...

              Gruß, Waldemar
              OpenKNX www.openknx.de

              Kommentar


                #8
                Zitat von SirSydom Beitrag anzeigen
                Ist es auch, aber halt nicht mit Plattform I/O, sondern mit Arduino IDE + MS Arduino VSC Extension.
                Aha. Guter Tipp. 😀👍
                Ich bin davon ausgegangen, dass PIO nur eine IDE ist und im Hintergrund das gleiche macht wie die Arduino IDE. Man lernt eben nie aus. Ich habe PIO auch nur benutzt, weil in thelsing/knx überall die PIO Config-Dateien liegen und ich dachte, dass ich so am schnellsten zum gewünschten Ergebnis komme. So wirklich intuitiv finde ich PIO im VSCode allerdings nicht, insofern ist mir dein o.g. Ansatz auch lieber.

                Leider kämpfe ich da aber jetzt mit den so oft üblichen "Kleinigkeiten": nach der Installation der MS Arduino VSC Extension habe ich dem VSC Workspace den Basis-Ordner von thelsing/knx hinzugefügt, und die examples/knx-demo/knx-demo.ino Datei als 'sketch' in der .vscode/arduino.json eingetragen. Das Pico-Board habe ich natürlich auch installiert und konfiguriert ("board": "arduino:mbed_rp2040: pico"). Ein leidiges Problem ist aber der Pfad zur knx.h, die beim Kompilieren nicht gefunden wird. Laut MS Arduino Doku muss man die Pfade in der .vscode\c_cpp_properties.json eintragen, bei mir scheint jeglicher Pfadeintrag in der Datei (egal ob relativ oder absolut) keine Auswirkung zu haben. Wenn ich im .ino Sketch include den absoluten Pfad zu knx.h angebe, dann wird die Datei gefunden, aber dann meckert er, dass MASK_VERSION nicht gesetzt ist, auch wenn ich "-DMASK_VERSION=0x27B0" unter "compilerArgs" hinzufüge. Für mich ein weiterer Hinweis, dass .vscode/c_cpp_properties.json gar nicht ausgewertet wird.

                Habe ich etwas übersehen?

                Kommentar


                  #9
                  Zitat von Quartel Beitrag anzeigen
                  Das Pico-Board habe ich natürlich auch installiert und konfiguriert ("board": "arduino:mbed_rp2040: pico").
                  das ist wieder das falsche Board. Mbed.

                  ich hack' jetzt mal schnell ein Demo-VSC-sketch zusammen, das wollte ich schon ewig mal machen. Jetzt hab ich ansporn.
                  OpenKNX www.openknx.de | NanoBCU und OpenKNX-HW verfügbar

                  Kommentar


                    #10
                    probier mal:

                    knx-demo-pipico.zip
                    OpenKNX www.openknx.de | NanoBCU und OpenKNX-HW verfügbar

                    Kommentar


                      #11
                      Kompilieren klappt!
                      Beim upload habe ich noch Probleme, habe ich aber noch nicht genauer untersucht.

                      Dass es nicht das Board mit mbed sein darf, konnte ich den vorigen Posts nicht entnehmen. Ich hatte mumpf so verstanden, dass mein erster Versuch mit dem "falschen" mbed war:

                      Zitat von mumpf Beitrag anzeigen
                      Der knx-Stack nutzt nicht das mbed package für den Pico, sondern das von earlephilhower
                      Und per Default wird das arduino-pico core board nicht vom Board Manager vorgeschlagen, weshalb ich das einzige angebotene Pico Board (mit mbed) ausgewählt hatte.

                      Insofern hat dein Beispiel-Projekt sehr viel Klarheit in die Sache gebracht. Danke! Vielleicht könntest du es ja irgendwie dem thelsing/knx Repo hinzufügen. Hilft bestimmt auch anderen weiter.

                      [Edit] Erst jetzt verstehe ich, wie ich das Zitat von mumpf falsch interpretiert habe : nicht das "falsche mbed" sondern gar kein mbed 😋.
                      Zuletzt geändert von Quartel; 09.04.2022, 10:01.

                      Kommentar


                        #12
                        Zitat von Quartel Beitrag anzeigen
                        Beim upload habe ich noch Probleme
                        a) richtige Serial auswählen
                        oder
                        b) vor dem Upload den PiPico in den BL-Modus versetzen (abstecken, Btn drücken, anstecken, loslassen)
                        oder
                        c) manuall das UF2-File aus dem build folder auf den als USB-MassStorage Device erkannten Pico im BL Modus kopieren
                        OpenKNX www.openknx.de | NanoBCU und OpenKNX-HW verfügbar

                        Kommentar


                          #13
                          Hallo zusammen,

                          ich versuche den rp2040 zum Laufen zu bekommen, aber leider endet der Versuch, eine PA über ETS zu schreiben, erfolglos. Eventuell habt ihr ja eine Idee, woran es liegen könnte. Gleicher Aufbau / Code mit SAMD21 (Seeeduino XIAO) läuft übrigens, wie es sollte.

                          Wenn ihr noch weiter Infos benötigt. Sagt bitte Bescheid. Ich habe noch keine Debug-Möglichkeit, sonst hätte ich in den Tiefen mal geschaut, was da genau passiert.

                          Hier mein Setup:

                          Setup
                          ETS 5.7.4 (Build 1093)
                          Siemens 5WG1 148-1AB21 + Siemens KNX PowerSupply

                          HW-Setup
                          BCU Breadboard Adapter:
                          • ADUM2101 VCC, GND, TX, RX from + MicroBCU (NCN5120)

                          RP2040 (Seeeduino ):
                          • RX/TX Serial - Default: Auf PIN_SERIAL1_TX (6ul) und PIN_SERIAL1_RX (7ul)
                          • Angeschlossen über USB!
                          • RP2040 TX, RX ist mit BCU RX, TX verbunden.
                          • Verkabelung ist ähnlich, wie hier: Foto

                          PlaformIO Setup (MacOS)
                          Code:
                          platform = https://github.com/maxgerhardt/platform-raspberrypi.git
                          board = pico
                          board_build.core = earlephilhower
                          framework = arduino
                          
                          upload_port = /dev/cu.usbmodem14301
                          upload_speed = 115200
                          
                          monitor_port = /dev/cu.usbmodem14301
                          monitor_speed = 115200
                          
                          ; note that download link for toolchain is specific for OS. see https://github.com/earlephilhower/pico-quick-toolchain/releases.
                          platform_packages =
                          ;maxgerhardt/framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#master
                          ;mumpf/framework-arduinopico@https://github.com/mumpf/arduino-pico.git
                          maxgerhardt/framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git
                          maxgerhardt/toolchain-pico@https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.3.3-a/x86_64-apple-darwin14.arm-none-eabi-ed6d983.220212.tar.gz
                          
                          ;lib_ignore = Adafruit TinyUSB Library ; Only with mumpf/framework-arduinopico
                          
                          lib_deps =
                          https://github.com/thelsing/knx.git
                          SPI
                          
                          build_flags =
                          -Wno-unknown-pragmas
                          -DMASK_VERSION=0x07B0
                          -DARDUINO_ARCH_RP2040
                          -DKNX_FLASH_SIZE=4096
                          ;-DUSE_RP2040_LARGE_EEPROM_EMULATION
                          -DUSE_RP2040_EEPROM_EMULATION
                          -DDBG_TRACE
                          ;-DKNX_FLASH_OFFSET=8192
                          ;-DNCN5120
                          -frtti

                          Hier die Log-Ausgabe:
                          Info:

                          - Nachdem start in 'progmode' versetzt.
                          - ETS - PA - Programmieren Angetriggert

                          Code:
                          --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time
                          --- More details at https://bit.ly/pio-monitor-filters
                          --- Miniterm on /dev/cu.usbmodem14301 115200,8,N,1 ---
                          --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
                          FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
                          DataObject api changed, any data stored in flash is invalid.
                          expexted DataObject api version: 1, stored api version: FFFF
                          ETS has to reprogram PA and application!
                          KNX - Individual Adress is set!
                          KNX - Is NOT Configured
                          ownaddr FFFF
                          Setup Finished!
                          Looping...
                          .progmode on
                          B0RLS
                          F11F156080ABRX_WAIT_START
                          90RLS
                          F11F1560808BRX_WAIT_START
                          90RLS
                          F11F1560808BRX_WAIT_START
                          90RLS
                          F11F1560808BRX_WAIT_START
                          B0RLS
                          F1100E1105FRX_WAIT_START
                          TX_FRAME
                          B0FFFF00E117got U_STATE_IND: PE
                          190RLS
                          40F1EFTX_WAIT_CONN
                          100E1107FRX_WAIT_START
                          57got U_STATE_IND: RE PE
                          90RLS
                          F1100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          B0RLS
                          F11F156143069RX_WAIT_START
                          90RLS
                          F11F156143049RX_WAIT_START
                          90RLS
                          F11F156143049RX_WAIT_START
                          90RLS
                          F11F156143049RX_WAIT_START
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          B0RLS
                          F1100E1105FRX_WAIT_START
                          TX_FRAME
                          B0FFFF00E1190RLS
                          40F1EFTX_WAIT_CONN
                          100E1107FRX_WAIT_START
                          47got U_STATE_IND: RE
                          90RLS
                          F1100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF0047got U_STATE_IND: RE
                          E147got U_STATE_IND: RE
                          47got U_STATE_IND: RE
                          147got U_STATE_IND: RE
                          47got U_STATE_IND: RE
                          40EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          B0RLS
                          F1100E1105FRX_WAIT_START
                          TX_FRAME
                          B0FFFF00E1190RLS
                          40F1EFTX_WAIT_CONN
                          100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FF47got U_STATE_IND: RE
                          FF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          B0RLS
                          F1100E1105FRX_WAIT_START
                          TX_FRAME
                          B0FFFF00E1190RLS
                          40F1EFTX_WAIT_CONN
                          100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF17got U_STATE_IND: PE
                          00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E147got U_STATE_IND: RE
                          117got U_STATE_IND: PE
                          17got U_STATE_IND: PE
                          40EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          B0RLS
                          F1100E1105FRX_WAIT_START
                          TX_FRAME
                          B0FFFF047got U_STATE_IND: RE
                          0E1190RLS
                          40EFTX_WAIT_CONN
                          F1100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF17got U_STATE_IND: PE
                          0047got U_STATE_IND: RE
                          E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          B0RLS
                          F1100E1105FRX_WAIT_START
                          TX_FRAME
                          B0FFFF00E1190RLS
                          40F1EFTX_WAIT_CONN
                          100E1107FRX_WAIT_START
                          47got U_STATE_IND: RE
                          90RLS
                          F1100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          17got U_STATE_IND: PE
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          B0RLS
                          F1100E1105FRX_WAIT_START
                          TX_FRAME
                          B0FFFF00E1190RLS
                          40F1EFTX_WAIT_CONN
                          100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          90RLS
                          F1100E1107FRX_WAIT_START
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E147got U_STATE_IND: RE
                          147got U_STATE_IND: RE
                          40EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          TX_FRAME
                          B0FFFF00E1140EFTX_WAIT_CONN
                          L_DATA_CON not received within expected time
                          datagroup-confirm: unhandled APDU-Type: 192
                          TX_IDLE
                          B0RLS
                          Zuletzt geändert von GeminiServer; 29.04.2022, 13:16.
                          OpenKNX www.openknx.de

                          Kommentar


                            #14
                            bei PlattformIO bin ich leider raus.
                            Aber wenn du mal das VSC-Projekt auf #10 ausprobierst, könnte man es evtl. weiter eingrenzen..
                            OpenKNX www.openknx.de | NanoBCU und OpenKNX-HW verfügbar

                            Kommentar


                              #15
                              Ich glaube nicht, dass es wirklich am PIO liegt... scheint ja die KNX-Kommunikation nicht zu klappen.

                              Ich kann Dir anbieten, Dein Zeug auf meiner Hardware laufen zu lassen und dann zu schauen, ob es bei mir geht. Dann wissen wir garantiert, dass es an der Hardware/Verdrahtung/BCU liegen muss.

                              Hast Du Deine Sachen auf git? Schick mir den Link, dann ziehe ich das und probiere es aus.

                              Gruß, Waldemar
                              OpenKNX www.openknx.de

                              Kommentar

                              Lädt...
                              X