[第14天] 高分辨率和键盘输入

好久没有更新了。最近搞怎么黑人搞上瘾了。所以没有时间更新这个了。当然不能半途而废。

今天的主要内容是更新分辨率和接收键盘输入。分辨率这部分我早就实现了。因为原来320×200的分辨率看着实在恶心。而且这部分也不难,主要涉及硬件,所以直接跳过。

基本原理:

键盘的原理是什么?学过电子的应该知道,TM的映射那么多键需要很多线,而且还有组合这不是坑爹吗?我也不是很清楚,概括来说就是有个单片机一直在扫描电路,看看有没有接通,接通了就传给计算机相应代码。具体可以看这个。搞过下面的那个板子的同学肯定也能理解原理。但是如何做到这么多键位我就有点糊涂了。

danpianji

按下键盘的按键后,硬件会传入一个代码,这个代码代表什么字符就需要系统判断。一般的映射是Original XT scan code set。按下A就传如1E,松开传入9E。我也实现了这个。

代码实现:

其中接收部分之前就已经完成。就是传入到FIFO里。然后要做的就是解释代码。为了方便起见,用个数组。下面就是主要代码。

参考:

  1. OS dev
  2. Computer engineering
  3. linux atkbd.c
  4. how keyboard works

[第13天]定时器优化

      强迫症改不了,本来想好12,13天一块写掉,因为能记录的内容不多,但这样总感觉不舒服。所以还是分开写了。

      今天是定时器的优化,为什么要优化呢?这跟处理鼠标和键盘数据的道理是一样的。定时器会触发一个中断,而处理中断的时候CPU不能做其他的事情。所以要加快中断处理。因为之前的是char类型的FIFO,在时间处理上不太够,因此重写使用int类型的FIFO32。

优化思路:

  • 定时器链表:因为每个定时器都有一个超时时间,只要按超时的早晚顺序把这些定时器链接起来即可,每次只要看看第一个定时器有没有超时即可。
  • 哨兵:这是为了简化程序,哨兵是链表经常使用的技术。在这里,是设置一个永远不会超时的定时器,实际上就是0xffffffff。由于这个的存在,实际上这个操作系统在经历 (0xffffffff/中断频率) 秒后就会失效。

      所以得出的中断处理的代码如下。其他代码见github

疑问:

      我就想不通,为什么不是每次中断然后把这个中断信息存到FIFO里,然后在主程序里处理呢?这就是处理鼠标和键盘数据时的做法。直到第16天,我才恍然大悟,确实定时器是特别的。因为定时器涉及到任务切换。仔细想想,如果我是多任务的,然后定时器的数据都由主任务处理,那么在执行其他任务的时候就不能处理定时器了,就再也不能任务切换了。但也可以每个任务都处理相同的定时器,这得多麻烦。所以在中断时直接处理是合理的,而且直接导致后面的任务切换也在inthandler20里。妙及了。

性能:

      作者是通过计数来测试性能的。作者的电脑是有多老,我的计数结果差不多是其百千倍。。所以看看结果如何。

couter4

[第12天]定时器

      6月简直就是废了,大作业加考试,没时间搞自己的东西了。我擦,换了个键盘,打字真tm舒服。

      接着干《30天自制操作系统》,时间太久,都不知道第12天到底干了什么了。原来是定时器。为什么操作系统需要定时器呢?因为中断,因为要多任务分配时间槽。MD,一下子就明白了多任务的原理。以前完全不了解。以前我是这么想的:多任务肯定需要调度,那么必须有一个主任务一直在运行,那么其他任务怎么运行?

PIT:

      操作系统使用的是PIT(Programmable interval timer),就是用他来产生中断,然后处理中断。而这个跟硬件的时钟频率密切相关。基本上用的都是Intel 8254。如下设置,可以使其产生100HZ的中断频率,具体原因看说明。然后bochs有点问题,可能是我配置不当。时钟总是不对。virutalbox和qtemu都没有问题。

中断处理:

      接下来就是中断处理。跟鼠标键盘事件一样先要注册中断处理程序,具体见github。然后可以扩展到真的定时器,原理:设置超时时间,每次中断后比较是否超时。当然这是最简单的,效率不高,可以优化很多。这里就展示一下核心的中断处理程序。

 多个定时器:

      这个的实现原理与图层类似,就是设定一个数组,存放对应的定时器信息。有了这个就可以进行多任务了。但是今天和明天都还有很多优化要做。

      顺便提一句,GCC的优化是必要的。GCC -O1直接将编译好的代码缩小了近2/3。但是这会导致之前第十天说的bug,所以还是跟作者一样把检测内存的代码改成了汇编。好像volatile也可以起到作用。最后是今天结果。

counter