USB11-Interface
Das Interface wird mit einem auf 18 Bit Breite konfigurierten Blockram realisiert. Ein Port des Blockrams ist mit dem Systembus des SpartanMC verbunden und das zweite Port mit dem USB-Interface. Das Modul hat keine I/O-Register. Die Komunikation erfolgt nur durch Daten lese und schreib Zugriffe in diesen Blockram. Jeder der installierten Endpunkte kann einen Interrupt auslösen, wenn der Host Daten von einem IN-Endpunkt (Tx) gelesen hat oder wenn der Host Daten auf einen OUT-Endpunkt (Rx) abgelegt hat. Das Interface kann maximal 6 Endpunkte realisieren. An den drei erzeugten Signale ist nur noch folgende externe Beschaltung notwendig, wenn die Signale einen 3,3V Pegel realisieren:Der 1,5K Widerstand zieht D+ bei Disc=1 auf 3,3V wodurch das Interface im FULL-Speed Mode angemeldet wird.
Speicherorganisation
Die Basiadresse des USB Modul liegt oberhalb des Arbeitsspeichers der Konfiguration.Die Adressen (Offset) 0x000 bis 0x07f des DMA-Speichers sind für die Konfiguration des USB-Interfaces reserviert. Im verbleibenden Bereich (0x080 bis 0x3ff) befinden sich 28 Datenspeicher mit je 32 Worten (64 Bytes). Sie werden je nach Konfiguration den Endpunkten zugeordnet. Bei deaktiviertem Double Buffering sind die Puffer aufeinander folgend den Endpunkten 0 bis 15 zugeordnet. Der Bereich ab 0x280 bleibt unbenutzt. Ist Double Buffering aktiviert werden in aufsteigender Reihenfolge jedem der Endpunkte 0 bis 13 zwei Puffer zugeordnet. Enpunkt 14 und 15 kann nicht verwendet werden! Siehe Adresstabelle. Die aktuelle Implementierung der Hardware kann nur maximal 6 Endpunkte verwalten!
Konfigurations- und Statusregister
Offset | Register | Bemerkung | ||
0x00 | ep0c1 | Globales Kommandoregister 1 | ||
0x01 | ep0c2 | Globales Kommandoregister 2 | ||
0x02 | ep1c | Kommandos für Endpunkt 1 | ||
0x03 | ep1s | Status vom Endpunkt 1 | ||
0x04 | ep2c | Kommandos für Endpunkt 2 | ||
0x05 | ep2s | Status vom Endpunkt 2 | ||
0x06 | ep3c | Kommandos für Endpunkt 3 | ||
0x07 | ep3s | Status vom Endpunkt 3 | ||
0x08 | ep4c | Kommandos für Endpunkt 4 | ||
0x09 | ep4s | Status vom Endpunkt 4 | ||
0x0a | ep5c | Kommandos für Endpunkt 5 | ||
0x0b | ep5s | Status vom Endpunkt 5 | ||
.. | .. | |||
0x1e | ep15c | Kommandos für Endpunkt 15 | ||
0x1f | ep15s | Status vom Endpunkt 15 | ||
0x20 | glob | globales Steuerregister |
Die aktuelle Implementierung unterstützt nur 6 Endpunkte!
Descriptoren (read only)
Offset | Bemerkung | |||
0x21 | Device Descriptor | |||
0x2a | Configuration Descriptor | |||
0x68 | Language Descriptor | |||
0x6a | String Descriptor describing manufacturer | |||
0x73 | String Descriptor describing product | |||
0x7c | String Descriptor describing serial number |
Puffer
Offset | Puffer | Bemerkung | EP ohne double buffering | EP mit double buffering |
0x080 | data00 | Puffer 0 für 64 Byte | 0 | 0 (0) |
0x0a0 | data01 | Puffer 1 für 64 Byte | 1 | 0 (1) |
0x0c0 | data02 | Puffer 2 für 64 Byte | 2 | 1 (0) |
0x0e0 | data03 | Puffer 3 für 64 Byte | 3 | 1 (1) |
.. | .. | |||
0x260 | data15 | Puffer 15 für 64 Byte | 15 | 7 (1) |
.. | .. | |||
0x3e0 | data27 | Puffer 27 für 64 Byte | - | 13 (1) |
Die aktuelle Implementierung unterstützt nur 6 Endpunkte! Die Anordnung der Bytes in den Puffern kann mit dem Parameter NOGAP verändert werden. Mit NOGAP=0 werden die Bytes in der 9 Bit Anordnung des SpartanMC abgelegt. Diese Anordnung ist für die Übertragung von Zeichenketten sinnvoll. Sollen 16 Bit Werte vom SpartanMC in dem DMA-Puffer abgelegt werden, dann müssen die Byte im 8 Bit Abstand in das 18 Bit Wort eingetragen Werden. Diese Anordnung der Bytes wird mit NOGAP=1 eingestellt.
Lesen eines 16 Bit Wortes aus einem Puffer mit NOGAP=0 oder NOGAP=1
// lesen 16 Bit unsigned int wert16; #if SB_USB11_0_NOGAP == 0 unsigned int i; unsigned int j; i = USB11_0_DMA->data02[0]; // 2 SpMC Byte zu 16 Bit zusammen fassen j = i & 0x3fe00; i = i & 0x000ff; j = j >> 1; wert16 = j | i; #else wert16 = USB11_0_DMA->data02[0]; #endif
Schreiben eines 16 Bit Wortes in einen Puffer mit NOGAP=0 oder NOGAP=1
// schreiben 16 Bit unsigned int wert16; #if SB_USB11_0_NOGAP == 0 unsigned int k; unsigned int l; k = wert16; // 16 Bit in der SpMC Bytanordnung in k bilden l = k & 0x3ff00; k = k & 0x000ff; l = l << 1; k = l | k; USB11_0_DMA->data01[0] = k; #else USB11_0_DMA->data01[0] = wert16; #endif
Bitbelegung der Register
epXc Register
Bit | Bezeichnung | Bedeutung | ||
6-0 | size | Anzahl zu sendender Bytes -1 | Wert mit 0x3f maskieren (0 entspricht 1 Byte) | |
10-7 | reserviert | |||
11 | bufsel | Auswahl des aktiven Puffers bei double buffering. | 0=Unterer Puffer, 1=Oberer Puffer (im Speicherbereich) | |
12 | in | Tx Endpunkt zum Senden von Daten zum Host | 1=Endpunkttyp IN, sonst 0 | |
13 | out | Rx Endpunkt zum Empfangen von Daten von Host | 1=Endpunkttyp OUT, sonst 0 | |
14 | control | Steuerinformationen des Interface | 1=Endpunkttyp CONTROL, sonst 0 | |
15 | mode | Datentransfer | 1=synchron, 0=asynchron | |
16 | intr | enable Interrupt | 1=Interrupt enable, 0=Interrupt disable | |
17 | en | enable (HOST darf lesen bzw. schreiben) | EP IN: 1=Puffer enhällt Daten, EP OUT: 1=Puffer leer |
epXs Register (read only)
Bit | Bezeichnung | Bedeutung | ||
6-0 | Anzahl empfangender Bytes -1 | =0 es wurde 1 Byte empfangen / =63 es wurden 64 Byte empfangen. | ||
17-7 | not used |
Globales Steuerregister
Bit | Bezeichnung | Bedeutung | ||
0 | iep00 | Impuls setzt Interrupt EP 0 zurück | ||
.. | .. | |||
15 | iep15 | Impuls setzt Interrupt EP 15 zurück | ||
16 | ep0ie | enable EP0 Interrupt | ||
17 | en | enable USB-Interface |
C-Quellen der USB-Include Funktionen und Macros:
Programm | Beschreibung | ||
---|---|---|---|
* | usb_init.c | - | void usb_init(usb11_dma_t *usb, unsigned int delay) - Abmelden des USB-Interfaces am Host und
erneute Anmeldung am Host nach einer Pause. |
* | usb_ep_intr_dis.c | - | void usb_ep_intr_dis(struct usb_ep *ep) - Interrupt für einen Endpunkt sperren |
* | usb_ep_intr_en.c | - | void usb_ep_intr_en(struct usb_ep *ep) - Interrupt für einen Endpunkt freigeben |
* | usb_ep_intr_clear.c | - | void usb_ep_intr_clear(struct usb_ep *ep) - Löschen eines aktiven Endpunkt Interrupt in der ISR |
* | usb_ep_poll_rxdata.c | - | int usb_ep_poll_rxdata(struct usb_ep *ep) - Der aktuelle Zustand des Signals USB_CTRL_EN wird abgefragt. Ist das Signal 0, dann wurden noch keine Daten vom Host empfangen und die Funktion gibt eine -1 zurück. Ist das Signal 1, dann hat der Host Daten im Puffer abgelegt und die Funktion gibt die Anzahl der empfangenen Byte - 1 zurück. |
* | usb_ep_poll_txready.c | - | int usb_ep_poll_txready(struct usb_ep *ep) - Der aktuelle Zustand des Signals USB_CTRL_EN wird abgefragt. Ist das Signal 0, dann wurden die Daten im Puffer vom Host abgeholt und es wird eine 1 zurück gegeben. Ist das Signal 1, dann wurden die Daten im Puffer noch nicht vom Host abgeholt und es wird eine 0 zurück gegeben. |
* | usb_ep_packet_receive.c | - | void usb_ep_packet_receive(struct usb_ep *ep) - Die Funktion setzt das USB_CTRL_EN Bit des Endpunkts und signalisiert damit dem Host, das Daten empfangen werden können. |
* | usb_ep_wait_rxdata.c | - | int usb_ep_wait_rxdata(struct usb_ep *ep) - Die Funktion wartet bis Daten vom Host empfangen wurden und gibt dann die Anzahl der empfangenen Byte - 1 zurück. Die Bereischaft zum Empfang muss vorher dem Host durch Aufruf der Funktion void usb_ep_packet_receive(struct usb_ep *ep) signalisiert werden. |
* | usb_ep_packet_send.c | - | void usb_ep_packet_send(struct usb_ep *ep, unsigned int size) - Die Funktion setzt das USB_CTRL_EN Bit des Endpunkts und die Anzahl zu sendender Byte woraus der Host erkennt, das Daten abgolt werden müssen. |
* | usb_ep_wait_txready.c | - | void usb_ep_wait_txready(struct usb_ep *ep) - Die Funktion wartet bis der Host die Daten aus dem
Endpunkt abgeholt hat. Die Bereitschaft zum Senden muss vorher dem Host durch Aufruf der Funktion void usb_ep_packet_send(struct usb_ep *ep, unsigned int size) signalisiert werden. |
* | usb_ep_bufsel.c | - | void usb_ep_bufsel(struct usb_ep *ep, int buf_no) - Bei der Verwendung des Modes zur Doppelpufferung kann mit dieser Funktion zwischen den beiden Puffern umgeschaltet werden. Mit buf_no = 0 wird der 1. Puffer und mit buf_no = 1 der 2. Puffer aktiviert. Die Doppelpufferung kann nur mit einem Parameter bei der Erstellung der Konfiguration freigegeben werden. |
* | usb_ep_switch_buffer.c | - | void usb_ep_switch_buffer(struct usb_ep *ep) - Die Funktion hat die gleiche Aufgabe wie die vorherige
Funktion. Sie kann aber nur auf den zur Zeit nicht aktiven Puffer umschalten Bei der Verwendung des Modes zur Doppelpufferung kann mit dieser Funktion zwischen den beiden Puffern umgeschaltet werden. Die Doppelpufferung kann nur mit einem Parameter bei der Erstellung der Konfiguration freigegeben werden. |
* | usb_ep_get_buffer.c | - | volatile unsigned int *usb_ep_get_buffer(struct usb_ep *ep, unsigned int buf) - Die Funktion liefert die Adresse des aktiven Puffers für buf=0 oder die Adresse des passiven Puffes bei buf=1. Der aktive Puffer ist jeweils der der gerade vom Host gelesen oder geschrieben wird. Der passive Puffer kann bei Tx immer schon mit den nächsten Daten beschrieben werden. Bei Rx müssen im passiven Puffer die zuletzt empfangenen Daten abgeholt werden, während der Host bereits die nächsten Daten senden kann. |
* | USB_ENDPOINT( usb_base, ep_num) | - | Der Macro erstellt die Datensruktur usb_ep für jeden Endpunkt, wie er für die obigen Funktionen bei einfacher Pufferung benötigt wird. Die Makros werden in der usb.h deklariert. |
* | USB_ENDPOINT_DB( usb_base, ep_num) | - | Der Macro erstellt die Datensruktur usb_ep für jeden Endpunkt, wie er für die obigen Funktionen bei doppelter Pufferung benötigt wird. Die Makros werden in der usb.h deklariert. |
usb_init.h zur Vorinitialisierung der USB DMA Puffer.
usb.h und usb11.h mit der Struktur der DMA-Puffer.
Externe Dokumentationen
USB11 bei Open CoresWEB-Seiten mit Informationen zur Funktion des USB
http://www.sprut.de/electronic/interfaces/usb/usb.htm
http://www.usb.org/home
http://de.wikipedia.org/wiki/Universal_Serial_Bus
http://www.beyondlogic.org/usbnutshell/usb1.htm
http://mandalex.manderby.com/u/usb.php
Offene Fragen
* Ggf. Zusammenlegung der epXc- und epXs-Register (Pufferinhalt)