Forum: Compiler & IDEs Xmega mit USB on board


von Daniel Held (Gast)


Lesenswert?

Hallo Forum,

ich probiere gerade den ATxmega128A3U mit USB vernünftig zu laufen zu 
bekommen und nutze als Grundlage Beispiele aus dem ASF.
Als erstes soll der xmega als cdc device arbeiten und hier tauchen schon 
die ersten Probleme auf. Sobald eine zu große Datenmenge (>320Byte) in 
die Routine "udi_cdc_write_buf" geschrieben wird bleibt der xmega in der 
"udi_cdc_multi_is_tx_ready" Schleife des ASF-Codes hängen. Anscheinend 
passiert das, wenn der Buffer überläuft bzw. die neue Nachricht nicht 
hineinpasst.
Die einzelnen Aufrufe umfassen jeweils 22Byte Daten und der Buffer fasst 
320Byte. Vielleicht liegt es auch am leeren des Buffers durch den Stack?

Hatte jemand schon dieses Problem und weiß evtl. Rat?

Aufruf:
1
  while (GetLog(&Log) == 1)
2
  {
3
    count++;
4
    sprintf(TransferString, "Test %02d.%02d.%02d.%02d.%02d" , Log.DateTime.Day, Log.DateTime.Month, Log.DateTime.Year, Log.DateTime.Hour, Log.DateTime.Minute); 
5
    if (!udi_cdc_is_tx_ready())
6
    {
7
      udi_cdc_signal_overrun();
8
    }
9
    else
10
    {
11
      udi_cdc_write_buf(TransferString, sizeof(TransferString));
12
    }
13
14
  }return count;

die write Funktion des ASF:
1
iram_size_t udi_cdc_multi_write_buf(uint8_t port, const int* buf, iram_size_t size)
2
{
3
  irqflags_t flags;
4
  uint8_t buf_sel;
5
  uint16_t buf_nb;
6
  iram_size_t copy_nb;
7
  uint8_t *ptr_buf = (uint8_t *)buf;
8
9
  if (9 == udi_cdc_line_coding[PORT].bDataBits) {
10
    size *=2;
11
  }
12
// hier die dann entstehende Endlosschleife
13
14
udi_cdc_write_buf_loop_wait:
15
  // Check avaliable space
16
  if (!udi_cdc_multi_is_tx_ready(PORT)) {
17
    if (!udi_cdc_running[PORT]) {
18
      return size;
19
    }
20
    goto udi_cdc_write_buf_loop_wait;
21
  }
22
23
  // Write values
24
  flags = cpu_irq_save();
25
  buf_sel = udi_cdc_tx_buf_sel[PORT];
26
  buf_nb = udi_cdc_tx_buf_nb[PORT][buf_sel];
27
  copy_nb = UDI_CDC_TX_BUFFERS - buf_nb;
28
  if (copy_nb>size) {
29
    copy_nb = size;
30
  }
31
  memcpy(&udi_cdc_tx_buf[PORT][buf_sel][buf_nb], ptr_buf, copy_nb);
32
  udi_cdc_tx_buf_nb[PORT][buf_sel] = buf_nb + copy_nb;
33
  cpu_irq_restore(flags);
34
35
  // Update buffer pointer
36
  ptr_buf = ptr_buf + copy_nb;
37
  size -= copy_nb;
38
39
  if (size) {
40
    goto udi_cdc_write_buf_loop_wait;
41
  }
42
43
  return 0;
44
}

von Basti M. (counterfeiter)


Lesenswert?

Hatte ich schon öfter, aber nur wenn am anderen Ende das 
Terminalprogramm nicht geöffnet war...

In der ASF wird dafür eine globale Variable in den USB Interrupts 
beschrieben... Die sollte man dann vor dem Senden prüfen...
Das udi_cdc_is_tx_ready() kannste dir glaube ich sparen... hatte ich 
jedenfalls noch nicht benutzen müssen..

von Daniel Held (Gast)


Lesenswert?

Hallo Basti,
danke Dir für den Tip - den Namen der Variable hast Du nicht zufällig 
parat, oder?
Daniel

von Basti M. (counterfeiter)


Lesenswert?

der ist ja variabel ;)

-> main_b_cdc_enable

von Daniel Held (Gast)


Lesenswert?

Hallo Basti,
Ah OK. Diese Callback hatte ich auch schon gefunden.
Das Problem ist, dass der PC schon noch verbunden ist, aber wohl der 
xmega die Daten nicht schnell genug aus dem Buffer sendet. So läuft 
dieser voll und die Endlosschleife beginnt. Vielleicht kann man auch den 
verfügbaren Platz im Buffer abfragen?
Du hattest doch die GPS Sache gebaut, oder?

Danke
Daniel

von Bassti (Gast)


Lesenswert?

ja, hab ich...

In dem GPS Projekt habe ich ein MB in 5 Sekunden übertragen (SPI zu USB 
ohne DMA)(wenn mir das richtig in Erinnerung ist). Kann nicht behaupten 
das da was übergelaufen wäre.

Habe aber auch schon angefangen ein paar Funktionen der ASF im Bezug auf 
USB umzuschreiben. Da ging es aber eher um die Receive-Funktionen...

Was fast immer schief geht, sich debuggend durchs USB Programm zu 
bewegen... da stürtzt dann meist was ab... vielleicht haste auch 
irgendwo mal angehalten... dann wird das keine Runde sache...

von Bassti (Gast)


Lesenswert?

Achso, und wenn der Takt nicht auf USB Kalibriert ist oder von nem 
genauen Quarz kommt, dann kann es sein das USB sich bei bestimmten 
Zeichenfolgen aufhängt. Da habe ich auch schon mal ewig gesucht...

Versuch mal keine 0 Zeichen oder what ever mit zu senden indem du den 
hier machst:

 udi_cdc_write_buf(TransferString, strlen(TransferString));

Wenn das Problemlos geht, schau dir mal die Taktversorgung an...


Grüße

Basti

von Daniel Held (Gast)


Lesenswert?

OK.
Das der Debugger mit USB nicht funzt ist mir auch schon aufgefallen, das 
hängt aber am USB Host, wenn der nicht kommunizieren kann beendet er die 
Verbindung. Der Takt ist auf USB kalibriert kommt aber vom internen 
32MHz Oszi.
Das komische ist, wenn ich in der while-Schleife mein log auslese und 
die Summe der Zeichen (Einträge im Log * Länge des Transferstring) 
kleiner als 320 Bytes ist funktioniert es problemlos, auch bei 
mehrmaligen aufeinander folgenden Aufrufen. Als Transferstring habe ich 
auch schon eine feste Zeichenkette mit exakter Länge definiert, da ist 
aber das gleiche Problem.
Ich weiß auch nicht...

von Bassti (Gast)


Lesenswert?

Hm, keine Idee mehr... evtl mal ne neue oder ne ältere ASF probieren...

Hier mal noch die clock settings:
1
//#define CONFIG_SYSCLK_SOURCE          SYSCLK_SRC_RC2MHZ
2
#define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_RC32MHZ
3
//#define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_RC32KHZ
4
//#define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_XOSC
5
//#define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_PLL
6
7
#define CONFIG_OSC_AUTOCAL        OSC_ID_RC32MHZ
8
#define CONFIG_OSC_AUTOCAL_REF_OSC    OSC_ID_USBSOF
9
//#define CONFIG_OSC_AUTOCAL_REF_OSC    OSC_ID_RC32KHZ
10
11
/* Fbus = Fsys / (2 ^ BUS_div) */
12
#define CONFIG_SYSCLK_PSADIV          SYSCLK_PSADIV_2
13
#define CONFIG_SYSCLK_PSBCDIV         SYSCLK_PSBCDIV_1_1
14
15
#define CONFIG_USBCLK_SOURCE    USBCLK_SRC_RCOSC
16
#define CONFIG_OSC_RC32_CAL      48000000UL

von Daniel Held (Gast)


Lesenswert?

Ich stelle erst einmal die clock auf einen externen Quarz um.
Welche ASF-Version nutzt Du? Ich habe jetzt hier die 3.1.3.

von Daniel Held (Gast)


Lesenswert?

Das Umstellen der clock auf einen externen Quarz hat nichts gebracht :-(

von Daniel Held (Gast)


Lesenswert?

Das Problem wurde gefunden :-)

Auf keinen Fall dürfen längere Operationen in den Callbacks erfolgen, 
die blocken die Interrupts des USB-Stacks.
Hätte ich auch früher drauf kommen können...

von Bassti (Gast)


Lesenswert?

na zum Glück hast du nicht lange gesucht ;)

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.