From: acevest Date: Sun, 28 May 2023 05:35:40 +0000 (+0800) Subject: 重写8253的代码,暂时将时钟中断频率限制在20Hz X-Git-Url: http://zhaoyanbai.com/repos/man.rndc.html?a=commitdiff_plain;h=93098e3ed4ec1790bd260bb24a78a3363403af84;p=kernel.git 重写8253的代码,暂时将时钟中断频率限制在20Hz --- diff --git a/kernel/clock.c b/kernel/clock.c index d5aabed..731cf60 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -10,12 +10,13 @@ *-------------------------------------------------------------------------- */ +#include #include #include #include #include -volatile uint32_t jiffies = 0; // TODO uint64 +volatile uint32_t jiffies = 0; // TODO uint64: undefined reference to `__umoddi3' unsigned int sys_clock() { return jiffies; } @@ -23,14 +24,10 @@ void debug_print_all_tasks(); void dump_irq_nr_stack(); void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { - if (jiffies % 100 == 0) { - printl(MPL_CLOCK, "clock irq: %d", jiffies); - } + // if (jiffies % 100 == 0) { + printl(MPL_CLOCK, "clock irq: %d", jiffies); + // } -#if 0 - unsigned long iflags; - irq_save(iflags); -#endif jiffies++; current->jiffies = jiffies; @@ -40,54 +37,17 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { // 同时其下半部分处理时间过长,直到这个时钟中断还没处理完 // 那么这个时钟中断是完全可以打断它,且在这里把这个ticks从0减到负数 // 而这个是uint32_t型,因此会溢出成0xFFFFFFFF - volatile uint32_t ticks; - - ticks = current->ticks; if (current->ticks > 0) { current->ticks--; } - ticks = current->ticks; - -#if 0 - if (current->ticks > TASK_MAX_PRIORITY) { - printl(MPL_X, "current %08x ticks %u", current, current->ticks); - printk("DIE: "); - dump_irq_nr_stack(); - } -#endif assert(current->ticks <= TASK_MAX_PRIORITY); // 防止ticks被减到0后再减溢出 - -#if 0 - task_union *p = 0; - list_head_t *t = 0; - list_head_t *pos = 0; - list_for_each_safe(pos, t, &all_tasks) { - p = list_entry(pos, task_union, list); - if (0 != p->delay_jiffies && jiffies > p->delay_jiffies && p->state == TASK_WAIT) { - p->delay_jiffies = 0; - p->state = TASK_READY; - } - } -#endif - -#if 0 - debug_print_all_tasks(); - debug_print_all_tasks(); - debug_print_all_tasks(); - debug_print_all_tasks(); -#endif - -#if 0 - irq_restore(iflags); -#endif } // 开中断执行这个函数 +// 后续放到一个内核任务中去做,需要先把禁止内核抢占做了 const char *task_state(unsigned int state); void clk_bh_handler() { - unsigned long iflags; - irq_save(iflags); task_union *p = 0; list_head_t *t = 0; list_head_t *pos = 0; @@ -105,5 +65,25 @@ void clk_bh_handler() { // 此处调用这个还是有问题的 debug_print_all_tasks(); - irq_restore(iflags); -} \ No newline at end of file +} + +void setup_i8253(uint16_t hz) { + // 最低频率为18.2Hz(1193180/65536,最大计数值是65536是因为往计数器里写0就从65536开始计数) + assert(hz >= 19); + + const uint8_t counter_no = 0; // 第0个计数器 + const uint8_t read_write_latch = 3; // 0 锁存数据供CPU读;1只读写低字节;2只读写高字节;3先读写低字节,后读写高字节 + const uint8_t mode = 2; // + + const uint8_t cmd = (counter_no << 6) | (read_write_latch << 4) || (mode << 1); // 第0位为0表示二进制,为1表示BCD + + const uint8_t i8253_cmd_port = 0x43; + const uint8_t i8253_data_port = 0x40 + counter_no; + + const uint32_t clock_rate = 1193180; + uint16_t latch = (clock_rate + hz / 2) / hz; + + outb_p(cmd, i8253_cmd_port); + outb_p(latch & 0xFF, i8253_data_port); + outb(latch >> 8, i8253_data_port); +} diff --git a/kernel/setup.c b/kernel/setup.c index 4d2e7f5..5af3618 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -14,7 +14,6 @@ *-------------------------------------------------------------------------- */ #include -#include #include #include #include @@ -23,6 +22,7 @@ extern void init_mm(); extern void setup_gdt(); extern void setup_idt(); extern void setup_gate(); +void setup_i8253(uint16_t hz); extern void detect_cpu(); extern void setup_sysc(); extern void setup_pci(); @@ -37,16 +37,6 @@ extern void reboot(); extern void cnsl_init(); extern void init_ttys(); -#define HZ 100 -#define CLOCK_TICK_RATE 1193180 -#define LATCH ((CLOCK_TICK_RATE + HZ / 2) / HZ) - -void setup_i8253() { - outb_p(0x34, 0x43); - outb_p(LATCH & 0xFF, 0x40); - outb(LATCH >> 8, 0x40); -} - #define VERSION "0.3.1" const char *version = "Kernel version " VERSION " @ " BUILDER " ["__DATE__ @@ -73,11 +63,10 @@ void setup_kernel() { setup_gdt(); setup_idt(); setup_gate(); - - setup_i8253(); - set_tss(); + setup_i8253(20); + setup_sysc(); cnsl_init(); @@ -96,7 +85,7 @@ void setup_kernel() { printk(version); extern tty_t monitor_tty; - // tty_switch(&monitor_tty); + tty_switch(&monitor_tty); void ide_init(); ide_init();