Forum: Mikrocontroller und Digitale Elektronik XMega DFU Bootloader startet USB nicht nach neuer Clock


von Emanuel L. (eleicht)


Lesenswert?

Hallo zusammen,

ich bin mit meinem Problem am Wissens- und Recherche-Ende, deshalb muss 
ich einen eigenen Thread dafür erstellen.

Folgender Stand:
Ich habe den Atmel DFU Bootloader am XMega256A3U erfolgreich zum laufen 
gebracht. Ich kann über Flip neue Software flashen, danach aus einem 
USB-Terminal einen Reset-Befehl eingeben, um in den Bootloader zu 
springen und dann mit Flip wieder neue Software flashen.

Das Problem:
Ich habe die ganze Clock-Initialisierung der Applikation inkl. 
sysclk_enable_usb und sysclk_disable_usb durch eigenen Code getauscht. 
Statt der ASF-Geschichte mit der 48 MHz Clock, die über ein USB-SoF 
getrimmt wird, läuft der uC jetzt mit 32 MHz clock, die mit dem internen 
32 kHz Oszi getrimmt wird.

Seitdem kann ich zwar das -erste- Mal mit Flip software flashen (ohne 
Applikation drauf), und meine Applikation scheint bei einem Boot-Befehl 
auch in den Bootloader zu springen (zumindest ist die Applikation tilt). 
Allerdings kann Flip danach jetzt keine USB-Verbindung mehr aufbauen, 
d.h. ein Update meiner Software ist unmöglich geworden.

Was ich nicht verstehe: Meine Änderungen am Applikations-Code sollten 
doch nicht die USB-Initialisierung des Bootloader beeinträchtigen, oder?

Die Fuses:
FF 00 BE F6 E3
(BOD 2,4V - Bootloader Reset)

Hier sind die Codes:

So gehts in den Bootloader (das hat bisher funktioniert!):
1
void(* jump_to_bootloader)(void) = (void (*)(void))(BOOT_SECTION_START/2 + 0x1FC/2);
2
3
// ... dann später:
4
udc_detach();
5
udc_stop();
6
        
7
EIND = BOOT_SECTION_START>>17;
8
jump_to_bootloader();

Die Init-Routine für meine Clock:
32 MHz Oszi mit internem 32 kHz kalibriert. Der 32 MHz Oszi ist dann 
Referenz für die PLL, mit der USB auf 48 MHz getrieben wird. Die 
Applikation funktioniert soweit einwandfrei.
1
void init_clock(void)
2
{  
3
  OSC.CTRL |= OSC_RC32MEN_bm;                        // enable the internal 32 MHz oscillator
4
  OSC.CTRL |= OSC_RC32KEN_bm;                        // enable the internal 32 kHz oscillator (RC oscillator for synchronisation purposes)
5
  
6
  //OSC.CTRL |= OSC_RC2MEN_bm;
7
8
  while(!(OSC.STATUS & OSC_RC32MRDY_bm));                  // wait for 32 MHz oscillator to stabilise (ready)
9
  while(!(OSC.STATUS & OSC_RC32KRDY_bm));                  // wait for 32 kHz oscillator to stabilise (ready)
10
11
  CCP = CCP_IOREG_gc;                            // protect I/O register      
12
  CLK.CTRL = CLK_SCLKSEL_RC32M_gc;                    // Use 32 MHz oscillator as system clock
13
  
14
  
15
  OSC.DFLLCTRL |= OSC_RC2MCREF_RC32K_gc;                  // Interal 32 kHz oscillator as reference for 32 MHz clock source
16
  OSC.DFLLCTRL |= OSC_RC32MCREF_RC32K_gc;                  // Internal 32 kHz oscillator as reference for 32 MHz clock source
17
  
18
  // Setting this bit enables the DFLL and auto-calibration of the internal oscillator.
19
  // The reference clock must be enabled and stable before the DFLL is enabled.
20
  DFLLRC32M.CTRL |= DFLL_ENABLE_bm;  
21
}

1
void sysclk_enable_usb(uint8_t frequency)
2
{
3
  uint8_t prescaler;
4
  /*
5
   * Enable or disable prescaler depending on if the USB frequency is 6
6
   * MHz or 48 MHz. Only 6 MHz USB frequency requires prescaling.
7
   */
8
  if (frequency == 6) {
9
    prescaler = CLK_USBPSDIV_8_gc;
10
  }
11
  else {
12
    prescaler = 0;
13
  }
14
  
15
  // PLL for USB
16
  OSC.PLLCTRL = OSC_PLLSRC_RC32M_gc;                    // PLL source = 32 MHz oscillator/4 (always /4 by hardware)
17
  OSC.PLLCTRL |= OSC_PLLFAC2_bm | OSC_PLLFAC1_bm;              // PLL multiply by 6 --> 32 MHz / 4 x 6 = 48 MHz for full speed USB
18
  
19
  OSC.CTRL |= OSC_PLLEN_bm;                        // Enable PLL
20
  while(!(OSC.STATUS & OSC_PLLRDY_bm));                  // wait for PLL to stabilise (ready)
21
  
22
  CCP = CCP_IOREG_gc;
23
  CLK.USBCTRL = (CLK_USBSRC_PLL_gc | CLK_USBSEN_bm | prescaler);      // USB clock source: PLL, clock enable, prescaler
24
                                        // Using 32 MHz oscillator with 48 MHz calibration values only works with USB connected (USB Start of Frame, SOF).
25
                                        // Device MUST be accurate for 1 Mb UART baud without USB, so 32 MHz have to be calibrated via 32 kHz clock
26
  *((uint8_t *)&PR.PRGEN) &= ~PR_USB_bm;
27
}
28
29
30
/**
31
 * \brief Disable clock for the USB module
32
 */
33
void sysclk_disable_usb(void)
34
{
35
  *((uint8_t *)&PR.PRGEN) |= PR_USB_bm;
36
  CCP = CCP_IOREG_gc;
37
  CLK.USBCTRL = 0;
38
}

von Thomas S. (thomasschattat)


Lesenswert?

Hallo Emanuel,
eventuell ist mein alter Thread hierinteressant:

Beitrag "RTC an XMEGA Hilfe!!"

Mein Problem seinerzeit war, dass meine RTC nicht mehr tickt wenn ich im 
Bootloader den Takt (meiner war 2MHz seinerzeit) mit dem 32KHz 
Uhrenquarz kalibriere.

Ich hab den BL XBOOT dann hergenommen und die Kalibrierung manuell 
einschaltbar gemacht per Taster der eh da war.
Hintergrund war: Mit Kalib ging meine Applikation nicht mehr, RTC war 
tot nach BL Ende.

Also drücke ich einen Taster wenn XBOOT startet, der Quarz korrigiert 
die 2MHz so dass die serielle Schnittstelle richtig funktioniert, XBOOT 
lädt die neue Version und das Ding hängt fest.

Dann mache ich alles stromlos, starte erneut und drücke den Taster 
NICHT.
Keine Kalibrierung des Systemtaktes -> kein Problem, BL, Applikation und 
alles läuft.

Ich hatte den Eindruck dass das ein Bug im XMEGA ist, hab es aber nie 
weiter verfolgt.
Versuche mal nur die Kalibrierung weg zu nehmen, eventuell löst das das 
Problem.
Gruß

Thomas

von Emanuel L. (eleicht)


Lesenswert?

Thomas S. schrieb:
> Hallo Emanuel,
>[...]
> Versuche mal nur die Kalibrierung weg zu nehmen, eventuell löst das das
> Problem.
> Gruß
>
> Thomas

WOW!
Das hätte ich -niemals- herausgefunden ohne diese Hilfe - Danke!
Direkt vor dem Sprung in den Bootloader deaktiviere ich einfach die 
Kalibrierung über
1
DFLLRC32M.CTRL &= ~(DFLL_ENABLE_bm);

Und siehe da, es funktioniert wieder, wie es soll. Und ich hatte schon 
gedacht, dass ich nie das Detail heraus finden werde, an dem es hakte.

Ein riesiges Dankeschön an Dich!

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.