Hallo Zusammen, Ich versuche gerade herrauszufinden wie Adresse des Sequence complete Interrupt des ADC vom MC9S12C lautet. Also die Adresse im Speicher wo er nach auslösen hinspringt. Hab das Datenblatt schon x-mal durchforstet und es gelingt mir nicht. Zudem stosse ich immer wieder auf Adressangaben wie "Module Base + 0x001" - Was ist die "Module Base"? Danke für eure Hilfe!
Ok, Nachtrag. Ich habe jetzt doch etwas gefunden, macht mich aber nicht wirklich Schlauer. Es müsste laut Datenblatt diese Adresse sein, oder: 0xFFD2, 0xFFD3 ATD. Ok, das sind 2 Speicherstellen aber wie passt da noch ein Jumpbefehl davor? Oder ist da beim HCs12 nicht mehr nötig und ich bin noch etwas Odlscool? Des weiteren verstehe ich den Code eines Kollegen nicht welcher für einen Timer-interrupt folgenden Code geschrieben hat:
1 | void initTimer(void) { |
2 | // timer enable, freeze while BDM
|
3 | *((unsigned char *) 0x0fe2) = 0x06; |
4 | *((void(**)(void)) 0x0fe3) = timer_interrupt; |
5 | TSCR1 = 0x80; // Timer enable |
6 | TSCR2 = 0x07; // Prescaler = 128 (1 timer tick every 16µs) |
7 | TCTL2 = 0x00; // TC2 disconnected from Pin |
8 | TIOS |= 0x04; // TC2 is Output Compare |
9 | TIE |= 0x04; // TC2 Interrupt enable |
10 | }
|
Ich dachte bissher immer die "0x0fe3" wäre die Adresse für den Timmerinterrupt. Passt dan aber nicht mit der Tabelle im Datenblatt zusammen.
Markus schrieb: > *((unsigned char *) 0x0fe2) = 0x06; > *((void(**)(void)) 0x0fe3) = timer_interrupt; > Ich dachte bissher immer die "0x0fe3" wäre die Adresse für den > Timmerinterrupt. Passt dan aber nicht mit der Tabelle im Datenblatt > zusammen. Wieso? Passt doch wunderbar: > *((void(**)(void)) 0x0fe3) = timer_interrupt; timer_interrupt wird wohl die aufzurufende Funktion sein. Deren Adresse wird beginnend ab 0x0fe3 abgelegt. Der cast links sieht etwas seltsam aus (eigentlich müsste es ein Stern alleine auch tun), ist aber dem Datentyp nach ein Pointer auf eine Funktion. > *((unsigned char *) 0x0fe2) = 0x06; das wird dann wohl der 'Jump' sein. Schau doch mal ins Datenblatt deines Prozessors welcher OpCode sich hinter 0x06 verbirgt.
Passt wunderbar? - Dann bin ich zu doof.
Im datenblatt steht was von Adresse 0xFFDE, 0xFFDF für Standard
timer overflow TMSK2 (TOI), das ist aber weit entfernt von 0x0FE3.
>das wird dann wohl der 'Jump' sein.
Richtig, ist ein Jump aber ich bin immer noch verwirrtt wegen der
Adresse. Der Code mit Funktioniert aber ich komm nicht dahinter wo mein
Kollege diese Adressangaben herhat.
Markus schrieb: > Passt wunderbar? - Dann bin ich zu doof. > Im datenblatt steht was von Adresse 0xFFDE, 0xFFDF für Standard > timer overflow TMSK2 (TOI), das ist aber weit entfernt von 0x0FE3. > >>das wird dann wohl der 'Jump' sein. > Richtig, ist ein Jump aber ich bin immer noch verwirrtt wegen der > Adresse. Der Code mit Funktioniert aber ich komm nicht dahinter wo mein > Kollege diese Adressangaben herhat. Jetzt bin ich verwirrt. Dein Aussage: "Ich dachte bissher immer die "0x0fe3" wäre die Adresse für den Timmerinterrupt." Und im Code schreibt er die Adresse einer Funktion namens "timer_interrupt" nach 0x0fe3. Beides mal die gleiche Adresse - was verwirrt dich daher? Was soll da nicht passen? (OK, die Frage bleibt, warum der eigentliche jump nach 0x0fe2 kommt, aber das kann ich dir nicht beantworten) > Im datenblatt steht was von Adresse 0xFFDE, 0xFFDF für Standard > timer overflow TMSK2 (TOI), das ist aber weit entfernt von 0x0FE3. Da geb ich dir recht. Aber ohne das Datenblatt ist das schwer zu entscheiden.
Hallo Markus, leg dir eine Vektortabelle an und trage alle benutzten Interrupts dort ein. Für nicht benutzte Interrupts legts du dir einen DummyIsr an. Damit brauchst du solche Häßlichkeiten wie *((unsigned char *) 0x0fe2) = 0x06; *((void(**)(void)) 0x0fe3) = timer_interrupt; nicht, das erledigt dann dein Linker. Bei deinem manuellem Konstrukt mußt du bei jeder Änderung diese Adressen kontrollieren und anpassen. Dann muss die Vektortabelle nur noch an die richtige Adresse des FLASH gelinkt werden. Bei den Frescale S12 ist das normalerweise ganz am Ende. Im Anhang mal ein Beispiel des S12C32. Zu deiner Frage mit dem Module Base: Du kannst bei dem S12 das RAM, das EEPROM und die Register verschieben, damit ändert sich dann (natürlich) die Module Base Adresse und du mußt die Registeradressen anpassen.
>Beides mal die gleiche Adresse - was verwirrt dich daher? Mich verwirrt dass im Datenblatt etwas anderes steht und ich die Adresse "0x0fe3" dort niergens finden kann. Der Code funktioniert aber dennoch. >Da geb ich dir recht. Aber ohne das Datenblatt ist das schwer zu entscheiden. Wäre jemand so nett und schaut mal ins Datenblatt des MC9S12C und sagt mit die Adresse für den "Sequence complete Interrupt" des ADC? - Danke >leg dir eine Vektortabelle an und trage alle benutzten Interrupts dort ein. Ist im Prinzip eine gute Idee aber dazu muss ich erstmal Verstehen wo den die Adressen der Interrupts liegen um so eine Tabelle anzulegen. Aber da bin ich im Augenblick noch nicht angekommen. Was ich auch noch nicht verstehe: Im Datenblatt stehen 2 Adressen - Wie pack ich da eine neue Adresse und einen Jump Befehl rein - Ich dachte ich bräuchte da zumindest 3 freie Speicherstellen? Danke Euch!
OK, dir fehlt ein klein wenig das Verständis, wie das mit den Interrupts so abläuft. DIe Adresse des Sequence Complete Interrupts ist 0xFFD2, d.h. an dieser Adresse (16 Bit! 0xFFD2 und 0xFFD3) steht wo der erste Befehl der ATD Sequence complete Service Routine im Adressraum steht. Oder anders formuliert, der Inhalt diese Adresse zeigt auf eine andere Adresse, nämlich die der Serviceroutine. Du brauchst hier also nicht mit Gewalt ein Jump hinzuschreiben, das geht dann immer schief. Soweit verstanden? Deshalb eine Vektortabelle anlegen, so ungefähr wie ich sie gepostet habe, Serviceroutine eintragen und den Rest vom Linken erledigen lassen.
>OK, dir fehlt ein klein wenig das Verständis, wie das mit den Interrupts >so abläuft. Ja, ich hab noch wenig Erfahrung mit dem HCS12 und auch mit dem GNU-Compiler. Ich weis nur das es beim 80c535 3 Speicherstellen waren, eine für einen "jmp" und 2 für die Adresse. Aber so wie ich dich verstehe ist der HCS12 da schon etwas weiter und springt automatisch an die Adresse die er an 0xFFD2 und 0xFFD3 findet. Bin halt schon etwas in die Jahre gekommen ;-) Wie gesagt, auch mit dem Gnu-Compiler bin ich noch nicht wirklich vertraut darum noch eine Frage zur Vectortabelle. Funktioniert das so? Hab es in der GNU-Documentation so gefunden. Wird (".vectors") mit der ersten Adresse der Vectortabelle automatisch vom Compiler erstezt oder muss ich da noch etwas tun?
1 | extern void _start(void);/* entry point in crt0.s */ |
2 | extern void __attribute__((interrupt)) ADC_cov_complete (void); |
3 | void __attribute__((interrupt)) isr_empty(void){/* do nothing */} |
4 | |
5 | void __attribute__ (( section (".vectors") )) (* const interrupt_vectors[])(void) = { |
6 | isr_empty, /* $ffc0: reserved */ |
7 | isr_empty, /* $ffc2: reserved */ |
8 | isr_empty, /* $ffc4: reserved */ |
9 | isr_empty, /* $ffc6: reserved */ |
10 | isr_empty, /* $ffc8: reserved */ |
11 | isr_empty, /* $ffca: reserved */ |
12 | isr_empty, /* $ffcc: reserved */ |
13 | isr_empty, /* $ffce: reserved */ |
14 | isr_empty, /* $ffd0: reserved */ |
15 | ADC_cov_complete, /* $ffd2: ADC_cov_complete */ |
16 | isr_empty, /* $ffd4: reserved */ |
17 | isr_empty, /* $ffd6: SCI serial system */ |
18 | isr_empty, /* $ffd8: SPI serial transfer complete (SPIE) */ |
19 | isr_empty, /* $ffda: Pulse accumulator input edge (PAII) */ |
20 | isr_empty, /* $ffdc: Pulse accumulator overflow (PAOVI) */ |
21 | isr_empty, /* $ffde: Timer overflow (TOI) */ |
22 | isr_empty, /* $ffe0: Timer channel 7 */ |
23 | isr_empty, /* $ffe2: Timer channel 6 */ |
24 | isr_empty, /* $ffe4: Timer channel 5 */ |
25 | isr_empty, /* $ffe6: Timer channel 4 */ |
26 | isr_empty, /* $ffe8: Timer channel 3 */ |
27 | isr_empty, /* $ffea: Timer channel 2 */ |
28 | isr_empty, /* $ffec: Timer channel 1 */ |
29 | isr_empty, /* $ffee: Timer channel 0 */ |
30 | isr_empty, /* $fff0: Real-time interrupt (RTII) */ |
31 | isr_empty, /* $fff2: -IRQ (external pin) */ |
32 | isr_empty, /* $fff4: -XIRQ pin */ |
33 | isr_empty, /* $fff6: Software interrupt */ |
34 | _start, /* $fff8: Illegal opcode trap */ |
35 | _start, /* $fffa: COP failure (NOCOP) */ |
36 | _start, /* $fffc: Clock monitor fail (CME) */ |
37 | _start /* $fffe: -RESET (hardware reset) */ |
38 | };
|
Danke und Gruß!
Hallo, sieht gut aus. Sollte so funktionieren. Der Ausdruck "( section (".vectors") )" markiert dieen Code als Sektion. Diese Sektion wiederum gibt an, wo der Code hin gelinkt werden soll. Deshalb muss im Linkerfile auch ein Label .vectors auftauchen und mit der richtigen Adresse verknüpft sein. So ist es zumindest bei Metrowerks, Cosmic oder anderen Compilern. Den GNU kenne ich nicht, vermute aber mal, dass der auch so arbeitet.
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.