Nutzung einiger TRAP Aufrufe des Monitors in C.
Funktionen des Assembler Include -Wf-include-stdasm=monitor.inc mit dem C Aufruf #include <monitor.h>
1. monitor_print(Zeichenkette); // TRAP 1
Eine mit 0x00 abgesclossene Zeichenkette an die UART senden.// monitor_print("\r\n\Zeichenkette anzeigen\r\n"); // Anzeige des Textes mit Steuerzeichen zwichen den Anführungszeichen. //
// char zeit[11] = "00:00:00\r\0"; monitor_print(zeit); // Anzeige der in der Variablen zeit gespeicherten Zeichenkette //
2. monitor_putchar(zeichen); // TRAP 2
Ein Zeichen an die UART senden.// monitor_putchar('*'); // Anzeige des ASCII-Zeichen * //
// unsigned char zeichen = '#'; monitor_putchar(zeichen); // Anzeige des ASCII-Zeichen # //
3. monitor_getchar(); // TRAP 3
Ein Zeichen von der UART empfangen.// unsigned char zeichen; zeichen = monitor_getchar(); // Eingabe eines ASCII-Zeichen ohne Echo //
// // Eingabe von + oder - unsigned char zeichen = ' '; while (!(zeichen == '+' || zeichen == '-')) { zeichen = monitor_getchar(); } monitor_putchar(zeichen); // Echo des eingegebenen Zeichen, wenn es richtig ist. //
4. monitor_getstat(); // TRAP 17
Ein Zeichen von der UART empfangen, ohne auf eine Eingabe zu warten.// unsigned char e = 0; // keine Eingabe unsigned char f = 0; // keine Eingabe while (e == 0) { f = monitor_getstat(); // f = ASCII-Zeichen oder 0 bei keiner Eingabe if (f == 'a') { monitor_putchar(f); } else { e = f; } } //
5. monitor_putbyte(wert); // TRAP 5
Einen 8 Bit Wert hexadezimal über die UART anzeigen.// unsigned char wert = 0x4a; monitor_putbyte(wert); // Es wird 04A angezeigt. //
6. monitor_getbyte(); // TRAP 7
Eingabe eines hexadezimalen 8 Bit Wertes über die UART. Es sind nur die Ziffern 0 ... 9 und die Buchstaben A ... F und a ... f bei der Eingabe zulässig. Die eingegebenen Zeichen sind nur zu sehen, wenn vorher monitor_echoon(); aufgerufen wurde.// unsigned char wert; wert = monitor_getbyte(); // Eingabe eines Hex Wertes von 0x00 bis 0xff //
7. monitor_putint(wert); // TRAP 4
Einen 18 Bit Wert hexadezimal über die UART anzeigen.// int wert = 0x3456f monitor_putint(wert); // Es wird 3456F angezeigt. //
8. monitor_getint(); // TRAP 6
Eingabe eines hexadezimalen 18 Bit Wertes über die UART. Es sind nur die Ziffern 0 ... 9 und die Buchstaben A ... F und a ... f bei der Eingabe zulässig. Die eingegebenen Zeichen sind nur zu sehen, wenn vorher monitor_echoon(); aufgerufen wurde.// int wert; wert = monitor_getint(); // Eingabe eines Hex Wertes von 0x00000 bis 0x3ffff //
9. monitor_newline(); // TRAP 12
Senden von CR und LF an die UART.// monitor_newline(); //
10. monitor_space(); // TRAP 13
Senden eines Leerzeichens an die UART.// int wert1 = 0x55; int wert2 = 0xaa; monitor_newline(); monitor_putint(wert1); monitor_space(); monitor_putint(wert2); monitor_newline(); // Es wird 00055 000AA angezeigt. //
11. monitor_putregs(); // TRAP 16 und TRAP 12
Anzeige der Adresse an der die Funktion aufgerufen wurde, des SFR_STATUS Registers, des SFR_CC Bit und die aktuellen 16 Register.// monitor_putregs(); //
Ausgaben nach 3 Aufrufen in einem Programm.
; 00171 00103 0 017E4 00006 00000 00000 02200 02208 02208 00000 007A9 00001 00000 00FC2 00018 00000 00200 00001 0018F 00103 0 017E4 00006 00000 00000 02200 02208 02208 00001 007A9 00001 00000 00FC2 00018 00000 00200 00001 002AD 00103 1 017E4 00006 00000 00000 02200 02208 02208 00001 007A9 00001 00000 00FC2 011D4 00000 00200 00001 ;
Bedeutung der einzelnen Werte im obigen Protokoll.
; UP EI,MM CC Start Rbase 00171 00103 0 017E4 00006 00000 00000 02200 02208 02208 00000 007A9 00001 00000 00FC2 00018 00000 00200 00001 ro r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 ;
12. monitor_intregs(int npc, int cc); // TRAP 16 und TRAP 12
Diese Funktion ist speziell zur Einbindung in die ISR der Taste die mit "Interrupt Lowactiv" verbunden ist gedacht. Sie Zeigt die Register des unterbrochenem Programms an. Um auch Informationen aus der Interrupt Annahme im "Startup Programm" auszuwerten, wird die Registernutzung des C-Compilers ausgenutzt. Der C-Compiler verwendet für die ersten 4 Parameter immer die Register R12 bis R15, wenn das Datenformat dies zulässt. Das "Startup Programm" lädt in R14 bei der Interrupt Annahme das SFR_CC Register und in R12 steht eine Kopie von R11, der Rücksprungadresse und damit von Next-PC. Dies soll dann wie bei der Funktion monitor_putregs(); angezeigt werden. Dazu hat die ISR folgenden Aufbau:
ISR-zur Anzeige der Register in C in den jeweils höchsten Interrupt eines Systems einfügen.
// interrupt_lowactiv (Taste Nord auf dem 3e Board) void isr10(int reg12, int reg13, int reg14, int reg15) { monitor_newline(); monitor_intregs(reg12, reg14); }
Der Assembler Code, der daraus entsteht sieht dann wie folgt aus:
; _ISR10: ADDI R0, -4 JALS _MONITOR_NEWLINE MOV R12, R4 MOV R13, R6 JALS _MONITOR_INTREGS ADDI R0, 4 JRS R11 ;_isr10 2 ; _MONITOR_INTREGS: MOV R12, R4 ; Adresse bei der UP gerufen wurde MOVS2I R13, SFR_STATUS ; Bit8 = EI, Bit7 = MM, Bit6:0 = RegBase MOV R14, R5 ; r14 Bit0 = CC MOVI R15, 4 ; RegBase um 4 Ebenen nach oben TRAP 16 ; 16 pg_regs anzeigen MOVI R15, 3 ; RegBase um 3 Ebenen nach oben TRAP 16 ; 16 pg_regs anzeigen TRAP 12 ; crlf JRS R11 ; ;
Damit entsteht dann folgendes Bild auf der Konsole des Monitors:
; 002C7 00005 1 017D0 00006 00000 00000 01A26 0001F 020C4 00058 00001 00020 00058 00FC5 00000 340A0 0007F 00001 002C7 00005 1 017D0 00006 00000 00000 00000 340A0 0007F 00001 34080 00048 00032 002C7 002C7 00000 00001 00080 002C8 00005 1 017D0 00006 00000 00000 01A26 0001F 020C4 00058 00001 00020 00058 00FC5 00000 340A0 0007F 00001 002C8 00005 1 017D0 00006 00000 00000 00000 340A0 0007F 00001 34080 00048 00032 002C8 002C8 00000 00001 00080 002CE 00005 1 017D0 00006 00000 00000 01A26 0001F 020C4 00058 00001 00020 00058 00FC5 00000 340A0 0007F 00001 002CE 00005 1 017D0 00006 00000 00000 00000 340A0 0007F 00001 34080 00048 00032 002CE 002CE 00000 00001 00080 ;
Bedeutung der Anzeige:
; Next EI,MM CC Next EI,MM CC ********** Absolute Registeradressen ********* PC Rbase PC Rbase Register = Absolute Registeradressen - Rbase * 8 002CE 00005 1 017D0 00006 00000 00000 01A26 0001F 020C4 00058 r0 r1 r2 r3 r28 r29 r30 r31 \_ bei Rbase-2=3 00001 00020 00058 00FC5 00000 340A0 0007F 00001 002CE 00005 1 r32 r33 r34 r35 r36 r37 r38 r39 / 017D0 00006 00000 00000 00000 340A0 0007F 00001 r0 r1 r2 r3 r36 r37 r38 r39 \_ bei Rbase-1=4 34080 00048 00032 002CE 002CE 00000 00001 00080 r40 r41 r42 r43 r44 r45 r46 r47 / ;
Der 1. Wert ist die Adresse des nächsten Befehls (PC), der 2. der Wert ist SFR_STAT in der Funktion "monitor_intregs(int npc, int cc);" vor dem Aufruf vom TRAP 16 und der 3. Wert ist das CC Bit. Dann folgen die 16 Register des unterbrochenem Programms mit angezeigtes !RegBase -2 (5-2=3) von R0 bis R15. Ist das unterbrochene Programm wie hier ein mit dem Monitor geladenes MAIN Programm, dann steht in R11 (oben absolut r35) die Rücksprungadresse aus dem GO-Kommando des Monitors (hier 0x00FC5). Darauf folgen dann noch einmal die 3 Werte aus dem Kopf gefolgt von den 16 Registern mit angezeigtes !RegBase - 1 (5-1=4). Hier ist R11 (oben absolut r43) die Rücksprungadresse des Interrupts, also der PC des nächsten Befehls. In R14 steht dann nochmal das SFR_CC Register. Die Liste des hier unterbrochenen Programm von 0x002C0 bis 0x002CF hat dabei folgenden Aufbau (die mit * markierten Befehle, sind die Befehle aus dem obigen Protokoll):
; 0002C2 000134AE M63: M61: M59: M57: MOVI R10, (_aktzeit) 0002C3 00025540 L18 R10, 0(R10) 0002C4 00012E94 MOVI R7, (_i) 0002C5 00024EE0 L18 R7, 0(R7) 0002C6 000014E8 SEQU R10, R7 * 0002C7 00000005 MOV R0, R0 * 0002C8 0000E006 BNEZC M64 0002C9 00007EF9 JALS _PUTZEIT 0002CA 000134AE MOVI R10, (_aktzeit) 0002CB 00012E94 MOVI R7, (_i) 0002CC 00024EE0 L18 R7, 0(R7) 0002CD 00026F40 S18 0(R10), R7 * 0002CE 00013496 M64: MOVI R10, (_j) 0002CF 00025540 L18 R10, 0(R10) ;
und realisiert von 0x002C2 bis 0x002CD die C-Befehlfolge:
if (aktzeit != i) { putzeit(); aktzeit = i; }
13. monitor_echoon();
Setzt das Bit 1 im Register 1 und schaltet damit für die Funktionen monitor_getbyte(); und monitor_getint(); das Echo der eingegebenen Zeichen ein.monitor_echoon();
14. monitor_echooff();
Löscht das Bit 1 im Register 1 und schaltet damit für die Funktionen monitor_getbyte(); und monitor_getint(); das Echo der eingegebenen Zeichen aus.monitor_echooff();