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
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
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 | }
|
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.