Autor Thema: Uhrzeit abrufen  (Gelesen 10233 mal)

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« am: 26. November 2011, 18:17 »
Hi, also ich würde gern die aktuelle Uhrzeit abrufen können. Im i-net hab ich gelesen das es mit diesem Assembler befehlen geht:
xor ah, ah  //ah auf 0 setzen
int 1ah      //interrupt aufrufen
Dann sollte in ex und dx n counter drinn sein (millisec oder so denk ich)...
So dann dachte ich, ich schreib sowas:
static inline unsigned long getTime(void){
    unsigned long h,l;
    asm volatile ("xor %ah, %ah");
    asm volatile ("int $0x1a": "=c" (h), "=d" (l));
    return ((h<<16) | (l & 0x00ff));
}

Also ob das mit dem =c und =d als Ausgabe tut weiß ich net, bitte klärt mich auf.
Aber wenn ich des so mit make mache (benutze die makefile usw. von hier ausm tut) kommt kein Fehler aber wenn ich den "kernel" in qemu starte stürzt alles ab und qemu startet den "Rechner" neu. Hat da einer einen Plan?

Danke schön

edit:
Wie kann man bei dem code quote hier des highlighting anschalten?
Und kann man die makefile so ändern dass es erkennt ob sich auch Header geändert haben im Programm?
« Letzte Änderung: 26. November 2011, 18:24 von evildrno »

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #1 am: 26. November 2011, 18:46 »
Hi,

dieser Code sieht sehr nach Realmode-Code aus. Bist du noch im Realmode? Ansonsten funktioniert der nämlich nicht.
Die Uhrzeit kannst du im Protected Mode über den CMOS Baustein auslesen, im Wiki gibt es einen entsprechenden Artikel.

Für dein Makefile und Highlighting Problem habe ich leider keine Lösung

Grüße,
LittleFox

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 26. November 2011, 18:55 »
Da du dich mit deinem Kernel (vermutlich) im Protected-Mode und nicht im Real-Mode bewegst, hast du keinen zugriff auf BIOS und/oder DOS Interrupt Routinen. D.h. int 0x1a kannst du vergessen. Du kannst die Uhrzeit aber auch relativ einfach aus dem CMOS auslesen.

Ansonsten solltest du dich nicht darauf verlassen, dass zwischen den beiden asm-Blöcken die Registerwerte erhalten bleiben.

also
asm volatile ("xor %%ah, %%ah\n"
              "int $0x1a" : "=c"(h), "=d"(l) : : "eax");
oder gar
asm volatile ("int $0x1a" : "=c"(h), "=d"(l) : "a"(0) );
und dann sollte es in der return zeile sicher (l & 0xffff) heißen.

Syntax-Highlighting geht so weit ich weiß hier nicht.
Und was die makefiles angeht: du kannst die Header mit in die dependance liste packen. Gcc kann dir das auch generieren (siehe dazu hilfe zu gcc -M -MT)

Edit: Das mit dem '=c' sollte gehen, kopiert dir halt komplett ecx nach h. Weil du h als long hast.
« Letzte Änderung: 26. November 2011, 19:01 von MNemo »
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 26. November 2011, 19:15 »
So ja also bin im 32bit protected mode, kompiliere ja mit 32bit  (gcc -m32 ...)^^ . So ok dann wäre das ja geklärt, dann hab ichs noch mit dem CMOS getestet und auch die Sekunden in BCD bekommen, bräuchte aber eher so Millisekunden -.-
Aber Danke euch, gerade das der Assemblerbefehl direkt hintereinander ausgeführt werden sollte macht Sinn, aber hab ich einfach nicht dran gedacht, nützt mir leider gerade noch nicht so viel  :?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 26. November 2011, 19:27 »
Die RTC löst nicht bis in den Millisekundenbereich auf, dafür müsstest du was anderes hernehmen. Mit anderen Zeitquellen bekommst du aber nur Zeitdifferenzen hin, keine absolute Uhrzeit.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 26. November 2011, 19:39 »
Ah ok, d.h. auch mit int 1ah hätt ich nur Sekunden gehabt? Gut dann is des auch geklärt. Ja es geht eig. darum n kleines spiel zu machen und dann eben so z.b. die Spielzyklen Zeit zu steuern, also bei 20fps muss ich halt schaun ob seit dem letzten durchlauf  50 ms vergangen sind, wenn nicht z.B. in ne Methode gehen die nicht viel tut, dann wieder zurück und schaun ob jetzt ca. 50 ms rum sind usw.
Gut da könnte man ja ggf. beim starten des spiels schauen wieviel spielzyklen ich in einer sek. in etwa hin bekomm, und das dann so irgendwie steuern aber des is ja alles doof. Wie funzt des dann z.b. bei java mit getcurrenttimemillis, oder einer anderen Programiersprache(ja ich weis das Java ne VM is, aber auch die muss ja irgendwie die Millisekunden vom echten System bekommen...).
Aber mal OT: kann ich mit lidt wieder interrupts im PM benutzen oder wie hab ich das zu verstehen?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 26. November 2011, 19:49 »
Wie gesagt, Zeitdifferenzen kriegst du genauer hin. Wenn du den PIT auf 100 Hz laufen lässt (relativ normale Einstellung), dann kriegst du alle 10 Millisekunden einen Interrupt und das wäre dann die Genauigkeit, die du bereitstellen kannst. Du kannst relativ einfach den TSC nehmen, aber den musst du erstmal mit was anderem (normal mit dem PIT) kalibrieren, weil er von der CPU und ihrer Taktfrequenz abhängt (d.h. möglicherweise ändert sich die Geschwindigkeit auch, wenn die CPU dynamisch die Taktrate ändert). LAPIC-Timer und HPET wären noch Stichwörter für weitere mögliche Zeitquellen, die du dir anschauen kannst.

Ich schätze mal, für die Auflösung, die du brauchst, ist der PIT das richtige (und das ist auch der Timer, den alle Tutorials beschreiben, um z.B. Multitasking zu machen).
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 26. November 2011, 20:00 »
OK Danke, dann muss ich wohl doch mit IRQs und dem PIC und so arbeiten, dachte ich komme darum herum ein Interrupt Handler zu machen, weil das hab ich beim Tutorial überblättern noch nicht so richtig verstanden und sieht n bisschen komplizierter aus... naja dann hab ich des WE was zu tun^^
Muss ich um dem PIC programmieren zu können auch im RM sein oder geht das dann auch im PM? Wie gesagt hab das alles noch nicht so richtig ferstanden. Aber wenn ich dann schon mit dem PIC arbeite kann ich auch meine Tastatur Abfrage ohne polling machen^^(Siehe mein anderen Thread, wens interresiert XD)

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 26. November 2011, 20:15 »
Das geht alles im Protected Mode.

Und ja, wenn du schon Interrupts bearbeitest, dann kannst auch gleich deinen Tastaturtreiber richtig machen. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 26. November 2011, 23:18 »
Soo, hab nun mal versucht die Inerrupts zu behandeln. Aber nur mit mäßigem Erfolg:
Hab den Code vom Tut. hier also http://git.tyndur.org/?p=tutorial.git;a=commit;h=28b2b4cbda58827f241c9ef030ae2997a9a4f3e8
handle_interrupt hab ich so umgeschrieben das es mir immer die interrupt-Nummer noch ausgibt und nicht auf int 32 reagiert, der irgendwie mit qemu immer ausgelöst wurde. Soweit so gut und wenn ich im prog dann irgendwo zb. asm("int $3") benutzt hab hat das auch super getan, aber auf Tastatureingaben oder den PIT den ich mit void pit_init(int freq)
{
   freq = 1193182 / freq;
   outb(0x43, 0x34);
   outb(0x40,freq & 0xFF);
   outb(0x40,freq >> 8);
}
eingestellt hab, hat mein handler einfach mal garnichts gemacht...
Muss man da noch was spezielles machen das der auch auf Tastatur und PIT (ich denk doch mal auch Hardware Interupts im allg) reagiert???

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #10 am: 26. November 2011, 23:24 »
Hi,

Interrupt 32 ist IRQ 0 -> also der PIT ;)
Die Interrupts vorher sind Exceptions, die 3 ist z.B. eine Breakpoint-Exception ;)
Also musst du für dein Problem nur die Handler an Interrupt [32 + IRQ-Nummer] registrieren.

Grüße,
LittleFox

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 27. November 2011, 11:17 »
Hä? Warum ist jetzt int 32 vom PIT ausgelöst? und warum Löst er dann nur beim Start 1 mal aus? Eingestellt ist er ja auf Intervall, des hab ich schon getestet (also das er nur 1. auslöst). Und warum steht dann hier: http://www.lowlevel.eu/wiki/IRQ#IRQ_Tabelle
Dass 0 vom PIT ausgelößt wird bzw 0x08. Also vom 32 hab ich noch nirgends was gelesen. Also der Interrupt S''''' macht mich grad echt fertig XD

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 27. November 2011, 11:34 »
Hallo,


welcher INT dann von einem IRQ tatsächlich benutzt wird hängt von der Konfiguration des PIC ab, das ist relativ beliebig einstellbar. littlefox geht wohl von dem aus was die meisten machen, IRQ0..15 auf die INTs 32..47 mappen, aber das muss man nicht unbedingt so machen (auch wenn es so schon recht sinnvoll ist).

Hast Du den überhaupt die PICs richtig konfiguriert?


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 27. November 2011, 11:53 »
Gut das weiß ich jetzt natürlich auch nicht ob ich da alles richtig gemacht hab. Also ich hab dieses hier http://git.tyndur.org/?p=tutorial.git;a=commit;h=28b2b4cbda58827f241c9ef030ae2997a9a4f3e8
genommen und in mein Projekt eingearbeitet, und dann nur noch in der init() von der main.c   
init_gdt();
init_intr();
Aufgerufen. Da dann, wenn ich später zb in der init() mit asm(int $xyz) nen interrupt ausgerufen hab, der auch so angekommen ist in dem interrupt handler von der intr.c, hab ich eig. gedacht da wäre alles richtig, aber wie gesagt Hardware Interrupts kommen nicht an, aber wenn ich z.b durch null teile kommt wiederum ne exeption an... Kein Plan.
Ich hab also sozusagen die kritischen Sachen direkt von intr.h und intr.c und der stub.S übernommen nur den Handler n bissle umgeschrieben, um z.b die Interrupt Nummer auszugeben usw. da ich kein kprintf hab. Wenn man da natürlich noch irgendwelche Einträge zusätzlich machen muss fehlen die bei mir. Aber ich hab auch kein Plan welche ich brauch für den PIT und Keyboard
« Letzte Änderung: 27. November 2011, 12:26 von evildrno »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 27. November 2011, 12:49 »
init_pic() konfiguriert den PIC. Und zwar mappt er IRQ 0 nach Interrupt 0x20 (= 32). Der PIT hat den IRQ 0 (und damit bei dieser Konfiguration Interrupt 32) und die Tastatur IRQ 1 (Interrupt 33).
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 27. November 2011, 13:37 »
Muuhhaa, ok ich fang jetzt gleich des heulen an.
Also du meinst es müsste auf 32 der pic und auf 33 der Tastatur Dinger liegen, aber warum  wird dann handle_interrupt(...) nich aufgerufen wenn ich auf die tastatur ein hacke bzw warum wird handle_interrupt nur einmal vom pit aktiviert??? Also wntweder bin ich einfach zu blöd und muss mal 2-3 Tage abstand davon nehmen um wieder klar zu kommen, oder es is der wurm drinn...

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #16 am: 27. November 2011, 13:41 »
Hi,

das klingt sehr danach das du kein EOI (EndOfInterrupt) sendest - dann werden nämlich keine weiteren IRQ's angenommen.
Der Code müsste im Tutorial aber eigentlich enthalten sein. Hab aber gerade nicht nachgeschaut.

Grüße,
LittleFox

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 27. November 2011, 13:54 »
OH MEIN GOTT, DANKE DANKE!!!
Ja des mit dem EOI wars dann auch ;-) hab des wohl beim Handler neu schreiben als nicht wichtig angesehen und rausgelöscht!. Ok jetzt tut alles und danke für die Geduld mit mir ^^.
Naja jetzt mach ich mich mal zuerst drann den "Tastatur Treiber" ohne Polling zu machen.
Wie ist des denn wenn ich den Processor mit hlt schlafen lege, und ich dann auf die Tastaur Eindresche macht er wieder weiter, so dass ich ihn zwsichen den einzelnen Tastatur Eingaben schlafen legen kann, oder?

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #18 am: 27. November 2011, 14:12 »
Hi,

wenn du die Interrupts vor dem hlt nicht deaktivierst müsste der Prozessor bei einem Tastendruck wieder aufwachen.
Allerdings wird er auch für jeden anderen Interrupt aufwachen also auch bei IRQ0

Grüße,
LittleFox

evildrno

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 27. November 2011, 18:33 »
Hehe ja genau des is jetzt mein Problem, ich lege den Prozessor jetzt wenn der Interrupt von was anderem kommt (z.b PIT) gleich schlafen (mit hlt), also noch im Interrupt. Da is jetzt meine frage ob des so gut geht: Hier der mein Thread zum Thema Tastatur Abfragen (so wie scanf usw)
http://forum.lowlevel.eu/index.php?topic=2946.0
« Letzte Änderung: 27. November 2011, 19:06 von evildrno »

 

Einloggen