“五一”假期前后这约五天时间,终于将MIPS中断系统进行了板级验证及实例测试。因为老师给的交叉编译工具不会用,所以测试代码完全用MIPS汇编编写。使用MARS而没有用QtSpim,其实我觉得SPIM这个东西比较复杂,但是确实很好用,但是MARS是开源,可以根据你的需求修改这个汇编器(这个汇编器功能很强大,笔者至今没有用熟练)。据传说MARS可以支持link异常处理程序,但是我没有这么做,手动链接也是一样的,本来我们做的就是最底层的事情。
首先,必须要强调的是MIPS中断有别于Intel中断,两者用本质上的区别。Intel中断使用中断控制器8259控制中断,但是MIPS体系架构不同,它仅仅使用了很简单巧妙的方式处理中断。据我个人浅薄认识,8259是用来扩展中断源,而并不能认为只有8259可以控制中断,它控制的更多的是优先级。其实对中断响应等更具备控制权限的是CPU,所有的外部信号都需要由处理器控制是否响应等等。笔者,已经模仿8259的功能写了一个片上中断控制器,而今天所讲的中断系统并不包含8259,仅仅是捕获最原始的中断源,即将中断源的输出信号直接与Cause(IP)位的某一位相连。
为什么讲这么多有关8259的事情,因为这里有一个误区,也是我们做中断做了N多久遗留的误区。就是我们认为中断请求信号仅仅是一个脉冲,这个脉冲可能持续一个时钟周期,也可能持续N个时钟周期,然而这种想法一定是错的。《Intel微处理器》P356页有一个标准的INTR输入和INTA输出的时序图。所有INTR信号都是一个从低电平越变到高电平的信号,并持续保持高电平。另外,《微机原理与接口技术》这本书中P273页详细描述了8253的方式0的功能:中断信号发生器。如下图所示。当计数到0后,将产生一个持续的高电平。
我想说的是,用FPGA去验证和我们实际学到的知识理论可能会有很大的不同。就拿我现在最不理解的来说,《Intel微处理器》P357页描述使INTR输入为边沿触发信号,其处理办法就是将中断请求信号作为D触发器的CLK,如下图所示。
这种方式在FPGA中绝对是没法实现的,因为所有人都知道做SOC最重要的就是时钟。时钟是所有时序电路的灵魂,用一个中断请求信号作为CLK,非常不稳定,我甚至怀疑是否允许这样做。其实,还有更多的例子。我觉得不能讲书中的电路图或者设计方式生搬硬套到FPGA设计中,而是要自己进行设计和转换。还有,Intel的东西只是一种参考、一种理论,并不是绝对的,并不是一成不变的。
说了那么多有关Intel的东西,只是想做个比较。与之对照的自然是MIPS。MIPS采用很简单的方式处理中断。其实,说简单点而就是仅使用CP0的部分处理器实现,很多工作都由软件来进行。同时,N多MIPS手册或者《see mips run》都强调MIPS更乐于使用Compability方式而非Intel的向量化方式。首先,我觉得采用向量化的方式最大的好处就是快速,快速地定位到产生向量的中断处理程序中。须知Intel可以处理256个中断。而此中断包含了异常(如溢出)。而MIPS仅有不多的异常,此异常包含中断。这个概念最开始让我们很是琢磨不清,一会儿异常包含中断,一会儿中断包含异常。但是仔细想想,无论哪种方式都只是非正常执行外的一种处理方式。道理很类似,非常类似。所有的中断都只对系统不会产生负面影响的内部或外部的要求系统处理的信号,系统可以不理睬。而一场则是负面影响,系统若不长时间处理会产生极大的危害。
所谓Compatibility中断模式,其实我个人认为也是由于在MIPS中,一场包含中断,系统只提供8个中断源接口(2个软件、6个硬件)。不要认为,接口少。可以讲中断控制器的INTR信号直连如其信号源,很多MIPS处理器都是这样。由于我们只是做一个有关学习的SOC,所以直接将硬件中断源与之相连。因此,很多按键灯外设需要认为地将INTP信号持续拉高。
处理流程可以完全按照MIPS手册的General Exception Handler来处理。这里唯一需要注意的是,异常也是有优先级的。这个优先级可以使用全译码的方式控制,也可以使用诸如硬件排队器、菊花链的方式控制。而Cause(ExcCode)位是保持最近的一次产生异常的编码。一定是最近的一次,比如,在一条ADD指令的Fetch阶段产生了一个外部中断,而当执行后发现产生了OverFlow,那么Cause(ExcCode)位也必须按照优先级的不同修改,尽管中断是先发生的。当然这也解释了中断优先级最低的原因,中断pending信号是一直保持的,就算我的处理器不响应也不会对处理器产生危害,但是溢出等其它异常就可以,因此中断具有最低优先级。
其实,做中断与CP0这块仿真时,我建议大家不要怕搓,大胆尝试,大胆地去设计和验证。当你发现你的设计不稳定或者有bug时就证明你的设计一定有问题,就需要修改。这部分的仿真我大概前前后后陆陆续续做了近两个月,虽不是一直在做,但是确实在一直在思考。我看到很多书,或者很多硕士论文,或者很多pudn的代码。这个部分的东西都做的很烂。这个部分最重要的不是完全和MIPS的一模一样,而是可以用,可以响应中断,我觉得就可以了。有的学校的MIPS处理器声称可以6级中断嵌套,我觉得这是完全没必要的。中断嵌套只是保护处理器、保护堆栈区的一种方式,只要有稳定的中断处理程序谁都可以中断嵌套。因此,只要攻破了一级中断,你也就一定可以攻破多级中断。因为非向量化式的中断完全由INT-entry程序判断中断优先级。向量化的中断我也实现过,那个优先级是由译码或者排队器做的。可以说嵌套靠的不是控制单元,而是优先级。所以最重要的是单级中断。一定要做出一个可以板级验证的单级中断,再去思考多级中断。笔者就犯了冒进的例子。血的教训。
处理中断还有一个难点就是理解原子性,这个概念其实是在OS课中才接触到的。我也是因为不明白为什么一定要原子,去看了AST的《现代操作系统》。有疑问的推荐那本书。
就中断系统而言,会发生原子操作的地方在于即将处理异常的时候,需要同时利用时钟上升沿做三件事情:1)将EXL置位;2)将PC保存入EPC;3)修改Cause(ExcCode)。另外,当异常处理程序结束时,也要进行原子操作:1)将EPC的值返回给PC;2)清楚EXL位。
这就是一个经典的生产者——消费者模型。很多指令解决了这一问题,比如set and lock(IBM的好型),XCHG指令等等。这是MIPS体系结构中一个很经典的设计,完全由简单的控制信号控制同时写入,简单迅速。
剩下的所有内容其实都是靠软件来实现,硬件就做这么些事情。笔者的中断系统是靠秒闪灯验证,这也是老师给的验证方式(真心简单方便还好)。主程序和中断程序共同维护一段儿内存,该内存变量为second。使用TC0(FPGA实现的8253)方式0每隔1S产生一个中断信号,进入中断处理程序。在中断处理程序中,将second增加1写入内存。主程序初始化TC0,随后进入死循环,不断读入second值,与pre second比较,若相等则继续循环,若不等,则将当前second值写入LED地址,继续循环。

其实,说起来很简单,但是实现起来走的弯路会很多。很多人做了这东西,认为自己可以正常处理了或者可行了,我觉得都是很不负责任的。这东西是必须由特定的程序来验证的,而并不是指令集,只要一条指令就可以验证了。还有一点,我觉得很重要。就是搞FPGA设计不要完全参照别人的,有些网上的代码或者什么的都是很取巧的,比如我印象最深的读取RAM地址中的值时,诸多的程序都写成assign rd <= RAM[addr];试问,如果一个RAM可以用assign语句来如此迅速的读取内容,那么我们为什么还要GPR了呢?地址一边,RAM_rd立刻就改变,这是组合电路,并不是存储器读的真正时序。我觉得搞FPGA,不能用语言的技巧使你的仿真可以正确,而是要先设计,所有的程序必须完全按照你自己的设计来,这样就够了。你的设计可以不好,但是这种东西,一定可以实现,一定可以拿到板子上跑。

【原创】MIPS中断系统的板级验证及实例测试的更多相关文章

  1. 【原创】MIPS浅议之——中断系统之我见

    最近,准确的说应该是最近两个月的时间,我都在研究MIPS的异常与中断.或者可以说,最近这两个月,我才真正了解中断系统的整个结构和处理流程以及为什么要这样做?这段时间我最大的体会就是以前我们在“计算机组 ...

  2. 板级支持包(BSP)

    板级支持包(BSP)是介于主板硬件和操作系统中驱动层程序之间的一层,一般认为它属于操作系统一部分,主要是实现对操作系统的支持,为上层的驱动程序提供访问硬件设备寄存器的函数包,使之能够更好的运行于硬件主 ...

  3. bsp板级支持包

    定义 2作用 ▪ 建立让操作系统运行的基本环境  ▪ 完善操作系统运行的环境 3开发流程     1定义 板级支持包(BSP)是介于主板硬件和操作系统中驱动层程序之间的一层,一般认为它属于操作系统一部 ...

  4. Linux中断(interrupt)子系统之一:中断系统基本原理【转】

    转自:http://blog.csdn.net/droidphone/article/details/7445825 这个中断系列文章主要针对移动设备中的Linux进行讨论,文中的例子基本都是基于AR ...

  5. Linux中断(interrupt)子系统之一:中断系统基本原理

    这个中断系列文章主要针对移动设备中的Linux进行讨论,文中的例子基本都是基于ARM这一体系架构,其他架构的原理其实也差不多,区别只是其中的硬件抽象层.内核版本基于3.3.虽然内核的版本不断地提升,不 ...

  6. u-boot启动流程分析(2)_板级(board)部分

    转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...

  7. TMS320F28335项目开发记录9_28335中断系统

    28335中断系统 1.中断系统 在这里我们要十分清楚DSP的中断系统. C28XX一共同拥有16个中断源,当中有2个不可屏蔽的中断RESET和NMI.定时器1和定时器2分别使用中断13和14.这样还 ...

  8. ZYNQ入门实例——三种GPIO应用、中断系统及软硬件交叉触发调试

    一.前言 Xlinx的ZYNQ系列SOC集成了APU.各种专用外设资源和传统的FPGA逻辑,为ARM+FPGA的应用提供助力,降低功耗和硬件设计难度的同时极大提高两者间传输的带宽.之前在研究生课题中使 ...

  9. 痞子衡嵌入式:快速定位i.MXRT600板级设计ISP[2:0]启动模式引脚上电时序问题的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是一种快速定位i.MXRT600板级设计ISP[2-0]启动模式引脚上电时序问题的方法. 我们知道恩智浦i.MXRT600是主打音频市场的 ...

随机推荐

  1. windows server 2003 负载平衡的详细设置步骤(转载)

    声明:本文为转载. 当把一台服务器(包括Web服务器.FTP服务器或者流媒体服务器等等)放入网络中之后,随着客户端数量的不断增加,人们往往需要功能更强大.处理速度更快的服务器.为了解决这个问题,如果将 ...

  2. Eclipse配置CAS client

    1.新建一个Maven项目 2.Next,选择 3.输入group id 和 artifact id -->  Finish 4.项目创建完成的目录结构 编辑pom.xml文件,写上依赖 注意把 ...

  3. IE10访问Apache2.4卡死的问题

    windows环境下,使用IE10访问Apache2.4时,服务器经常卡死 找到EnableSendfile on,在下一行添加如下配置解决: AcceptFilter http none Accep ...

  4. php 中 isset()函数 和 empty()函数的区别

    首先这两个函数都是用来测试变量的状态: isset()函数判断一个变量是否在 如果存在返回true  否则返回false empty()函数判断一个变量是否为空,如果为空返回true 否则返回fals ...

  5. AD,Group

    DataTable dtUser = GetEmptyDT(); Dictionary<DirectoryEntry, string> test1 = GetUserAndGroup(cl ...

  6. Aspose.Words 总结

    生成答题卡 try { string tempPath = @"D:\moban\ttt.doc"; //Open document and create Documentbuil ...

  7. js简单实现删除记录时的提示效果

    删除记录时的提示效果,挺人性化的,实现的方法有很多,在本文为大家介绍下使用js是如何实现的 样式 复制代码代码如下: <style type="text/css">  ...

  8. 网页制作常见的面试题(怎样兼容IE6/IE7/火狐浏览器)

    1.IE6双边距问题? 在IE6的浏览器中明明设置的是10px的margin却为什么显示的是20px的margin其实这个Ie6的一个双边距BUG例如:<style type="tex ...

  9. Codeforces Round #344 (Div. 2) C. Report

    Report 题意:给长度为n的序列,操作次数为m:n and m (1 ≤ n, m ≤ 200 000) ,操作分为t r,当t = 1时表示将[1,r]序列按非递减排序,t = 2时表示将序列[ ...

  10. lua中的时间函数

    -- 获取当前的格林尼治时间print(os.time())-- 获取当前时间的字符串表示,形如:11/28/08 10:28:37print(os.date())-- 获取当前日期的字符串表示,形如 ...