上海文明城市建设网站综合网站开发实训总结
上海文明城市建设网站,综合网站开发实训总结,查企业信息的黄页有哪些,线上营销策划案例1. 从零开始#xff1a;理解8259中断控制器到底是个啥
如果你刚开始接触微机原理或者嵌入式系统#xff0c;看到“8259中断控制器”这几个字#xff0c;可能头都大了。别慌#xff0c;我第一次接触它的时候#xff0c;感觉就像在看天书#xff0c;满屏的ICW、OCW、IRQ、…1. 从零开始理解8259中断控制器到底是个啥如果你刚开始接触微机原理或者嵌入式系统看到“8259中断控制器”这几个字可能头都大了。别慌我第一次接触它的时候感觉就像在看天书满屏的ICW、OCW、IRQ、向量号根本不知道从哪下手。但后来我慢慢发现这东西其实就是一个非常聪明的“前台接待员”它的工作就是帮你管理各种“突发事件”。想象一下你的CPU是公司里最忙的老板他正在处理一份重要的文件执行主程序。突然键盘有人按了一下外部中断请求鼠标动了一下另一个中断请求网卡收到一个数据包又一个中断请求。如果这些事都直接冲进老板办公室汇报老板啥也别干了光应付这些杂事就够了。这时候8259这位“前台”的作用就体现出来了。所有外部设备的中断请求IRQ都先送到它这里它来决定第一现在有没有更紧急的事在忙第二如果同时来了好几个事哪个最优先第三决定好了之后怎么用最清晰的方式通知老板CPU我们这次实验用的Intel 386EX芯片里面就集成了这么两个“前台”一个主片一个从片它们级联起来能管理最多15个外部中断源主片8个从片7个因为从片要占主片一个IRQ。实验箱上把主片的IR6、IR7和从片的IR1这几个“热线”引了出来让我们可以手动按按钮产生单脉冲信号来模拟外部设备的中断请求。这就像给了我们几个可以直接呼叫“前台”的内线电话让我们能亲眼看看这位“前台”是怎么工作的。所以这个实验的核心目标就三个第一打通一条热线单一中断看流程能不能走通第二同时打两条热线双中断看“前台”怎么判断谁先谁后优先级第三让“前台”呼叫另一个“前台”级联看跨部门协作怎么搞。听起来是不是比单纯看寄存器有意思多了接下来我们就手把手从最基础的接线和代码开始把这个“前台”的工作机制彻底摸透。2. 实战第一步搭建单一中断请求的“热线电话”我们先从最简单的开始只接通主片的IR7这一条“热线”。目标就是每次我们按下连接IR7的按键屏幕上就显示一个数字“7”。这相当于测试这条通信线路是否畅通以及整个中断响应流程是否正常。在动手写代码之前有件顶顶重要的事必须做对填写中断向量表。你可以把这想象成在公司通讯录里把“前台”的7号分机IR7对应的处理人中断服务程序的名字和工位写清楚。CPU响应中断后会直接查这个“通讯录”去找该谁处理。对于8086/88系统这个通讯录固定在内存最低端的1KB空间里地址00000H~003FFH。每个“分机号”中断类型号占4个字节前两个字节是处理人座机的分机号偏移地址IP后两个字节是他所在的楼层段地址CS。我们的“7号分机”IR7对应的中断类型号是多少呢这由我们初始化时给主片设置的ICW2决定。在提供的代码里ICW2被设置为08H。ICW2的高5位是我们设定的基址08H低3位由8259根据IRQ号自动填入。所以对于IR7最终的中断类型号就是 08H 7 0FH。那么它在通讯录里的位置中断向量地址就是 0FH * 4 3CH十六进制。所以我们必须把自己写的中断服务程序MIR7的入口地址准确地填到内存 0000:003CH 开始的4个字节里。理解了原理再看代码就清晰了START: PUSH DS MOV AX, 0000H MOV DS, AX ; 设置DS指向中断向量表段地址0 MOV AX, OFFSET MIR7 ; 获取中断服务程序MIR7的偏移地址 MOV SI, 003CH ; IR7的中断向量地址偏移部分 MOV [SI], AX ; 填入偏移地址 MOV AX, CS ; 获取当前代码段地址 MOV SI, 003EH ; IR7的中断向量地址段地址部分 MOV [SI], AX ; 填入段地址 CLI ; 关键在配置8259完成前先关中断防止意外触发 POP DS这段代码执行后当地址总线出现7号中断时CPU会自动到0000:003CH处取出CS:IP然后跳转到我们的MIR7程序去执行。这就是中断向量表的作用它是连接硬件中断号和软件处理程序的桥梁。填好“通讯录”接下来就得初始化“前台”8259本身了也就是写入那4个初始化命令字ICW。这个过程有个固定顺序不能乱; 初始化主片8259 MOV AL, 11H ; ICW1: 边沿触发需要ICW4 OUT 20H, AL ; 写入偶地址端口 MOV AL, 08H ; ICW2: 设置中断类型号基址为08H OUT 21H, AL ; 写入奇地址端口 MOV AL, 04H ; ICW3: 主片表示从片连在IR2上 (0000 0100) OUT 21H, AL MOV AL, 01H ; ICW4: 非缓冲模式非自动结束中断8086/88模式 OUT 21H, AL这里有个容易懵的点为什么有的命令写20H端口有的写21H端口这其实是8259的硬件设计它只有两个端口地址一个偶地址20H一个奇地址21H。CPU通过往这两个端口写数据来下达不同命令。具体怎么区分是ICW1还是OCW2呢靠的是命令字中的特征位。比如写入20H端口的数据如果D4位是18259就认为这是ICW1如果D4D300就认为是OCW2。这个细节我们后面会专门讲现在你只需要记住这个固定顺序和端口就行。初始化完成后我们还需要告诉8259哪些“热线”是允许接进来的。这就要用到操作命令字OCW1它实际上是一个中断屏蔽寄存器。某一位为1就屏蔽对应的IRQ为0则允许。MOV AL, 6FH ; OCW1: 0110 1111即只开放IR4系统串口用和IR7我们实验用 OUT 21H, AL STI ; 所有配置完成打开总中断开关最后主程序进入一个无限循环等待中断AA1: NOP JMP AA1当中断发生时CPU会自动保存现场然后跳转到MIR7执行。在MIR7中我们显示字符‘7’然后最关键的一步发送中断结束命令EOI。MIR7: STI ; 允许中断嵌套如果需要的话 CALL DELAY ; 延时为了看清显示效果 MOV AX, 0137H ; AH01H显示字符功能AL7的ASCII码37H INT 10H ; 调用BIOS中断显示字符 MOV AL, 20H ; 非特殊EOI命令OCW2的一种 OUT 20H, AL ; 发送给8259告诉它这个中断处理完了 IRET ; 中断返回恢复现场如果不发EOI命令8259会认为这个中断还在处理中从而屏蔽掉同级和更低级的中断。所以这个OUT 20H, AL指令虽然短但必不可少。至此一条完整的“热线”就打通了。你可以编译、连接、运行这段代码然后按下实验箱上连接IR7的按键看看屏幕上是不是跳出了一个“7”。这个“7”的出现意味着从硬件触发到软件响应的整个链条全部跑通恭喜你迈出了理解中断机制的第一步3. 优先级之争双中断实验看透8259的调度逻辑单一中断只是热身真正体现8259“智能调度”能力的是当多个中断同时或接连到来的时候。我们的第二个实验就是同时开放主片的IR6和IR7观察它们谁更“优先”。这就像“前台”同时接到了6号和7号两个内线电话他先接哪个后接哪个处理一个的时候另一个又该怎么办在开始前我们要明确8259默认的优先级规则固定优先级IR0最高IR7最低。所以IR6的优先级天生就比IR7高。这意味着如果IR6和IR7的中断请求同时到达8259会优先向CPU报告IR6如果CPU正在处理IR7的中断这时IR6来了8259会立刻打断嵌套IR7的处理转去处理IR6。代码上和单中断实验相比主要增加了几处多填一个中断向量除了IR7的还要把IR6的中断服务程序MIR6的入口地址填到中断向量表里IR6类型号08H60EH向量地址0EH*438H。修改中断屏蔽字在OCW1里要同时允许IR6和IR7。原代码是MOV AL, 6FH0110 1111这屏蔽了IR6。我们需要改为MOV AL, 2FH0010 1111这样IR6和IR7都开放了IR4系统用也保持开放。编写两个中断服务程序MIR6显示字符‘6’MIR7显示字符‘7’。实验的玩法很有意思。你可以先按一下IR7的键屏幕上会显示“7”。在显示“7”之后、程序返回之前也就是在MIR7的IRET指令执行前快速按下IR6的键。你会观察到什么理论上因为IR6优先级更高它会立刻打断MIR7的执行屏幕上紧接着会显示一个“6”。等MIR6执行完返回后CPU才会回到MIR7被打断的地方继续执行虽然我们的MIR7也马上就返回了。这个过程就清晰地演示了中断嵌套。但是这里有个细节需要注意我们的中断服务程序开头都有一条STI指令。这条指令打开了CPU的中断允许标志才使得高优先级中断能够嵌套进来。如果你把STI去掉或者在中断处理过程中一直关中断那么即使IR6的请求来了CPU也不会响应必须等当前的MIR7处理完才行。这就引出了一个重要的设计选择中断服务程序要尽可能短小精悍。如果处理时间很长又一直关着中断就会导致其他紧急事件无法及时响应系统的实时性变差。在实际的嵌入式系统中中断服务程序ISR通常只做最紧急的现场保存和标志位设置然后把耗时的处理任务交给主循环或后台任务去完成。另一个可以验证的点是优先级排队。你可以在没有中断发生时几乎同时按下IR6和IR7的按键或者先按7再快速按6。观察屏幕的输出顺序一定是先‘6’后‘7’。因为即使它们几乎同时到达8259内部的判优电路也会根据固定优先级先选择IR6提交给CPU。只有当CPU处理完IR6并发送了EOI命令之后IR7的中断才会被响应。通过这个简单的双中断实验8259作为硬件中断管理员的“调度策略”就一目了然了。4. 级联应用主从片协同扩大中断管理规模单一芯片只能管理8个中断源这在实际系统中往往不够用。8259支持级联就是把一个从片的INT输出连接到主片的一个IR输入上。这样主片的一个IRQ引脚就能扩展出从片的8个IRQ实际是7个因为从片要占用主片一个IRQ来连接。我们实验箱的386EX芯片内部已经固定把从片连到了主片的IR2上。第三个实验就是要验证这种主从协同工作的模式我们触发从片的IR1SIR1和主片的IR7MIR7看看它们能否正常工作。级联配置比单芯片复杂因为你需要初始化两个8259。从片的初始化流程和主片类似但有几个关键参数不同端口地址不同主片命令端口是20H数据端口是21H从片命令端口是A0H数据端口是A1H。ICW2不同主从片需要设置不同的中断类型号基址防止冲突。代码中主片是08H从片是30H。这意味着从片IR0的中断号是30HIR1是31H以此类推。ICW3必须正确设置这是级联配置的核心。主片的ICW3要指明从片连在哪个IR引脚上我们的例子是IR2所以是0000 0100。从片的ICW3则要告诉它自己的“身份标识”即它连到了主片的哪根线上对于连到主片IR2的从片这个标识就是02H。来看关键的初始化代码片段; 初始化主片8259 (端口: 20H/A0H) MOV AL, 11H OUT 20H, AL ; ICW1 MOV AL, 08H ; ICW2: 主片中断号基址 OUT 21H, AL MOV AL, 04H ; ICW3: 从片连在IR2 (0000 0100) OUT 21H, AL MOV AL, 01H ; ICW4 OUT 21H, AL ; 初始化从片8259 (端口: A0H/A1H) MOV AL, 11H OUT 0A0H, AL ; ICW1 MOV AL, 30H ; ICW2: 从片中断号基址 OUT 0A1H, AL MOV AL, 02H ; ICW3: 从片标识号 (连到主片IR2所以是02H) OUT 0A1H, AL MOV AL, 01H ; ICW4 OUT 0A1H, AL初始化完成后还需要设置中断屏蔽字OCW1。这里要注意必须同时开放主片连接从片的那个IR引脚本例是IR2。如果主片屏蔽了IR2那么从片的所有中断都无法传递到主片也就到不了CPU。MOV AL, 0FDH ; 从片OCW1: 1111 1101只开放IR1 OUT 0A1H, AL MOV AL, 6BH ; 主片OCW1: 0110 1011开放IR2(从片)和IR7IR4用于串口 OUT 21H, AL中断服务程序SIR1处理从片IR1和MIR7的编写与之前类似但发送EOI命令时有重大区别对于从片引发的中断中断处理结束后必须同时向从片和主片都发送EOI命令。SIR1: STI CALL DELAY MOV AX, 0153H ; 显示S INT 10H MOV AX, 0131H ; 显示1 INT 10H MOV AL, 20H OUT 0A0H, AL ; 先向从片发送EOI OUT 20H, AL ; 再向主片发送EOI IRET为什么要发两次因为从片的中断被响应意味着主片的IR2也被服务了。只给从片发EOI从片知道结束了但主片不知道IR2上的中断已经处理完毕这会导致主片IR2及更低优先级的中断一直被屏蔽。所以必须两边都通知到这是一个非常容易踩坑的地方。运行这个程序当你按下连接SIR1的按键时屏幕上会显示“S1”按下MIR7的按键显示“M7”。这个实验成功的关键在于深刻理解两级中断响应链外部中断触发从片IR1 - 从片向主片IR2发送请求 - 主片汇总后向CPU发送INT信号 - CPU响应并从数据总线读取从片提供的中断类型号31H- CPU根据31H*40C4H这个地址去中断向量表找到SIR1的入口并执行。整个过程中主片和从片各司其职协同完成了中断的传递和识别。5. 庖丁解牛深入剖析8259的寄存器与命令字前面我们跟着实验代码一步步配置了各种命令字可能你只是依葫芦画瓢。这一节我们就像拆解一个精密仪器一样把8259的每一个命令字掰开揉碎了看理解每一位到底控制着什么。这才是你真正掌握8259并能自己设计中断系统的关键。首先我们必须牢记端口寻址和命令字识别的规则这是和8259对话的“暗号”。8259只有两个I/O端口一个偶地址如20H/A0H一个奇地址如21H/A1H。CPU通过向这两个端口写入数据来下达命令8259则根据数据中的特征位来判断这是什么命令。我刚开始总是记混后来总结了一个简单的判断流程你可以参考看端口数据是写入偶地址端口还是奇地址端口如果是偶地址端口看数据的D4位。D41这是ICW1初始化命令开始。D40再看D3位。D30是OCW2用来设置优先级方式和发EOID31是OCW3用来查询状态、设置特殊屏蔽等本实验未用到。如果是奇地址端口这需要结合初始化顺序来判断。在写入ICW1之后紧接着写入奇地址端口的一定是ICW2。如果ICW1的D1位SNGL指示为级联模式0那么ICW2之后需要写ICW3主/从片标识。如果ICW1的D0位IC4指示需要ICW41那么ICW3或ICW2如果没有ICW3之后需要写ICW4。以上都不是那就是OCW1中断屏蔽寄存器。现在我们逐一看看每个命令字的具体含义。ICW1写入20H/A0H的格式如下D7 | D6 | D5 | D41 | D3 | D2 | D1 | D0 ? | ? | ? | 1 |LTIM|ADI |SNGL|IC4D3 (LTIM): 0边沿触发1电平触发。我们实验用边沿触发所以是0。D1 (SNGL): 0级联模式1单片模式。我们实验有主从片所以是0。D0 (IC4): 1需要ICW40不需要。8086/88模式必须用ICW4所以是1。 我们实验设置的是11H0001 0001含义就是需要ICW4、级联模式、边沿触发。ICW2写入21H/A1H比较简单它就是中断类型号的高5位T7-T3。低3位T2-T0由8259根据IRQ号自动填入。我们主片设08H从片设30H就是为了让主从片的中断号分布在不同的区域避免冲突。ICW3级联时才需要是主从片通信的“接头暗号”。主片的ICW38位的哪一位为1就表示对应的IR引脚上连接了从片。我们是从片连主片IR2所以主片ICW3是04H0000 0100。从片的ICW3低3位有效则填写自己的标识码即它连到了主片的哪个IR引脚。我们是从片连主片IR2所以从片ICW3是02H。ICW4用于定义一些高级工作模式。我们实验用的是最普通的8086模式和非自动结束中断所以设置01H0000 0001即可。初始化完成后在工作过程中我们主要通过OCW1来动态屏蔽或开放中断。它就是直接对应8个IR引脚的屏蔽位写1屏蔽写0开放。这是我们在实验中多次修改的寄存器。OCW2写入20H/A0H则用来控制中断结束方式和优先级循环。它的格式中D7-D5R, SL, EOI的组合决定了功能。我们实验里一直用的MOV AL, 20H就是OUT 20H, AL这是一个固定的非特殊EOI命令R0, SL0, EOI1用于通知8259当前中断处理结束。OCW2还能设置优先级自动循环等模式但在我们的基础实验中未涉及。把这些位都搞清楚之后你再回头看实验代码里的那几行OUT指令就不会觉得是魔法了。每一行都是在精确地设置这个中断控制器的某个特定开关。理解到这一步你才算真正把8259“驯服”了。6. 避坑指南与高级玩法从实验到实战的思考做完三个基础实验你可能觉得已经掌握了8259。但在真实的项目开发中仅仅让代码跑通是远远不够的。我结合自己以前踩过的坑分享几个需要特别注意的地方和可以深入探索的方向。第一个大坑中断共享与冲突。我们的实验每个IRQ只接了一个按键所以很单纯。但在实际系统中多个设备可能共享一个IRQ例如老的PCI设备。这时候在你的中断服务程序里就不能简单地认为进来的一定是你的设备。标准的做法是先读取设备的状态寄存器确认中断确实是由你的设备产生的然后再处理处理完后发送EOI。如果不是你的设备产生的直接返回即可不发EOI由真正的处理程序来发。这需要硬件和驱动的协同设计。第二个坑中断服务程序ISR的设计。我强烈建议在ISR里只做最低限度、最紧急的工作。比如对于串口接收中断ISR里最好只把数据从硬件寄存器读到内存缓冲区然后设置一个“有数据待处理”的标志就立刻返回。把数据解析、业务处理这些耗时操作放到主循环里。我们的实验代码里用了CALL DELAY来延时以便观察这在实战中是绝对要避免的它会严重拖慢系统响应速度。记住ISR的执行时间越短越好。第三个需要注意的点中断嵌套的深度控制。我们实验里开了STI允许嵌套。在复杂系统里中断嵌套可能很多层。你需要评估最坏情况下中断嵌套的栈空间消耗确保不会导致栈溢出。有时候为了避免复杂嵌套带来的不可预测性可能会在某个高优先级ISR里暂时关闭中断CLI处理完关键部分再打开。但这需要非常谨慎的权衡。说完避坑我们再来看看基于现有实验的高级玩法。原始文章里提到了一个“选做实验”用中断控制LED灯移动这个想法就很好它把中断机制和具体的硬件控制8255并口控制LED结合起来了。你可以在此基础上继续发挥模拟一个“中断负载测试”编写程序让两个中断源以不同的频率随机触发可以用定时器模拟然后在ISR里记录时间戳。最后分析这些时间戳看看高优先级中断对低优先级中断的延迟到底有多大中断响应是否及时。这能让你对系统的实时性有直观感受。探索特殊中断结束方式我们一直用的是一般EOI。8259还支持特殊EOI在OCW2中指定结束哪个IRQ号和自动EOI在ICW4中设置中断响应后自动发EOI但慎用容易导致重复嵌套。你可以修改代码试试自动EOI模式观察现象有何不同。你会发现在自动EOI模式下因为中断一响应就自动结束所以低优先级中断也能打断正在执行的高优先级ISR因为高优先级的“正在服务”状态立即被清除了这会彻底改变优先级行为。尝试优先级轮转通过OCW2设置优先级自动轮转或特殊轮转模式。比如让刚服务完的IRQ优先级降到最低。然后设计一个实验观察在这种模式下多个中断请求是如何被“公平”调度的。最后给想更深入的同学一个建议尝试脱离实验箱的代码框架自己从头写一遍。从定义中断向量表、初始化8259、写ISR到主循环全部自己构思。过程中你肯定会遇到各种问题比如忘了发EOI导致中断一次后死锁或者屏蔽字设错了某个中断死活不响应。解决这些问题的过程才是知识内化的最快路径。8259虽然是一个老芯片但它所体现的中断管理思想——优先级、屏蔽、嵌套、结束——在现代的ARM Cortex-M系列芯片的NVIC嵌套向量中断控制器中依然存在只是变得更强大、更易用。学好8259就像是掌握了内功心法再学任何新的中断控制器都会觉得似曾相识上手极快。