Forum: Mikrocontroller und Digitale Elektronik 89C51CC03CA per Software in den Bootloader bringen


von C. L. (calle)


Lesenswert?

Hallo zusammen,

ich versuche den o.g. Controller per Software in den CAN Bootloader zu 
bringen. Das gelingt mir allerdings nicht!

Im Datenblatt auch S. 61 steht das zwar annähernd beschrieben aber ich 
kapiere es nicht.

Habe es versucht mit folgenden Ideen:

   AUXR1 = AUXR1 | 0x20;   // BIT ENBOOT im AUXR1 auf "1"
   FCON = 0x00;            // FCON Register alles "0"
hier fehlt mir dann der Zugriff auf den Programmcounter als 
Softwarereset.
=> klappt nicht

Die Zielschaltung habe ich mit einem MAX807L Überwachungsbaustein mit 
Watchdog ausgestattet. ENBOOT auf "1", den Trigger halte ich an, der MAX 
resetet den Controller. Funtkioniert nur bedingt, weil der Bootloader 
nicht antwortet und der Überwachungsbaustein natürlich weiter fleißig 
Reset ausführt.

Ziel soll es sein den Controller "von fern über CAN" neu zu flashen.
Mit der HW Lösung funzt das super, würde aber später alles vom PC aus 
machen.

Kann mir da mal jemand helfen bitte?

Carsten

von Peter D. (peda)


Lesenswert?

Du mußt erst per API-Call das BLJB löschen.

von C. L. (calle)


Lesenswert?

Das heisst ich muss erst ...

/* Speicherzellen für API Funktionen reservieren*/
near unsigned char api_cmd @ 0x1C;
near unsigned char api_val @ 0x1D;
near unsigned char api_dph @ 0x1E;
near unsigned char api_dpl @ 0x1F;

Mit den entsprechenden Werte versorgen, dann laut Handbuch einen 
Usercall zu fixen Adresse FFC0h machen und vorher ENBOOT setzen.

Wie mache ich denn in C ein Usercall zu fixen Adresse FFC0h??
Oder stehe ich jetzt total auf dem Schlauch?

Mir fehlt irgendwie noch das Grundverständnis eines solchen API 
Handling.
Ist ja auch das erste mal.

Nutze uC51 von Wickenh...

Carsten

von Peter D. (peda)


Lesenswert?

Mit Keil C51:
1
#define CALL(addr)      (((void(*)(void))(char code *)addr)())
2
3
sfr     AUXR1         = 0xA2;
4
#define AUXR1_DPS     0x01
5
#define AUXR1_GF2     0x08
6
#define AUXR1_ENBOOT  0x20
7
sfr16   DPTRW         = 0x82;
8
9
10
u8 api_call( u16 dptr, u8 r0, u8 r1, u8 acc )
11
{
12
  bit ea;
13
14
  DPTRW = dptr;
15
  ea = EA;      // save interrupt status
16
  EA = 0;
17
  AUXR1 |= AUXR1_ENBOOT;  // enable boot
18
  *(char data*)1 = r1;    // R1 pointed by R0
19
  *(char data*)0 = r0;    // R0 pointed by R0 and overwrite itself !
20
  ACC = acc;
21
22
  CALL( 0xFFF0 );    // API call
23
  EA = ea;
24
  return ACC;
25
}

von C. L. (calle)


Lesenswert?

Moin!

Ich versteh´nur Bahnhof!
Das sackt noch nicht durch und KeilC51 ist mir nicht geläufig.
Versuche das mal zu interpretieren...

Peter Dannegger schrieb:
> #define CALL(addr)      (((void(*)(void))(char code *)addr)())
=> Definiton

> sfr     AUXR1         = 0xA2;
=> Registeradresse

> #define AUXR1_DPS     0x01
> #define AUXR1_GF2     0x08
> #define AUXR1_ENBOOT  0x20
=> Wertigkeiten

> sfr16   DPTRW         = 0x82;
=> Registeradresse


> u8 api_call( u16 dptr, u8 r0, u8 r1, u8 acc )
> {
>   bit ea;
=> Bitvariable deklarieren

>   DPTRW = dptr;
=> 16Bit Datenpointer, bei mir DPH und DPL

>   ea = EA;      // save interrupt status
=> Zwischenspeichern

>   EA = 0;
=> Ist das der EA PIN?? oder wie?

>   AUXR1 |= AUXR1_ENBOOT;  // enable boot
=> ENBOOT auf "1"

>   *(char data*)1 = r1;    // R1 pointed by R0
>   *(char data*)0 = r0;    // R0 pointed by R0 and overwrite itself !
=> Hier werden die API Aufrufdaten übergeben, das verstehe ich nicht
=> Pointer auf Pointer?

>   ACC = acc;
=> was ist ACC??

>   CALL( 0xFFF0 );    // API call
=> Aufruf zu fixer Adresse, wie geht das bei uc51 von Wickenh...

>   EA = ea;
=> zurückschreiben

>   return ACC;
=> Ergebnis mitteilen
> }

Ich bekomme das nicht auf meinen Verstand portiert!
Kannst du das mal im Blockschaltbildcharakter beschreiben?

1. das
2. dann das..
3. das noch....
usw.

Carsten

von C. L. (calle)


Lesenswert?

Hey, habs hinbekommen,

Wenn man es so macht unter uc51, dann kommen die richtigen Daten zurück.
Lesen klappt schonmal...

Hier der Code;
/* Speicherzellen für API Funktionen reservieren*/
near unsigned char api_cmd @ 0x1C;
near unsigned char api_val @ 0x1D;
near unsigned char api_dph @ 0x1E;
near unsigned char api_dpl @ 0x1F;


// zum Test erstmal die CAN Knotennummer lesen.
AUXR1 = AUXR1 | 0x20;    // BIT ENBOOT im AUXR1 auf "1"
i = 0;                   // löschen
api_val = 0;             // löschen

/* aus dem CAN Bootloader pdf die Werte für die API einschreiben*/
api_cmd = 0x05;
api_dph = 0x00;
api_dpl = 0x1F;

/* Als Assembler einen LCALL auf die im pdf angegebene Adresse */
#asm
lcall 0xFFC0
#endasm

/* zurück kommt der Wert */
 i = api_val;

/* darstellen */
printf(" (Wert: %5x)", i);
 _wait_ms(5000);


Gruß

Carsten

von C. L. (calle)


Lesenswert?

Sooooo,

jetzt klappt das flashen und der Bootloader ohne die Platine anzufassen 
und irgendwelche Knöpfe zu drücken.
Hier der Code, noch unoptimiert:

// ####################### API SCHREIBEN ############################

 api_cmd = 0x08; // HSB lesen
 api_dph = 0x00;
 api_dpl = 0x00;
#asm
lcall 0xFFC0
#endasm
 i = api_val; // Hier steht jetzt der Inhalt des HSB Registers drin
// nächster API Aufruf
 api_cmd = 0x07; // BLJB löschen
 api_dph = 0x00;
 api_dpl = 0x00;
 api_val = i & 0xBF; // HSB Registerwert mir gelöschten BLJB zurück
#asm
lcall 0xFFC0 // und Abmarsch!!!
#endasm

// jetzt sollte der cc03er bei nächsten Reset im Bootloader anfangen
// also... Watchdog einschalten und Reset auslösen lassen
FCON = 0x00;            // FCON Register leermachen
WDTPRG = WDTPRG | 0x07; // WDT Teiler auf 2,1 Sekunden bei 12 Mhz setzen
WDTRST = 0x1E;          // WDTRST Routine laut Datenblatt setzen
WDTRST = 0xE1;
while(1);               // Controller hier parken, Resetbaustein 
beachten


Danke, jetzt kann ich ruhig schlafen!!

Carsten

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.