Hi,
ich beziehe mich wieder auf das XMega-USB-Projekt hier:
Beitrag "CDC für xmega"
Ich versuche seit zwei Wochen, den Code von woodym zu verstehen, und bin
für meine Verhältnisse sogar relativ weit gekommen. Aber... Testweise
habe ich den Code mal auf ein Minimum reduziert, weil bei meinem eigenen
Projekt der "Transaction Complete Interrupt" ISR(USB_TRNCOMPL_vect) nie
getriggert wurde. Soll heißen, mein eigener Versuch scheiterte schon
unnötig früh.
Dabei habe ich diese Zeile hier als Auslöser dafür gefunden, ob der
Interrupt anspringt oder nicht:
Nicht dass ich verstehen würde, was diese Zeile genau macht, aber sie
soll wohl den Speicherbereich in Chunks zu 2 Byte organisieren,
unabhängig davon, ob gerade uint8_t oder ein uint16_t gespeichert wird.
Ich habe den Code in mehreren Schritten und Versionen reduziert, und
seltsamerweise funktioniert in manchen Fällen das Programm nur mit und
manchmal auch ohne "GCC_FORCE_ALIGN_2".
Als ersten Versuch möchte ich euch erstmal ersparen, dass ich meinen
gesamten Code poste.
Kann sich vielleicht jemand einen Zusammenhang vorstellen, warum der
Interrupt nicht getriggert wird, wenn diese Zeile fehlt? Im Manual steht
meiner Meinung nichts davon drin, dass Endpunkt auf diese Weise
organisiert werden müssen.
Vielen Dank schon mal!
Peder schrieb:> Hier wird nach meinem Verständnis Speicher für 16 Endpunkt-Paare> reserviert. (...)> Nicht dass ich verstehen würde, was diese Zeile genau macht, aber sie> soll wohl den Speicherbereich in Chunks zu 2 Byte organisieren,
Der Speicherblock wird auf eine 16-Bit-Grenze ausgerichtet oder für den
hippen Neusprachler: "aligned". :-)
Guck doch einfach mal in das Datenblatt, z.B. XMEGA AU [MANUAL]:
"20.14.7 EPPTRL – Endpoint Configuration Table Pointer Low
The EPPTRL and EPPTRH registers represent the 16-bit value, EPPTR, that
contains the address to the endpoint configuration table. The pointer to
the endpoint configuration table must be aligned to a 16-bit word; i.e.,
EPPTR[0] must be zero."
Ich käme jetzt nicht auf die Idee, den Speicherbereich anders
auszurichten und zu hoffen, dass das trotzdem funktioniert.
Grüßle,
Volker
Oh wow, danke! Das macht auf einmal vielmehr Sinn. Ich kannte das
Alignment-Konzept bis dahin noch nicht, und dementsprechend hab ich das
wahrscheinlich als "hoffentlich unnötig" überlesen.
Und das erklärt dann wahrscheinlich auch, warum das manchmal
funktioniert hat und manchmal nicht: weil sich je nach Änderung im Code
manchmal irgendeine 8-Bit-Variable dazwischen schiebt.
Vielleicht noch eine Frage zum Verständnis: Wird nur der Speicher-Block
selbst ausgerichtet oder werden auch darin enthaltene 8-Bit-große
Variablen auf 16 Bit "gestreckt"? Dann hätte ich das nämlich genau
falsch herum verstanden.
Peder schrieb:> Vielleicht noch eine Frage zum Verständnis: Wird nur der Speicher-Block> selbst ausgerichtet oder werden auch darin enthaltene 8-Bit-große> Variablen auf 16 Bit "gestreckt"
Hier geht's nur um den Pointer auf den RAM-Bereich mit der "endpoint
configuration table". Das hat vermutlich etwas damit zu tun, wie das
USB-Interface auf das RAM zugreift. Genaues weiß ich aber nicht.
Ich würde vermuten, dass der Inhalt der Tabelle vom USB-Standard
vorgegeben ist, habe mich aber bislang noch nicht im Detail damit
beschäftigt.
Grüßle,
Volker
Meine Frage bezog sich eher auf C und "align" selbst, gar nicht mal mehr
bezogen auf Mikrocontroller. Wie dieser Speicherblock aussieht, steht im
XMega-Manual.
Und da sich dort 8-Bit- and 16-Bit-Variablen aneinanderreihen, wollte
ich wissen, ob ein "align" nur den Beginn des genannten Speicherblocks
ans n*byte-Raster anpasst oder ob der Inhalt dieses Blocks auch an
dieses Raster angepasst wird. (was sich meiner Meinung nach mit der
Angabe im Manual beißen würde)
Sprich, wenn es sich z.B. um eine struct handelt mit 8-Bit- und
16-Bit-Membern, werden die 8-Bit-Member auf 16-Bit aufgeweitet?
Peder schrieb:> Meine Frage bezog sich eher auf C und "align" selbst, gar nicht mal mehr> bezogen auf Mikrocontroller.
M.W. richtet ein C-Compiler die Elemente einer struct entsprechend den
"Vorlieben" der MCU aus, also auf char bei einer 8-Bit MCU, short bei
einer 16-bittigen und long bei einer 32-bittigen.
Wenn er das nicht machen soll, muss man ihn explizit dazu anweisen die
struct zu "packen", bei gcc mittels "__attribute__ ((packed))"
> Wie dieser Speicherblock aussieht, steht im XMega-Manual.
...und was lesen wir aus Figure 20-6. SRAM memory mapping: Jedes Element
liegt an einer Byte-Grenze und die Elemente sind so geschickt
angeordnet, dass das LowByte einer 16-Bit-Variablen an einer geraden
Adresse beginnt, wie z.B. DATAPTRL.
> Und da sich dort 8-Bit- and 16-Bit-Variablen aneinanderreihen,
Wo siehst Du da 16-Bit-Variablen? Ich sehe nur 8-bittige.
> wollte> ich wissen, ob ein "align" nur den Beginn des genannten Speicherblocks> ans n*byte-Raster anpasst oder ob der Inhalt dieses Blocks auch an> dieses Raster angepasst wird. (was sich meiner Meinung nach mit der> Angabe im Manual beißen würde)
Das musst Du bei der Definition der jeweiligen struct angeben, s.o.
Warum machst Du es nicht einfach so wie in dem von Dir verwendeten
Beispielcode? Ich versteh' Deine Probleme nicht.
Grüßle,
Volker
Volker B. schrieb:> Wo siehst Du da 16-Bit-Variablen? Ich sehe nur 8-bittige.
Ich hab H&L-Paare jeweils als 16-Bit-Variable betrachtet. Und so wie ich
das sehe, tut das auch die Definition eines Endpunktes durch Microchip
selbst in der io256a3u.h (auch wenn _WORDREGISTER wiederum nur eine
struct aus zwei 8-Bit-Variablen ist):
1
typedefstructUSB_EP_struct
2
{
3
register8_tSTATUS;/* Endpoint Status */
4
register8_tCTRL;/* Endpoint Control */
5
_WORDREGISTER(CNT);/* USB Endpoint Counter */
6
_WORDREGISTER(DATAPTR);/* Data Pointer */
7
_WORDREGISTER(AUXDATA);/* Auxiliary Data */
8
}USB_EP_t;
Volker B. schrieb:> Warum machst Du es nicht einfach so wie in dem von Dir verwendeten> Beispielcode?
Weil ich ursprünglich meinen eigenen Ansatz erstellen wollte und dann
durch Reverse-Engineering verstehen wollte, warum der nicht mal bis zum
Interrupt kommt. Mein eigener Ansatz deshalb, weil ich eine andere
USB-Klasse brauche, weil ich was lernen möchte und weil ich ungern Code
benutze, den ich nicht verstehe. Ich hätte mir das Leben bestimmt
leichter machen können, ja.
Ich denke, es ist mittlerweile klar, dass ich mit Programmieren nicht
meinen Lebensunterhalt verdiene. ;) Deshalb nochmal vielen Dank für
deine Hilfe!