Reimplemented PIT Timer. Sleep is now a syscall. Also made docs/ that contains some info so i don't forget.

This commit is contained in:
2024-05-07 20:25:48 +02:00
parent e617f4fe69
commit 41e0b93f52
10 changed files with 137 additions and 62 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ CC = i386-elf-gcc
LD = i386-elf-ld
AS = nasm
CFLAGS = -ffreestanding -fno-builtin -fno-stack-protector -nostdinc -mgeneral-regs-only -m32 -march=i386 -Iinclude -Wall
CFLAGS = -ffreestanding -fno-builtin -fno-stack-protector -nostdinc -mgeneral-regs-only -m32 -march=i386 -Iinclude -Wall
SRC = ./src
BUILD = ./build
View File
+11
View File
@@ -0,0 +1,11 @@
=== System Calls ===
Syscall handlers are prefixed by 'sys_'
Syscalls can be called using interrupt 0x80
The EAX register should countain a syscall number
Here's a list of syscalls: (and their numbers)
syscall(0) : Sleep()
Args: EBX - Number of miliseconds to sleep for
+47
View File
@@ -0,0 +1,47 @@
#ifndef TIMER_H
#define TIMER_H
#include <stdint.h>
#include <idt.h>
#include <pic.h>
#include <screen.h>
#define CHANNEL_0 0x40 // Offset it by 1 or 2 for ch1 and ch2
#define COMMAND 0x43
#define INPUT_CLK 1193182
static uint32_t* timerTicks = (uint32_t*)0x1000;
__attribute__ ((interrupt))
void timerHandler(intFrame_t* iframe) {
*timerTicks += 1;
// TODO: Improve the cursor rendering
if (*timerTicks % 500 == 0) putcAt(' ', cursor.x, cursor.y);
else if (*timerTicks % 250 == 0) putcAt(127, cursor.x, cursor.y);
sendPicEOI(0);
}
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
if (channel > 2 || opMode > 7) { return; }
__asm__ volatile ("cli");
// Send command - bits 7-6 channel, 5-4 Access mode, 3-1 operating mode, 0 - Should be zero in x86
outb(COMMAND, ((channel << 6) | (3 << 4) | (opMode << 1)));
// Send frequency
uint16_t freq = INPUT_CLK / hz; // I solved an equation to figure this out
outb(CHANNEL_0 + channel, (uint8_t)freq);
outb(CHANNEL_0 + channel, (uint8_t)(freq >> 8));
__asm__ volatile ("sti");
}
void setupTimer() { // Sets up IRQ 0 - PIT
idtSetGate(0x20, timerHandler, INT_GATE_FLAGS);
unsetIrqMask(0);
setPitPhase(0, 2, 1000); // Default setup: 1000Hz - 1 tick per 1ms
}
#endif
+10 -12
View File
@@ -1,27 +1,25 @@
#ifndef SYSCALL_H
#define SYSCALL_H
#include <screen.h>
#include <pit.h>
// System call count
#define MAX_SYSCALLS 2
void sys_test0() {
fgColor = YELLOW;
print("Syscall 0 - Test\n");
fgColor = FG_COLOR;
}
// Args: ebx - number of miliseconds
void sys_sleep() {
uint32_t ms;
__asm__ volatile ("movl %%ebx, %0" : "=r"(ms));
void sys_test1() {
fgColor = CYAN;
print("Syscall 1 - Test\n");
fgColor = FG_COLOR;
uint32_t requiredTicks = *timerTicks + ms;
while (*timerTicks != requiredTicks) { // Wait...
__asm__ volatile ("sti;hlt;cli;");
}
}
// System call table
void* syscalls[MAX_SYSCALLS] = {
sys_test0,
sys_test1,
sys_sleep,
};
// int 0x80 - Syscall interrupt, handled by this function
+8
View File
@@ -0,0 +1,8 @@
#ifndef TIME_H
#define TIME_H
void sleep(uint32_t ms) {
__asm__ volatile ("int $0x80" : : "a"(0), "b"(ms));
}
#endif
+22 -21
View File
@@ -4,43 +4,44 @@
#include <stdint.h>
#include <idt.h>
#include <pic.h>
#include <system.h>
#include <screen.h>
#define INPUT_CLK 1193180
#define CHANNEL_0 0x40 // Offset it by 1 or 2 for ch1 and ch2
#define COMMAND 0x43
#define INPUT_CLK 1193182
uint32_t timerTicks = 0;
static uint32_t* timerTicks = (uint32_t*)0x1000;
__attribute__ ((interrupt))
void timerHandler(intFrame_t* iframe) {
timerTicks++;
*timerTicks += 1;
// TODO: Improve the cursor rendering
if (timerTicks % 500 == 0) putcAt(127, cursor.x, cursor.y);
else if (timerTicks % 250 == 0) putcAt(' ', cursor.x, cursor.y);
if (*timerTicks % 500 == 0) putcAt(' ', cursor.x, cursor.y);
else if (*timerTicks % 250 == 0) putcAt(127, cursor.x, cursor.y);
sendPicEOI(0);
}
void setupTimer() {
idtSetGate(32, timerHandler, INT_GATE_FLAGS);
unsetIrqMask(0);
}
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
if (channel > 2 || opMode > 7) { return; }
__asm__ volatile ("cli");
// Source: https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interval_Timer
void timerPhase(uint32_t hz) {
uint16_t div = INPUT_CLK / hz;
// Send command - bits 7-6 channel, 5-4 Access mode, 3-1 operating mode, 0 - Should be zero in x86
outb(COMMAND, ((channel << 6) | (3 << 4) | (opMode << 1)));
outb(0x43, 0x36); // Tell PIT that we're setting channel 0
outb(0x40, div & 0xff); // Low byte
outb(0x40, div >> 8); // High byte
}
void sleep(uint32_t ticks) {
uint32_t eticks = ticks + timerTicks;
// Send frequency
uint16_t freq = INPUT_CLK / hz; // I solved an equation to figure this out
outb(CHANNEL_0 + channel, (uint8_t)freq);
outb(CHANNEL_0 + channel, (uint8_t)(freq >> 8));
while (timerTicks != eticks); // Should ignore overflows unlike '<'
__asm__ volatile ("sti");
}
void setupTimer() { // Sets up IRQ 0 - PIT
idtSetGate(0x20, timerHandler, INT_GATE_FLAGS);
unsetIrqMask(0);
setPitPhase(0, 2, 1000); // Default setup: 1000Hz - 1 tick per 1ms
}
#endif
+16 -16
View File
@@ -1526,22 +1526,22 @@ db 00h,\
00h,\
00h,\
00h
db 00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
00h,\
0FEh
db 0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF,\
0xFF
;; End of visible ascii characters
times 2048-($-$$) db 0
+11 -6
View File
@@ -9,7 +9,8 @@
#include <string.h>
#include <graphics.h>
#include <keyboard.h>
#include <timer.h>
#include <pit.h>
#include <time.h>
#define PROMPT "#> "
@@ -54,7 +55,6 @@ void main() {
__asm__ volatile ("sti");
setupTimer();
timerPhase(1000); // 1 kHz
setupKeyboard();
// Run Interactive Shell Program
@@ -166,7 +166,7 @@ void main() {
drawCircle(1500, 600, 300, WHITE);
fillCircle(950, 750, 75, rgb(0xa2, 0xd6, 0xf9));
//read('q'); // Wait until we get a 'q'
read('q'); // Wait until we get a 'q'
clear();
} else if (strcmp(input, "help") == 0) {
print("Available Commands:\n");
@@ -179,6 +179,7 @@ void main() {
print(" ls | Lists all available files\n");
print(" memmap | Prints the memory map and info\n");
print(" reboot | Reboots the system\n");
print(" sleep | Sleeps for input number of seconds\n");
print(" test | Performs tests\n");
} else if (strcmp(input, "ls") == 0) {
printFiletable(filetable);
@@ -186,6 +187,13 @@ void main() {
printPhysicalMemmap();
} else if (strcmp(input, "reboot") == 0) {
outb(0x64, 0xFE);
} else if (strcmp(input, "sleep") == 0) {
if (*args == '\0') continue;
uint32_t ms = atoi(args) * 1000; // Convert seconds to miliseconds
if (ms == 0) continue;
sleep(ms);
} else if (strcmp(input, "test") == 0) {
print("Running Tests...\n");
uint8_t buf[512];
@@ -206,9 +214,6 @@ void main() {
} else {
print("[ FAIL ]\n");
}
print("Syscall Test:\n");
__asm__ volatile ("movl $0, %eax; int $0x80"); // Syscall(0);
__asm__ volatile ("movl $1, %eax; int $0x80"); // Syscall(1);
print("\nTests Finished!\n");
} else {
+11 -6
View File
@@ -9,10 +9,11 @@ Legend:
- [x] Multistage Bootloader
- [ ] Bootloader reads filetable to find files
- [ ] The almighty 'printf()'
- [!] Makefile refactorin'
- [x] Write down where stuff is in memory (in notes.txt)
- [ ] "Text" mode (not actually)
- [ ] Scrolling
- [x] Scrolling
- [ ] Scroll-back
- [ ] Color codes (and just multicolor text in general)
- [x] VESA BIOS Extensions
@@ -34,12 +35,15 @@ Legend:
- [x] Triangles (3D?!!???)
- [x] Rectange :)
- [x] Circle!
- [_] Filled verisons
- [ ] Interrupts
- [x] Filled verisons
- [ ] Interrupts
- [x] IDT Setup (idt.h)
- [x] Exception handling
- [ ] Hardware/software interrupts
- [ ] Syscalls! (int 0x80)
- [x] Hardware/software interrupts
- [x] Syscalls! (int 0x80)
- [ ] IRQ 0 - PIT
- [ ] IRQ 1 - Keyboard
- [ ] IRQ 8 - CMOS Real time clock
- [ ] Math
- [ ] Trigonometry
- [ ] Sine
@@ -63,6 +67,7 @@ Legend:
- [ ] NAN
- [x] E (eulers number)
- [x] PI
- [ ] Floating point macros/functions
- [ ] Filesystem
- [ ] Utility for filesystem building (not just an assembly file)
- [x] Filetable
@@ -77,6 +82,7 @@ Legend:
- [ ] Symbolic
- [ ] Hard
- [ ] System Calls
- [ ] Sleep()
- [ ] Write()
- [ ] Read()
- [ ] Open()
@@ -103,7 +109,6 @@ Legend:
- [ ] stdin
- [ ] stdout
- [ ] stderr
- [ ] printf
- [ ] Memory manager
- [x] Memory map
- [x] Print mem map