元芳你怎么看

本网站主要用于记录我个人学习的内容,希望对你有所帮助

0%

中断和动态时钟显示

外部硬件中断

外部硬件中断就是从处理器外面来的中断信号,优先级很高。

它的实现是通过两个信号线引入处理器内部的,分别叫NMIINTR

非屏蔽中断(Non Maskable Interrupt,NMI)

需要两条线的原因是不一定每一个中断的优先级都需要立刻处理。当涉及到非屏蔽中断,通常是一些紧急且必须立即处理的硬件事件。

硬件中断的优先级管理:某些系统可能会使用外部硬件中断来处理中断请求的优先级。这意味着当多个中断同时发生时,不是所有中断都需要立即处理。处理器可以为不同的中断信号分配不同的优先级,从而决定哪些中断需要立即处理,而哪些可以等待。

需要立即处理的:

  • 电池电量低,系统会发出一个中断告诉处理器快没电了。
  • 内存访问电路有校验错误(读取错误)。

不那么着急处理的:

举个例子,一个嵌入式系统可能有多个外部硬件设备连接到处理器,包括键盘、鼠标和网络适配器。如果用户同时按下键盘上的按键和鼠标点击,系统可以根据设定的中断优先级来决定哪个中断首先得到处理。通常情况下,键盘中断可能具有较高的优先级,因为用户通常期望键盘响应更快,而鼠标中断则有较低的优先级,因为它不太紧急。

中断信号的来教叫做 中断源。传统的兼容模式下,NMI的中断源通过一个与非门连接到处理器,处理器的NMI引脚是高电平有效,中断信号是低电平有效,也就是NMI引脚是低电平则没有中断。

即使NMI与非门的输出为高时,也不能立刻被识别,还需要至少维持4个以上的时钟周期才算有效。

处理器还应当知道发生了什么事,以便于采用适当的处理措施。每个类型的中断都被统一编号,被称为中断类型号、中断向量或者中断号。而有些比较严重的事件就在实模式下被赋予了统一的中断号 2 ,一旦发生 2 号中断,处理器和软件系统通常会放弃继续正常工作的念头,也不会试图纠正已经发生的问题和错误。

可屏蔽中断(Interrupt Request,INTR)1,7,4,9,2,5

由于可能有多台设备同时发送中断请求,但是处理器每次只能处理一个中断,这就需要一个中间层进行仲裁,优先处理优先级更高的。个人计算机中使用最多的就是8259芯片。Intel处理器允许256个中断,8259负责15个不固定的中断号,8个中断输入引脚。引脚的IR0优先级向IR7递减,从片是级联在主片的IR2引脚。

个人计算机中有两块8259芯片,并且两块的关系是级联:主片的INT输出直接送到处理器INTR引脚;从片的INT输出送到第一块的引脚2上,一共提供15个中断信号。

  • 主片的引脚 0 接的是系统定时器/定时器芯片,主片的端口号是0x200x21
  • 从片的引脚 0 接的是实时时钟芯片(RTC),从片的端口号是0xa00xa1

8259内部有中断屏蔽寄存器(IMR)8位寄SPSCQueue *SPSCQueueInit(int capacity);
void SPSCQueuePush(SPSCQueue *queue, void *s);
void *SPSCQueuePop(SPSCQueue *queue);
void SPSCQueueDestory(SPSCQueue *);
即使中断从8529发送出去,最终解释权也归处理器。处理器内部的标志寄存器有个IF标志位(中断标志)。当IF为0,中断信号被忽略。

对于IF标志位的处理有两条指令:cli(Clear Interrupt Flag)和sti(SeT Interrupt flag)。

中断嵌套:当一个中断事件正在处理时,如果来了优先级更高的中断事件,允许暂时中止当前的中断事件,先为优先级较高的中断事件服务。

实模式下的中断向量表

中断处理实际上就是处理器执行一段与该中断有关的指令。因为可以识别256个中断,理论上就需要256段程序,在实模式下,处理器要求将它们的入口点集中存放在内存中从地址0x000000x003ff,共1kb的空间内,这就是中断向量表(Interrupt Vector Table,IVT)。

每个中断在中断向量表中占2个字,分别是中断处理程序的偏移地址和段地址。

中断发生时,处理器执行完当前指令后会立刻为硬件服务,会先响应中断,告诉处理器处理该中断,然后向8259芯片所要中断号。

处理器拿到中断号会干下面的事情:

  1. 保护断点的现场。将标志寄存器FLAGS压栈,清除其IF位和TF位(陷阱标志)。然后将当前的CSIP压栈。(清除IF是因为在此期间不再响应硬件中断,如果希望更高优先级的中断嵌套,可以编写程序时,使用sti开放中断)
  2. 执行中断程序。拿到中断号,将其乘4,得到其在中断向量表的偏移地址。从表中取出来对应段地址和偏移地址传入CSIP
  3. 返回到断点继续执行。所有中断处理程序的最后一条必须是中断返回指令iret。依次恢复IPCSFLAGS的原始数值。

NMI不会从外部获得中断号,自动生成中断号码 2,其他过程相同。

实时时钟、CMOS RAM 和 BCD编码

计算机为什么能精准显示日期和时间?在外围设备控制器芯片ICH内部,集成了实时时钟电路(RTC)和两小块由互补金属氧化物材料组成的静态存储器(CMOS RAM)。实时时钟电路负责计时,日期和时间存储在静态存储器中。存储方式通常是二进制编码的十进制数(BCD)。

实时时钟是全天候跳动的,即使断电。因为主板上有个小电池供电。

日期和时间信息存储在CMOS RAM中,通常有128字节,日期和时间信息只占了一小部分容量,其他空间用于保存整机的配置信息(硬件类型、工作参数、开机密码、辅助设备启动顺序)

CMOS RAM的访问需要通过两个端口:0x70或者0x74是索引端口,用来指定CMOS RAM内的单元;0x71或者0x75是数据端口,用来读写对应单元内的内容。

偏移地址 内容 偏移地址 内容
0x00 0x01 闹钟秒
0x02 0x03 闹钟分
0x04 0x05 闹钟时
0x06 星期 0x07
0x08 0x09
0x0A 寄存器A 0x0B 寄存器B
0x0C 寄存器C 0x0D 寄存器D

下面的例子是用来获取当时是星期几:

1
2
3
mov al,0x06
out 0x70,al
in al,0x71
  1. out 0x70, al: 这是一个输出指令,用于将AL寄存器中的值(在这里是0x06)写入到I/O端口0x70。在x86架构中,0x70端口通常用于控制实时时钟芯片的寄存器。这个操作可能用于设置实时时钟的某些配置,例如将其配置为读取或写入日期和时间信息。

  2. in al, 0x71: 这是一个输入指令,用于从I/O端口0x71读取数据,并将读取的数据存储到AL寄存器中。在这个上下文中,0x71端口通常用于读取实时时钟的状态或数据,例如当前的时间信息。

端口的最高位是控制NMI中断的开关。为0时,允许NMI中断到达处理器;为1时,阻断所有NMI信号,它不是中断信号,但是能控制与非门的输出。其他七个比特实际上用于指定CMOS RAM单元的索引号。

初始化8259、RTC和中断向量表

寄存器A:寄存器A通常用于配置RTC的中断频率。通过设置寄存器A的值,你可以定义RTC中断的触发频率,例如每秒触发一次。这通常涉及到配置寄存器A的低4位(Rate Selector)。

寄存器B:寄存器B通常包含一些控制中断的位。它允许你启用或禁用RTC中断,并可能还有其他控制位,例如24小时模式、BCD码格式等。

寄存器C:寄存器C用于指示中断的发生。当RTC触发中断时,寄存器C的某些位会被设置,以告知系统发生了中断。

寄存器D:寄存器D通常包含一些额外的控制位,可能与其他RTC功能有关。