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:

USB-Anschluss
Der 1,5K Widerstand(external link) 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 (external link) zur Vorinitialisierung der USB DMA Puffer.

usb.h und usb11.h (external link) mit der Struktur der DMA-Puffer.

Externe Dokumentationen

USB11 bei Open Cores (external link)

WEB-Seiten mit Informationen zur Funktion des USB

http://www.sprut.de/electronic/interfaces/usb/usb.htm (external link)
http://www.usb.org/home (external link)
http://de.wikipedia.org/wiki/Universal_Serial_Bus (external link)
http://www.beyondlogic.org/usbnutshell/usb1.htm (external link)
http://mandalex.manderby.com/u/usb.php (external link)
Offene Fragen

* Ggf. Zusammenlegung der epXc- und epXs-Register (Pufferinhalt)





SpartanMC