• 从零开始操作系统-08:计时器


    这一节主要主要是计时器。

    所需要的文件在Github:https://github.com/yongkangluo/Ubuntu20.04OS/tree/main/Files/Lec7-ExternalInterrupt

    计时器:

    可编程间隔计时器:PIT(Programmalbe Interval Timer)8254

    使用APIC自带的Timer:
    更高精度并且能对CUP单独设置;

    概述而言就是:
    使用 两个Count来做计时:
    FEE0 0380H :Initial Count;
    FEE0 0390H :Current Count

    if(ICR){
    	do{
    		CCR = ICR;
    		while(CCR--);
    		Interrput;
    	} while(Timer Model)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    计数器的行为设置:
    在这里插入图片描述

    手动测量频率
    使用一个固定已知频率的时钟做参考:
    Lapic 计时器发生中断时,经过了多少的间隔:
    F t i m e r = F C P U / k I C R / F t i m e r = t / F R T C F_{timer} = F_{CPU} / k\\ ICR / F_{timer} = t / F_{RTC} Ftimer=FCPU/kICR/Ftimer=t/FRTC
    使用CPU来计算是不准确的,可能存在超频的可能。所以需要用手动测量。使用主板上的COMS来作为时间参考。

    步骤如下:

    1. 安装RTC和Lapic Timer 的临时中断服务例程
    2. 配置RTC的频率(1024赫兹)
    3. 打开中断
    4. 写入ICR
    5. PIE置位
    6. 阻塞
    7. 党LAPIC Timer触发之后,计算频率并关闭RTC
    8. 清楚临时例程
    Code
    void
    timer_init(uint32_t frequency)
    {
        timer_init_context();
        cpu_disable_interrupt();
        // 配置LAPIC中的中断寄存器; One shot, 中断号是202
        apic_write_reg(APIC_TIMER_LVT,
                       LVT_ENTRY_TIMER(APIC_TIMER_IV, LVT_TIMER_ONESHOT));
        // Time Driver设置为64
        apic_write_reg(APIC_TIMER_DCR, APIC_TIMER_DIV64);
        timer_ctx->base_frequency = 0;
        rtc_counter = 0;
        apic_timer_done = 0;
        // 安装APIC对一个的中断程序
        intr_subscribe(APIC_TIMER_IV, temp_intr_routine_apic_timer);
        intr_subscribe(RTC_TIMER_IV, temp_intr_routine_rtc_tick);
        // 开启RTC计时器
        rtc_enable_timer();    
        // 在APIC中写一个很大的常数                              
        apic_write_reg(APIC_TIMER_ICR, APIC_CALIBRATION_CONST); 
        // 开启中断
        cpu_enable_interrupt();
        wait_until(apic_timer_done);
        assert_msg(timer_ctx->base_frequency, "Fail to initialize timer (NOFREQ)");
        kprintf(KINFO "Base frequency: %u Hz\n", timer_ctx->base_frequency);
        timer_ctx->running_frequency = frequency;
        timer_ctx->tick_interval = timer_ctx->base_frequency / frequency;
        
        intr_unsubscribe(APIC_TIMER_IV, temp_intr_routine_apic_timer);
        intr_unsubscribe(RTC_TIMER_IV, temp_intr_routine_rtc_tick);
        apic_write_reg(APIC_TIMER_LVT,
                       LVT_ENTRY_TIMER(APIC_TIMER_IV, LVT_TIMER_PERIODIC));
        intr_subscribe(APIC_TIMER_IV, timer_update);
        apic_write_reg(APIC_TIMER_ICR, timer_ctx->tick_interval);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在这里插入图片描述

    方法主要跟着B站Up主做的,B站视频链接在:https://www.bilibili.com/video/BV1jL4y1s7X6/?spm_id_from=333.788&vd_source=72ce864f895f9fbf22b81450817f2875

  • 相关阅读:
    【Linux系统满足产品实时性需求】
    MyBatis与Spring的集成
    欧洲历史脉络
    Python 操作pdf文件(pdfplumber读取PDF写入Excel)
    Java实现简易版的【图书管理系统】
    刷题笔记27——图论并查集
    java-php-python-ssm能源类网站平台计算机毕业设计
    安卓逆向案例——X酷APP逆向分析
    链表| leecode刷题笔记
    k8s中无法获取到nginx-ingress的客户端真实ip地址x-forwarded-for
  • 原文地址:https://blog.csdn.net/lyk82698/article/details/127985458