Forum: Mikrocontroller und Digitale Elektronik XMEGA USB - ISR "TRNCOMPL" triggert nicht


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Peder (st_peter)


Lesenswert?

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:
1
USB_EP_pair_t endpoints[USB_DEF_EP_MAX] GCC_FORCE_ALIGN_2;

Hier wird nach meinem Verständnis Speicher für 16 Endpunkt-Paare 
reserviert. "GCC_FORCE_ALIGN_2" ist so definiert:
1
#define GCC_FORCE_ALIGN_2  __attribute__((section (".data,\"aw\",@progbits\n.p2align 1;")))

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!

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

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

: Bearbeitet durch User
von Peder (st_peter)


Lesenswert?

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.

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

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

von Peder (st_peter)


Lesenswert?

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?

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

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

: Bearbeitet durch User
von Peder (st_peter)


Lesenswert?

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
typedef struct USB_EP_struct
2
{
3
    register8_t STATUS;  /* Endpoint Status */
4
    register8_t CTRL;  /* 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!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.