STM32: CAN Loopback mit merkwürdigem Effekt

Gast #1972014
Lesenswert?

Hi,
als frischgebackener Besitzer eines STM32F103 Stamp Moduls ich habe das 
CAN Loopback Beispiel aus der ST Standard Lib (3.4.0) ausprobiert und 
bin dabei auf einen merkwürdigen Effekt gestoßen.

Im Loopback-Modus kann man die CAN-Nachrichten auf dem Tx-Pin mitlesen.
(Der ganze Quellcode ist im Attachment)
Ich habe dafür wie folgt initialisiert:
1
    GPIO_InitTypeDef  GPIO_InitStructure;
2

3
    /* GPIO clock enable */
4
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |RCC_APB2Periph_GPIO_CAN, ENABLE);
5

6
    /* Configure CAN pin: RX */
7
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_CAN_RX;
8
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
9
    GPIO_Init(GPIO_CAN, &GPIO_InitStructure);
10

11
    /* Configure CAN pin: TX */
12
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_CAN_TX;
13
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
14
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
15
    GPIO_Init(GPIO_CAN, &GPIO_InitStructure);
16

17
    GPIO_PinRemapConfig(GPIO_Remap_CAN , ENABLE);
An Pin 9 (Port B) kann ich dann das Tx-Signal auslesen.

Dann wird das CAN-Polling ausgeführt, danach die Interrupt-basierte 
CAN-Übertragung. Im Referenzbeispiel sind die Funktionen bereits 
ausformuliert.

Der Erfolg der CAN-Übertragungen soll über zwei LED's, der Mißerfolg 
über eine dritte LED angezeigt werden.
Beispiel für die "Erfolg"-LED bei CAN-Loopback:
1
  /* activating peripheral port A */
2
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
3

4
    /* setup Port 7 for Ports A as output with 2MHz clock: */
5
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
6
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
7
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
8
    GPIO_Init(GPIOA, &GPIO_InitStructure);
9

10
    GPIOA->BSRR  = GPIO_Pin_7; /* LED On */
Bei einem Erfolg des CAN-Interrupt-Beispiels soll die LED an PortA, Pin7 
angehen. Der Fehler wird angezeigt durch eine LED auf Port C an Pin 7:
1
      /* activating peripheral port C */
2
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
3

4
    /* setup Port 7 for Ports A as output with 2MHz clock: */
5
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
6
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
7
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
8
    GPIO_Init(GPIOC, &GPIO_InitStructure);
9

10
    GPIOC->BSRR  = GPIO_Pin_7; /* LED On */

Wo ist nun das Problem:

Beim ersten Start nach dem Flashen klappt die CAN-Übertragung- Moment: 
das CAN-Empfang via Interrupt klappt schon nicht mehr, aber immerhin 
CAN-Polling.
Damit es am Oszilloskop ordentlich was zu sehen gibt, wird die Funktion 
CAN-Interrupt-Testfunktion endlos aufgerufen. Leider wird nichts über 
die ISR empfangen (kein Einsprung), aber die Pakete gehen raus (man 
sieht es auf dem DSO).

Wenn ich nun auf den Reset-Button gehe und das Programm neue starte, 
gibt es keine Pakete mehr zu sehen, ja sogar die Funktion CAN-Polling 
geht nicht.
Wenn ich spaßeshalber das Remapping der CAN-Pins weglasse und 
neuprogrammiere, zeigt die LED Erfolg für das Polling an. Ein 
Wiedereinführen des Remapping zaubert wieder die Pakete auf das DSO - 
bis zum nächsten Reset.
Wenn ich den Strom für 30s aus und dann wieder einschalte, geht es immer 
noch nicht: Der Tx-Pin zeigt konstant '1' Pegel.

Meine Vermutung: irgendwelche Settings stimmen nach dem Reset nicht und 
werden merkwürdigerweise im Programm nicht richtig gesetzt.
Kann mir jemand helfen?
Grüße
schnack
Angehängte Dateien:
#1972150
Lesenswert?

STMF32F103 ist eim Medium-Device. Dein Startup sieht nach einem 
XL-Device aus. Könnte sein, dass die Interruptvektoren oder was anderes 
im Startup nicht passt.

Was hast Du für eine CAN Infrastruktur dran oder nur den Loopback?

Ansonsten laufen eigentlich bei mir die 2 Beispiele der FW-Lib 3.4.0. 
Dort wird aber von weiteren bereits erfolgten Routinen zur 
Initialisierung (EVA-Bords) ausgegangen. Kann bei Dir zB. keine 
Systeminits, wie Takt, PLL, ABP-Takte usw. finden, oder übersehen?

Nochwas. Bei den 103ern geht USB und CAN nicht gemeinsam. Diese 
Erkenntnis hatte ich auch zunächst im Datasheet überlesen.
Gast #1972249
Lesenswert?

Hi Matthias,
auf dem Stamp ist ein STM32F103RET6 verbaut mit immerhin 512KB Flash.
Laut Referenz-Manual ein High Density Device:

● High-density devices are STM32F101xx and STM32F103xx microcontrollers 
where
the Flash memory density ranges between 256 and 512 Kbytes.
● XL-density devices are STM32F101xx and STM32F103xx microcontrollers 
where the Flash memory density ranges between 768 Kbytes and 1 Mbyte.

Damit liege ich mit meiner Definition im Makefile:
1
SYMBOLS  = -DSTM32F10X_XL
auf jeden Fall falsch - danke!

Die CAN-Struktur ist bislang nur ein Loopback zum "Mithören". In einem 
zweiten Schritt wollte ich es an ein bestehendes Netz anschließen.

Die Takte werden in der system_stm32f10x.c definiert - hier ist z.B. die 
SystemInit.

Ich werde gleich mal prüfen, was die Definition als High Density Device 
liefert.
Grüße
schnack
#1972306
Lesenswert?

>/*!< At this stage the microcontroller clock setting is already
> configured, this is done through SystemInit() function which is
> called from startup file (startup_stm32f10x_xx.s) before to branch to
> application main. To reconfigure the default setting of SystemInit()
> function, refer to system_stm32f10x.c file */

Aber wo rufst Du es auf?

Ruf am Anfang mal diese beiden Routinen auf:
1
//***********************************************************************************************
2
// System-Einstellungen
3
//***********************************************************************************************
4
void SetupSystem (void) {
5

6
  RCC_DeInit ();                        // RCC System Reset(for debug purpose)
7

8
  // Enable HSE (Umschaltung auf externen Quarz)
9
  RCC_HSEConfig (RCC_HSE_ON);
10

11
  // HSE-Umschaltung abwarten
12
  while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
13

14
  // System-Taktung
15
  RCC_HCLKConfig   (RCC_SYSCLK_Div1);   // HCLK   = SYSCLK
16
  RCC_PCLK2Config  (RCC_HCLK_Div1);     // PCLK2 (APB2) = HCLK
17
  RCC_PCLK1Config  (RCC_HCLK_Div2);     // PCLK1 (APB1) = HCLK/2
18

19
  // FLASH-Speicher Zugriffstechnik
20
  FLASH_SetLatency(FLASH_Latency_2);                        // Flash - 2 wait states
21
  FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);     // Pipeline freigeben
22
  
23
  // PLL Konfiguration
24
  // PLLCLK = 8MHz * 9 = 72 MHz
25
  RCC_PLLConfig (RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);     // Externer Quarz, Faktor 9
26
  RCC_PLLCmd (ENABLE);                                      // Enable PLL
27

28
  // PLL-Konfiguration abwarten
29
  while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
30

31
  // PLL als System-Takt auswählen
32
  RCC_SYSCLKConfig (RCC_SYSCLKSource_PLLCLK);
33

34
  // PLL-Umschaltung abwarten
35
  while (RCC_GetSYSCLKSource() != 0x08);
36
}
37

38
//***********************************************************************************************
39
// Nested Vectored Interrupt Controller initialisieren
40
//***********************************************************************************************
41
void NVIC_Configuration(void) {
42

43
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); // FLASH Vector Table ab 0x08000000 (Default)
44

45
}
Gast #1972308
Lesenswert?

Hi,
also:
* die Definition habe ich geändert.
* außerdem hatte ich die startup_stm32f10x_xl.s statt 
startup_stm32f10x_hd.s gewählt (darauf hast Du Dich vermutlich 
bezogen..)

Beides war falsch und beides habe ich korrigiert. Aber das war es leider 
nicht. Weiterhin habe ich diesen "merkwürdigen" Effekt. Ich prüfe jetzt 
auch, ob der Code zum Init der eval-Boards noch mehr enthält.
Grüße
schnack
Gast #1972318
Lesenswert?

Hi Matthias,
ok- ich bin kein Assembler-Experte. Mein Verständnis ist, daß die 
Syteminit() im Reset-Handler aufgerufen wird.
Aus dem Assembler-File startup_stm32f10x_hd.s:
1
    .section  .text.Reset_Handler
2
  .weak  Reset_Handler
3
  .type  Reset_Handler, %function
4
Reset_Handler:  
5

6
/* Copy the data segment initializers from flash to SRAM */  
7
  movs  r1, #0
8
  b  LoopCopyDataInit
9

10
CopyDataInit:
11
  ldr  r3, =_sidata
12
  ldr  r3, [r3, r1]
13
  str  r3, [r0, r1]
14
  adds  r1, r1, #4
15
    
16
LoopCopyDataInit:
17
  ldr  r0, =_sdata
18
  ldr  r3, =_edata
19
  adds  r2, r0, r1
20
  cmp  r2, r3
21
  bcc  CopyDataInit
22
  ldr  r2, =_sbss
23
  b  LoopFillZerobss
24
/* Zero fill the bss segment. */  
25
FillZerobss:
26
  movs  r3, #0
27
  str  r3, [r2], #4
28
    
29
LoopFillZerobss:
30
  ldr  r3, = _ebss
31
  cmp  r2, r3
32
  bcc  FillZerobss
33
/* Call the clock system intitialization function.*/
34
  bl  SystemInit   
35
/* Call the application's entry point.*/
36
  bl  main
37
  bx  lr    
38
.size  Reset_Handler, .-Reset_Handler
Am Ende ruft er SystemInit() und dann main() auf. Wenn er das nicht 
täte,
dürfte ja doch gar nichts funktionieren- oder?


Grüße
schnack
Gast #1972353
Lesenswert?

Hallo,
der Effekt tritt differenzierter auf, als ich bisher bemerkt habe: wenn 
ich das Target via JLINK flashe und starte, klappt das CAN-Polling mit 
Remap - aber nicht nach einem Reset (wie oben beschrieben)
Wenn ich dagegen mit dem STMFlashLoader via USART flashe, tritt der 
Fehler sofort auf.
Offenbar "verbessert" der JLINK die Lage etwas...
Gast #1972479
Lesenswert?

Hi Matthias,
so ganz ist mir das nicht klar: Die SetupSystem() habe ich in den 
Sourcen nicht gefunden. Aber ich habe in der system_stm32f10x.c die 
Funktion SetSysClockTo72() gefunden. Diese scheint gerade die Settings 
Deiner SetupSystem() zu wählen (s.u.). Diese Funktion wird wiederum in 
der SystemInit durch
1
(...)
2
  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
3
  /* Configure the Flash Latency cycles and enable prefetch buffer */
4
  SetSysClock();
5
 (...)

aufgerufen. Ich habe den Eindruck, daß alle Takte laufen - so wie es 
sein soll. Da ich ja via JLINK zumindest initial die CAN-Frames sehen 
kann, hoffe ich, daß es irgendein Detail ist, was noch fehlt.
1
static void SetSysClockTo72(void)
2
{
3
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
4
  
5
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
6
  /* Enable HSE */    
7
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
8
 
9
  /* Wait till HSE is ready and if Time out is reached exit */
10
  do
11
  {
12
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
13
    StartUpCounter++;  
14
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
15

16
  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
17
  {
18
    HSEStatus = (uint32_t)0x01;
19
  }
20
  else
21
  {
22
    HSEStatus = (uint32_t)0x00;
23
  }  
24

25
  if (HSEStatus == (uint32_t)0x01)
26
  {
27
    /* Enable Prefetch Buffer */
28
    FLASH->ACR |= FLASH_ACR_PRFTBE;
29

30
    /* Flash 2 wait state */
31
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
32
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    
33

34
 
35
    /* HCLK = SYSCLK */
36
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
37
      
38
    /* PCLK2 = HCLK */
39
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
40
    
41
    /* PCLK1 = HCLK */
42
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
43

44
#ifdef STM32F10X_CL
45
    /* Configure PLLs ------------------------------------------------------*/
46
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
47
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
48
        
49
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
50
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
51
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
52
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
53
  
54
    /* Enable PLL2 */
55
    RCC->CR |= RCC_CR_PLL2ON;
56
    /* Wait till PLL2 is ready */
57
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
58
    {
59
    }
60
    
61
   
62
    /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
63
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
64
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
65
                            RCC_CFGR_PLLMULL9); 
66
#else    
67
    /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
68
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
69
                                        RCC_CFGR_PLLMULL));
70
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
71
#endif /* STM32F10X_CL */
72

73
    /* Enable PLL */
74
    RCC->CR |= RCC_CR_PLLON;
75

76
    /* Wait till PLL is ready */
77
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
78
    {
79
    }
80
    
81
    /* Select PLL as system clock source */
82
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
83
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    
84

85
    /* Wait till PLL is used as system clock source */
86
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
87
    {
88
    }
89
  }
90
  else
91
  { /* If HSE fails to start-up, the application will have wrong clock 
92
         configuration. User can add here some code to deal with this error */
93
  }
94
}
95
#endif
#1973213
Lesenswert?

Habe ich auch keine wirkliche Idee mehr. Bist Du sicher, dass das 
Startup .s zu win-arm passt? In Bsp. sehen die dort anderes aus. Mit 
Keil laufen auf jedem Fall die Startups der STM FW-Lib. Mit dem 
AtollicTrue Studio gehen die nicht, basiert auch auf Win-Arm.

Hast Du ein Blinky schon mal einwandfrei zum laufen gebracht?

Oder lade Dir mal zum testen die Keil MDK EVA-Version runter.
http://www.keil.com/arm/mdk.asp
Gast #1973254
Lesenswert?

Hi Matthias,
danke für Deine Unterstützung!
Ja, die blinkende LED läuft einwandfrei. Inzwischen habe ich den Fehler 
einkreisen können. Erstmal habe ich die Takterzeugung für die Periperie 
angepaßt und die Frameerzeugung klappt nun stabil (auch nach Reset). Ich 
kann jetzt auf beiden CAN-Ports je nach Remap die CAN-Frames (am TX-Pin) 
sehen- dafür gibt es folgenden Endlos-Code:
1
  TestRx = CAN_Polling();
2

3
  /* CAN transmit at 500Kb/s and receive by interrupt in loopback mode */
4

5
while (1) {
6
  TestRx = CAN_Interrupt();
7

8

9
  if (TestRx == SUCCESS)
10
        success2();
11

12

13
  miniDelayLoop(); // winziger Delay
14
}

Wobei zu beachten ist, daß das Interrupt-Handling nicht aktiviert ist.
Sobald ich im Code (davor) die Funktion NVIC_Configuration() starte, 
gibt es keine Frames mehr. Ich kann nur vermuten, daß ich beim 
Konfigurieren des Interrupts den Prozessor einen Fehler mache und beim 
Auftreten des Interrupts läuft er in die Pampa. Der Interrupt 
USB_LP_CAN1_RX0_IRQn hat aber bei allen Devices (, die CAN unterstützen) 
den gleichen Index:
1
 USB_LP_CAN1_RX0_IRQn        = 20,     /*!< USB Device Low Priority or CAN1 RX0 Interrupts       */
haben. Hier die fragliche Funktion, die ich (gegenüber der REferenz) um 
den das Statement NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); ergänzt 
habe.
1
void NVIC_Configuration(void)
2
{
3
  NVIC_InitTypeDef NVIC_InitStructure;
4

5
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); // FLASH Vector Table ab 0x08000000 (Default)
6

7
  /* Enable CAN1 RX0 interrupt IRQ channel */
8
#ifndef STM32F10X_CL
9
  NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
10
#else
11
 NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
12
#endif /* STM32F10X_CL*/
13
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
14
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
15
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
16
  NVIC_Init(&NVIC_InitStructure);
17
}
Gast #1973263
Lesenswert?

(...) und in der Testfunktion CAN_Interrupt wird der so konfigurierte 
Interrupt aktiviert:
1
 /* CAN FIFO0 message pending interrupt enable */ 
2
  CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

Das Problem tritt aber nur auf, denn NVIC_Configuration() aufgerufen 
wurde - die Interrupt-Aktivierung habe ich nicht auskommentiert, ist 
also immer aktiv.


[EDIT]
Baudratenberechnung: ich meine, ich habe die Beispielwerte nicht 
geändert, werde aber den Link auswerten.
Konfiguriert ist:
1
 CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
2
  CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
3
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
4
  CAN_InitStructure.CAN_Prescaler=5;
Nach Deinem Excel-Sheet (super Sache :-) ) läuft dies auf 450kHz hinaus, 
bzw. 2.2us. Im Oszi sind es ca. 2,24 us.
[/EDIT]

Grüße
schnack
Gast #1973302
Lesenswert?

Hi Matthias,
hier liegt ja vielleicht der Hund begraben:

> Bist Du sicher, dass das Startup .s zu win-arm passt? In Bsp. sehen die
> dort anderes aus.

Die Startup-Datei habe aus dem Verzeichnis für ride-gcc entnommen 
(attachment).
Bislang hat damit alles - na ja, also die blinkende LED immerhin - 
funktioniert. Ich bin jetzt (nach Deinem Hinweis) von der XL auf die HD 
Variante umgestiegen.
Grüße
schnack
Angehängte Dateien:
Gast #1973309
Lesenswert?

Hallo,
also der Wert der Vektor-Tabelle habe ich durch hinsteppen ermittelt, 
siehe attachment. Nun ist 134217728 = 0x8000000.
Die Statements mit reg sind (völlig überflüssig und) von mir.
Grüße
schnack
Angehängte Dateien:
Gast #1974764
Lesenswert?

Hallo Matthias,
Dein Linker-Skript (auf 512K Flash, 64K RAM modifiziert) hat leider 
keine Änderung gebracht.

Ich fasse noch einmal zusammen:

A) Mit Aufruf "NVIC_Configuration()":
* CAN-Frames nach Download via JTAG, keine ISR-Behandlung
* nach Reset keine CAN-Frames, offenbar springt er beim Empfang in eine 
ISR und "verendet" dort (These dazu unten)

B) Ohne Aufruf "NVIC_Configuration()":
* CAN-Frames nach Download via JTAG oder USART, keine ISR-Behandlung
* nach Reset das gleiche Verhalten

Und schließlich:

A*) Mit Aufruf "NVIC_Configuration()":
Wenn ich (nicht in Eclipse) direkt im gdb (CodeSourcery) debugge, gibt 
er nach monitor reset und continue ebenso keine Frames aus. Bei 
Unterbrechen der Ausführung mit Crtl-C meldet er:
1
Program received signal SIGTRAP, Trace/breakpoint trap.
2
0x080030c8 in WWDG_IRQHandler ()
Wieso er in den Windowed Watch Dog Handler läuft, ist mir allerdings 
komplett ein Rätsel - schließlich ist dieser Interupt nicht 
konfiguriert. Offenbar ist dies der Interrupt-Handler, den er irrtümlich 
nach CAN-Frame Empfang aktiviert - und der besteht nur aus einer 
Endlosschleife..

Grüße
schnack

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren