Ziel: USB-Treiber



  • erik.vikinger schrieb:

    Im Ernst, falls sich kein gescheites Board finden lässt und Du möchtest mach ich was passendes fertig.
    Ich hab mal hier http://www.mikrocontroller.net/topic/168335 eine Anfrage gestellt.

    Wie gesagt, Zeit hats schon noch. 😉

    Aber wirklich ganz großen Dank für die Mühen, die du auf dich nimmst bzw. auf dich zu nehmen bereit bist. 😮 🙂



  • Hallo,

    XanClic schrieb:

    Aber wirklich ganz großen Dank für die Mühen, die du auf dich nimmst bzw. auf dich zu nehmen bereit bist. 😮 🙂

    Blos nicht falsch verstehen, wenn ich mit meinem Projekt an dieser Stelle bin würde ich mich gerne ins gemachte Nest setzen (also den fertigen Quell-Code für den "Debug-USB-Stick" und viel Erfahrung übernehmen). Ganz uneigennützig bin auch ich nicht. 😃
    Den Lötkolben nehme ich beruflich zur Zeit leider nur selten in die Hand (FPGAs haben auch BGA-Behausungen) so das ich einfach mal wieder etwas sinnvolle Übung haben möchte.

    Grüße
    Erik



  • Dann bin ich ja beruhigt. 😃



  • Hallo,

    Als Entwicklungs-Board mit dem LPC2888 hab ich nur noch das http://www.icetech.com/emularm/lpc2880_board.html gefunden. Dieses Board ist zwar umfangreich ausgestattet (viel zu umfangreich und trotzdem fehlt es an DRAM, es benötigt auch immer ein Netzteil da es sich nicht per USB versorgen lässt) aber der Preis ist schlicht indiskutabel.
    Für vertretbares Geld scheint es wirklich nur das Olimex-Board zu geben. Wenn Du das wirklich machen möchtest sag mir bitte rechtzeitig bescheid, den fehlenden RS232-Anschluss kannst Du dann von mir haben.

    Ich hab auch mal nach anderen µC mit High-Speed-USB-Device geschaut aber da gibt es sonst fast nur größere ARM9-CPUs die z.B. Ethernet mitbringen und eben auch nur auf reichlich bestückten und entsprechend teuren Boards zu haben sind, nebst dessen das schon der µC an sich mehr Geld kostet (ein ARM9 fällt eher in die Klasse Pentium I mit >100MHz, wogegen der ältere ARM7-Kern eher mit nem 486-50MHz zu vergleichen ist und auch deutlich weniger Lizenzgebühren an ARM fließen). Am Wochenende klappere ich mal noch die anderen üblichen Verdächtigen (auch abseits der ARM-Lizenz-Nehmer) ab ob sich eventuell doch noch ein anderer interessanter µC auf einem adäquatem Board finden lässt.

    Gerade im Hinblick auf Mass-Storage bin ich wirklich der Meinung das Full-Speed nicht in Frage kommt, oder bist Du da anderer Meinung? Ich denke das die Beschränkung auf EHCI ein sinnvoller Schritt ist um möglichst schnell ein möglichst gutes Ergebnis zu erzielen. Trotzdem unterstützen die USB 2 Devices in den µC auch immer noch Full-Speed.
    Hierzu währe sicher auch die Meinung von Erhard interessant.

    Grüße
    Erik



  • erik.vikinger schrieb:

    ... aber der Preis ist schlicht indiskutabel.

    Als FPGA Entwickler solltest Du dich ja von solchen Preisen nicht abschrecken lassen 😉


  • Mod

    Ich denke das die Beschränkung auf EHCI ein sinnvoller Schritt ist, um möglichst schnell ein möglichst gutes Ergebnis zu erzielen.

    Ja, das wäre super, wenn das ginge. Am Netzwerk sind wir ja auch schon heftig dran. 🙂



  • erik.vikinger schrieb:

    Gerade im Hinblick auf Mass-Storage bin ich wirklich der Meinung das Full-Speed nicht in Frage kommt, oder bist Du da anderer Meinung?

    Bisher bin ich da noch ziemlich anderer Meinung. 😉
    Ich möchte USB erstmal zum Laufen bekommen, dann kann ich immer noch daran arbeiten, es schnell zu machen.

    abc.w schrieb:

    Als FPGA Entwickler solltest Du dich ja von solchen Preisen nicht abschrecken lassen 😉

    Ich bin aber keiner. 😉

    Erhard Henkes schrieb:

    Ja, das wäre super, wenn das ginge. Am Netzwerk sind wir ja auch schon heftig dran. 🙂

    Netzwerk ist ja auch was anderes und meiner Meinung nach (aus Erfahrung) um einiges einfacher. 😃



  • Hallo,

    XanClic schrieb:

    Ich möchte USB erstmal zum Laufen bekommen, dann kann ich immer noch daran arbeiten, es schnell zu machen.

    Dafür musst Du mindestens 2 unterschiedliche Host-Controller-Treiber schreiben und der Umstieg von USB 1 auf USB 2 im Basis-Treiber (z.B. die 8 fache Frame-Häufigkeit) ist sicher auch nicht ohne. Ich persönlich bin der Meinung das man sich damit den Weg nur unnötig lang macht. Aber jedem das seine, ich hoffe ich kann Dir trotzdem helfen.

    XanClic schrieb:

    Netzwerk ist ja auch was anderes und meiner Meinung nach (aus Erfahrung) um einiges einfacher. 😃

    Oh ja, bei Netzwerk muss man nur senden und empfangen, Timing ist auch nicht ganz so wichtig.

    abc.w schrieb:

    Als FPGA Entwickler solltest Du dich ja von solchen Preisen nicht abschrecken lassen 😉

    In einer Firma gibt es da auch andere Kriterien. Wenn man das Board von einer Firma kauft wo man auch mal unkompliziert einen Application-Engineer ans Telefon bekommt der einem aus ner Klemme befreit für die man selber mal 2 Tage braucht dann hat sich das teurere Board schon fast bezahlt gemacht. Privat gibt es einfach ganz andere Prioritäten.
    Außerdem gibt es auch preiswerte FPGA-Entwicklungs-Boards.

    Grüße
    Erik


  • Mod

    Zurück zum USB-Einstieg. Man fängt ja gemäß dem Stand der Diskussion wohl mit dem Host-Controller für EHCI an.

    OK, ich hab mir jetzt mal die EHCI-Spec runtergeladen und da steht tatsächlich: A USB 2.0 Host Controller includes one high-speed mode host controller and 0 or more USB 1.1 host controllers ...

    In Sun VirtualBox steht ja EHCI zur Verfügung. Da wir nun das ID Paging im MMIO-Bereich beherrschen, was sollte man da alles über die EHCI-USB-BaseAddress abfragen? Einiges haben wir ja während des PCI Scans beispielhaft dargestellt:
    http://www.henkessoft.de/OS_Dev/Bilder/rev131.PNG
    Was benötigen wir da alles an Infos?

    Links:

    Um zu dieser Spezfikation kompatibel zu sein, muss man Companion Controller unterstützen

    http://forum.osdev.org/viewtopic.php?f=1&t=21103&hilit=EHCI

    http://wiki.osdev.org/index.php?title=Programming_the_EHCI <--- leider noch leer!



  • XanClic schrieb:

    Netzwerk ist ja auch was anderes und meiner Meinung nach (aus Erfahrung) um einiges einfacher.

    Schon mal einen TCP/IP Stack oder sowas wie PPP programmiert? 😃


  • Mod

    Ich habe mal in pci.c begonnen die wichtigsten Daten mittels der USB-Basis-Adresse heraus zu lesen, z.B. Adresse der Operational Registers (=Basis+CapLength) oder Vorhandensein von Extended Capabilities.

    Ich denke, dass hier die "Musik" des Host-Controllers spielt:

    OpRegs:

    Offset  Mnemonic           Register-Name 
    00h     USBCMD             USB Command 
    04h     USBSTS             USB Status 
    08h     USBINTR            USB Interrupt Enable 
    0Ch     FRINDEX            USB Frame Index 
    10h     CTRLDSSEGMENT      4G Segment Selector 
    14h     PERIODICLISTBASE   Frame List Base Address 
    18h     ASYNCLISTADDR      Current Asynchronous List Address Register 
    1C-3Fh                    (Reserved) 
    40h     CONFIGFLAG         Configure Flag Register  
    44h     PORTSC(1-N_PORTS)  Port Status/Control
    

    USB Command Register indicates the command to be executed by the serial bus host controller. Writing to the register causes a command to be executed.
    USB Status Register indicates pending interrupts and various states of the Host Controller. The status resulting from a transaction on the serial bus is not indicated in this register. Software sets a bit to 0 in this register by
    writing a 1 to it.
    USB Interrupt Enable Register enables and disables reporting of the corresponding interrupt to the software. When a bit is set and the corresponding interrupt is active, an interrupt is generated to the host. Interrupt sources that are disabled in this register still appear in the USBSTS to allow the software to poll for events.
    USB Frame Index Register is used by the host controller to index into the periodic frame list. The register updates every 125 microseconds (once each micro-frame). Bits [N:3] are used to select a particular entry in the Periodic
    Frame List during periodic schedule execution.
    Control Data Structure Segment Register allows the host software to locate all control data structures within the same 4 Gigabyte memory segment.
    Periodic Frame List Base Address Register contains the beginning address of the Periodic Frame List in the system memory.
    Current Asynchronous List Address Register contains the address of the next asynchronous queue head to be executed.
    Configure Flag Register is only reset by hardware when the auxiliary power is initially applied or in response to a host controller reset.
    Port Status and Control Register is only reset by hardware when the auxiliary power is initially applied or in response to a host controller reset.

    Sehe ich das richtig? 😕



  • Z schrieb:

    XanClic schrieb:

    Netzwerk ist ja auch was anderes und meiner Meinung nach (aus Erfahrung) um einiges einfacher.

    Schon mal einen TCP/IP Stack oder sowas wie PPP programmiert? 😃

    TCP/IP ja, für IRC und etwas HTTP sowie ein ls mit FTP hats auch gereicht. 😉

    Erhard Henkes schrieb:

    Sehe ich das richtig? 😕

    Ja und nein. Ich persönlich würde sagen, das wichtige spielt sich eher in der Frameliste und in den dort eingetragenen Deskriptoren ab (wenn EHCI einigermaßen ähnlich zu UHCI ist, wie ich gehört habe).


  • Mod

    Frameliste und in den dort eingetragenen Deskriptoren

    Ja, die "Data Structures" sind wichtig. Bin gerade an Kap. 3 u. 4 der EHCI-Spec dran, interessant, aber auch herausfordernd komplex. 🙂


  • Mod

    Enhanced Host Controller Interface Specification for Universal Serial Bus, March 12, 2002, Revision: 1.0, Kap. 4.1 "Host Controller Initialization":

    When the system boots, the host controller is enumerated, assigned a base address for the register space and BIOS sets the FLADJ register to a system-specific value. After initial power-on or HCReset (hardware or via HCReset bit in the USBCMD register), all of the operational registers will be at their default values. After a hardware reset, only the operational registers not contained in the Auxiliary power well will be at their default values.

    In order to initialize the host controller, software (Anm.: unser Treiber, den wir erstellen wollen) should perform the following steps:
    • Program the CTRLDSSEGMENT register with 4-Gigabyte segment where all of the interface data structures are allocated.
    • Write the appropriate value to the USBINTR register to enable the appropriate interrupts.
    • Write the base address of the Periodic Frame List to the PERIODICLIST BASE register. If there are no work items in the periodic schedule, all elements of the Periodic Frame List should have their T-Bits set to a one.
    • Write the USBCMD register to set the desired interrupt threshold, frame list size (if applicable) and turn the host controller ON via setting the Run/Stop bit.
    • Write a 1 to CONFIGFLAG register to route all ports to the EHCI controller

    Das dürfte doch der Anfang sein?

    Kann man damit die Funktionalität bereits prüfen? (z.B. USB-Stick einstecken / entfernen usw.?)

    At this point, the host controller is up and running and the port registers will begin reporting device connects, etc.


  • Mod

    Ich hab das mal versuchsweise - hoffentlich richtig - umgesetzt, damit man Register usw. testen kann, siehe: https://prettyos.svn.sourceforge.net/svnroot/prettyos/trunk/Source/kernel/ehci.c und https://prettyos.svn.sourceforge.net/svnroot/prettyos/trunk/Source/kernel/include/ehci.h


  • Mod

    Eine funktionierende Vorgehensweise: (Rev. 156)

    void initEHCIHostController()
    {
        // Program the CTRLDSSEGMENT register with 4-Gigabyte segment where all of the interface data structures are allocated.
        pOpRegs->CTRLDSSEGMENT = *((volatile uint32_t*)(opregs + 0x10)); // default
    
        // Write the appropriate value to the USBINTR register to enable the appropriate interrupts.
        // pOpRegs->USBINTR       = *((volatile uint32_t*)(opregs + 0x08)) = 0x3F; // 63 = 00111111b
        pOpRegs->USBINTR       = *((volatile uint32_t*)(opregs + 0x08)) = 0x1; /// TEST: Bit 0, USB Interrupt Enable
    
        // Write the base address of the Periodic Frame List to the PERIODICLIST BASE register.
        uint32_t virtualMemoryPERIODICLISTBASE = (uint32_t) malloc(0x1000,PAGESIZE);
        uint32_t physicalMemoryPERIODICLISTBASE = paging_get_phys_addr( kernel_pd, (void*)virtualMemoryPERIODICLISTBASE );
        pOpRegs->PERIODICLISTBASE = *((volatile uint32_t*)(opregs + 0x14)) = physicalMemoryPERIODICLISTBASE;
    
        // If there are no work items in the periodic schedule,
        // all elements of the Periodic Frame List should have their T-Bits set to 1.
        /// TODO: set T-Bits
    
        // Write the USBCMD register to set the desired interrupt threshold
        // and turn the host controller ON via setting the Run/Stop bit.
        // Software must not write a one to this field unless the host controller is in the Halted state
        // (i.e. HCHalted in the USBSTS register is a one). Doing so will yield undefined results.
        pOpRegs->USBSTS = (*((volatile uint32_t*)(opregs + 0x04)) |= (1<<12)   ); // set Bit 12
        pOpRegs->USBCMD = (*((volatile uint32_t*)(opregs + 0x00)) |= (0x8<<16) ); // Bits 23-16: 08h, means 8 micro-frames
        pOpRegs->USBCMD = (*((volatile uint32_t*)(opregs + 0x00)) |=  0x1      ); // set Start-Stop-Bit                                                           |=  0x1 );    // Run-Stop-Bit
    
        // Write a 1 to CONFIGFLAG register to route all ports to the EHCI controller
        pOpRegs->CONFIGFLAG    = *((volatile uint32_t*)(opregs + 0x40)) = 1;
    
        printformat("\n\nAfter Init of EHCI:");
        printformat("\nCTRLDSSEGMENT:              %X", *((volatile uint32_t*)(opregs + 0x10)) );
        printformat("\nUSBINTR:                    %X", *((volatile uint32_t*)(opregs + 0x08)) );
        printformat("\nPERIODICLISTBASE phys addr: %X", *((volatile uint32_t*)(opregs + 0x14)) );
        printformat("  virt addr: %X", virtualMemoryPERIODICLISTBASE);
        printformat("\nUSBCMD:                     %X", *((volatile uint32_t*)(opregs + 0x00)) );
        printformat("\nCONFIGFLAG:                 %X", *((volatile uint32_t*)(opregs + 0x40)) );
    }
    

    Setzt man alle 6 Bits in USBINTR, dann kommen keine Tastenanschläge mehr an. 😉 Mit Bit0 geht es. Rest muss getestet werden, ob man es setzen kann.


  • Mod

    Tests zeigen, dass man Bit3 im USBINTR zu Beginn nicht setzen darf:

    pOpRegs->USBINTR       = *((volatile uint32_t*)(opregs + 0x08)) = 0x1 | 0x2 | 0x4 | /*0x8 |*/ 0x10 | 0x20;
        /// TEST: Bit 3 cannot be set to 1, Frame List Rollover Enable, otherwise keyboard does not come through
    

    Den Rest darf man auf 1 setzen.



  • Ich habe jetzt zumindest genau die Stelle gefunden wo der Fehler auftritt. Das setzen der Adresse für die Periodic Frame List:

    uint32_t virtualMemoryPERIODICLISTBASE = (uint32_t) malloc(0x1000,PAGESIZE);
    uint32_t physicalMemoryPERIODICLISTBASE = paging_get_phys_addr( kernel_pd, (void*)virtualMemoryPERIODICLISTBASE );
    pOpRegs->PERIODICLISTBASE = *((volatile uint32_t*)(opregs + 0x14)) = physicalMemoryPERIODICLISTBASE;
    

    Kommentiert man die letzte Zeile aus hängt es nicht mehr. Da mir der Code komisch vorkommt habe ich den mal neu geschrieben und auch wie in der Spezifikation die T-Bits gesetzt, hängen tut es aber trotzdem noch.

    Mein Code:

    void* virtualMemoryPERIODICLISTBASE = malloc(0x1000,PAGESIZE);
    uint32_t physicalMemoryPERIODICLISTBASE = paging_get_phys_addr(kernel_pd, virtualMemoryPERIODICLISTBASE);
    pOpRegs->PERIODICLISTBASE = physicalMemoryPERIODICLISTBASE;
    memset(virtualMemoryPERIODICLISTBASE, 0xFF, 0x1000); // Alles auf 1 Setzen setzt auch das T-Bit auf 1
    

  • Mod

    Danke für die Unterstützung! Bei Memory-Adressen bevorzuge ich i.d.R. uint32_t, caste es nach void*, wenn notwendig. Hier macht void* aber wirklich mehr Sinn. Ins Register PERIODICLISTBASE muss die physikalische Adresse der Frame-Pointer.

    Es sind nur 1024 Elemente in der Pointer-Liste, also 0x400 nicht 0x1000.


  • Mod

    Tobiking: Ich kann das nicht nachvollziehen mit dem "Nichthängen". Leider hängt es immer noch.

    Hier die Rev. 162: http://www.c-plusplus.net/forum/viewtopic-var-p-is-1863106.html#1863106

    Versuche bitte nochmal die genaue Stelle zu finden und den Trick, wie man es "laufend" halten kann beim Einstecken von USB-Devices.

    Bei mir läuft es mit real PC und mit Sun VB (aber nur, wenn man nur funktionierende USB-Devices einhängt). Alles sehr eigenwillig.


Anmelden zum Antworten