Forum: Mikrocontroller und Digitale Elektronik Atmega32u4 per Software reseten


von Draco (Gast)


Lesenswert?

Ich habe hier einen Atmega32u4, auf dem ein USB HID läuft. Nun habe ich 
ein Programm geschrieben welches neue Werte vom PC zum µC lädt und im 
EEPROM ablegt, der µC muss sich nun mit dem PC neu verbinden, sodass die 
Werte dann auch neu im System übernehmen werden. Momentan ziehe ich nun 
immer das Kabel und stecke es neu an.

Schöner wäre es natürlich das der µc den Reset selber durchführen kann, 
sodass ich auf der einen Seite die mechanische Belastung an der USB 
Buchse reduzieren kann, und es ist natürlich auch komfortabler.

Jemand einen kleinen Tipp im Ärmel?

von Harry L. (mysth)


Lesenswert?

Watchdog-Timer aktivieren, und den µC in eine Endlosschleife schicken.

von Draco (Gast)


Lesenswert?

Also ich habe nun den Reset mit dem Watchdog Timer ausgeführt. Der Reset 
funktioniert auch erstmal wunderbar. Aaaber

1
int main(void)
2
{ 
3
  wdt_reset();
4
  wdt_disable();
5
6
  uint8_t Ep2_temp[2] = {0,0};
7
8
  McStart();
9
    usb_init_device();    // Unterprogramm der USB-Bibliothek
10
    DracoRc_Setup();
11
    DracoRc_ChannelReset();
12
  McReady();
13
  
14
  wdt_enable(500);
15
  wdt_reset();
16
17
  sei();
18
19
  while (1)
20
  {
21
    Delay_MS(1);
22
    
23
    DracoRc_CalcMiddle();    
24
    Ep1_cnt = NumChannelOutPuts+2;  
25
    
26
    for(uint8_t i=0; i<NumChannelOutPuts;i++)
27
    {
28
       Ep1_buf[i]= ChannelPerc[i];
29
    }
30
31
    // Check USB Input Buffer
32
    if(Ep2_flag == 1)
33
    {
34
       if(Ep2_buf[0] == 0x86)
35
     Ep2_temp[1] = 0x01;
36
       else if (Ep2_buf[0] == 0x87)
37
     Ep2_temp[1] = 0x02;
38
      
39
       Ep2_flag = 0;
40
     }
41
42
     //Watchdog reset
43
     if(Ep2_temp[1] == 2)
44
     {
45
  while(1)
46
  {
47
  }
48
     }
49
50
    wdt_reset();
51
    Ep1_buf[4] = Ep2_temp[1];
52
    Ep1_buf[5] = NumChannelOutPuts;
53
    Ep1_flag = 1;
54
  }
55
}

Der Reset wird wie erwartet ausgeführt, jedoch kommt der µC nicht mehr 
korrekt zurück aus dem Reset. An PortB0 ist eine LED angeschlossen, 
diese blinkt nun, warum auch immer. Es hat den Anschein das er es 
nichtmal schafft mehr in die Main zurückzuspringen. Ein Bootloader ist 
AFAIK nicht auf dem µC, zumindest dürfte er ja mit einem normalen Chip 
Erase überschrieben wurden sein.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Evtl. musst du noch ein USB Device disconnect und reconnect auslösen. 
Evtl. das Disconnect sogar noch, bevor der WD zuschlägt.

von 1234567890 (Gast)


Lesenswert?

Draco schrieb:
> while(1)
>   {
>   }

Wenn er da ankommt, wird der Watchdog nie wieder resetet und der uC wird 
immer wieder durch den Watchdog resetet.

von 1234567890 (Gast)


Lesenswert?

1234567890 schrieb:
> Draco schrieb:
>> while(1)
>>   {
>>   }
>
> Wenn er da ankommt, wird der Watchdog nie wieder resetet und der uC wird
> immer wieder durch den Watchdog resetet.

Das ist sicher das was du willst, aber ist es das auch beim ersten mal?

von Draco (Gast)


Lesenswert?

1234567890 schrieb:
> Draco schrieb:
>> while(1)
>>   {
>>   }
>
> Wenn er da ankommt, wird der Watchdog nie wieder resetet und der uC wird
> immer wieder durch den Watchdog resetet.

Da stehe ich gerade auf dem Schlauch. Er soll ja durch diese Schleife in 
den Reset kommen, diese Schleife ist ja eine Ebene über der Main 
Schleife.


Mal aufgedröselt:
1
int main(void)
2
{ 
3
  //..
4
5
  while (1) //Hauptschleife
6
  {
7
  //...
8
9
     //Watchdog reset
10
     if(Ep2_temp[1] == 2)
11
     {
12
       while(1) //WD Schleife
13
      {
14
      }
15
     }
16
17
    wdt_reset();
18
    //.....
19
  }
20
}

kommt doch nur dort an, wenn die Variable den Wert hat. Springt der 
Watchdog automatisch wieder an ihren Urpsrungsvector?!

von Draco (Gast)


Lesenswert?

1234567890 schrieb:
> Das ist sicher das was du willst, aber ist es das auch beim ersten mal?

Beim normalen durchlauf, wird diese schleife ignoriert, da ja die 
Variable vorher in der if Abfrage nicht wahr ist.

von Draco (Gast)


Lesenswert?

Ich habe es nun hinbekommen:

1
int main(void)
2
{ 
3
4
  cli();
5
  uint8_t temp = MCUCR;
6
  MCUCR = temp | (1<<IVCE);
7
  MCUCR = temp & ~(1<<IVSEL);
8
  sei();
9
10
  wdt_disable();
11
  MCUSR = 0;
12
  wdt_reset();
13
  //..
14
15
16
17
  while (1) //Hauptschleife
18
  {
19
  //...
20
21
     //Watchdog reset
22
     if(Ep2_temp[1] == 2)
23
     {
24
        uint8_t temp = MCUCR;                 // Get MCUCR
25
        MCUCR = temp | (1<<IVCE);     // Enable change of Interrupt Vectors
26
        MCUCR = temp | (1<<IVSEL);    // Move interrupts to Boot Flash section
27
28
        while(1) //WD Schleife
29
        {
30
        }
31
     }
32
33
    wdt_reset();
34
    //.....
35
  }
36
}

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.