首页 > 其他 > 详细

OR1200处理器的可编程中断控制器PIC分析

时间:2014-07-04 08:14:27      阅读:559      评论:0      收藏:0      [点我收藏+]

以下内容摘自《步步惊芯——软核处理器内部设计分析》一书

16.3 可编程中断控制器PIC分析

16.3.1 PIC介绍

      可编程中断控制器Programmable Interrupt ControllerPIC)用来响应各种中断事件,如:键盘事件、串口数据到达等,PIC收集所有的中断,并通知CPU中断到达,后者转入到中断处理例程进行处理。OR1200最多支持32个中断。其功能实现主要依靠两个特殊寄存器:中断屏蔽寄存器PICMR、中断状态寄存器PICSR。通过PICMR可以设置是否屏蔽某些中断,通过PICSR可以知道中断源的信息。PICMRPICSR是第9组特殊寄存器,如表16.7所示。

bubuko.com,布布扣

      中断屏蔽寄存器PICMR的格式如表16.8所示,该寄存器可读、可写。标志IUM中的值表示对应中断是否被屏蔽,IUM0x0,表示所有中断都被屏蔽,IMU0xFFFFFFFF,表示所有中断都没有被屏蔽。在OR1200中,IUM的位数可以配置,配置范围是2-31,这是因为IUM的最低两位始终保持为1,即中断源01设置为不可屏蔽,可以将这两个中断源对应为电源关闭、系统复位。

bubuko.com,布布扣

      中断状态寄存器PICSR的格式如表16.9所示,该寄存器可读、可写。标志IS中的值表示对应中断是否发生并等待处理,IS0x0表示没有中断发生,第i位为1表示第i个中断源发生了中断。判断中断是否发生的方法有电平触发、边沿触发,OR1200支持的是电平触发,此时,IS的第i位实际对应的就是第i个中断源的当前电平值。

bubuko.com,布布扣

      OR1200中断处理过程如下:

      (1)中断源声明中断发生,PICSR[i]1,如果PICMR[i]1,那么通知处理器中断到达

      (2)处理器转入中断处理例程进行中断处理

      (3)中断已处理,中断处理例程通知中断源

      (4)中断源取消中断声明

      (5)中断处理例程设置PICSR[i]0,退出中断处理例程

      注意一点,单独设置PICSR[i]并不会清除中断,必须通知中断源,由后者取消中断声明。

16.3.2 PIC的对外连接关系及相关宏定义

      OR1200处理器中可编程中断控制器PIC的对外连接关系如图16.3所示,通过箭头方向表示该信号是输入还是输出。以spr_xxx开始的接口都是与特殊寄存器读写有关的信号,含义也很明了,此外,pic_int是一个宽度可配置的接口,最大为32,对应32个外部中断源输入。当中断发生时通过intr接口通知CPU模块,其值为1表示中断发生,连接到CPU模块的接口sig_int,同时还要通过pic_wakeup接口通知电源管理模块PM,如果中断发生时,处理器处于SleepDoze模式,PM模块在接收到pic_wakeup1后,会恢复正常模式,参考16.1节中对PM模块的分析。

bubuko.com,布布扣

      OR1200中与可编程中断控制器PIC有关的宏定义如下:

or1200_defines.v
`define OR1200_PIC_IMPLEMENTED             //是否实施PIC模块,PIC模块是可选模块

`define OR1200_PIC_INTS 20                 //定义外部中断源的数目,最多是32个,默认是20个

`define OR1200_PIC_OFS_PICMR 2'd0          //PICMR、PICSR寄存器在第9组特殊寄存器中的索引
`define OR1200_PIC_OFS_PICSR 2'd2

`define OR1200_PICOFS_BITS 1:0

`define OR1200_PIC_PICMR                   //需要定义这个宏,才可以使用PICMR寄存器
`define OR1200_PIC_PICSR                   //需要定义这个宏,才可以使用PICSR寄存器

`define OR1200_PIC_READREGS                //有了这个宏定义,才可以读PIC中的特殊寄存器PICMR、PICSR

`define OR1200_PIC_UNUSED_ZERO


 

16.3.3 PIC代码分析

      PIC的主要代码就是配置PICMRPICSR寄存器,以及依据PICMRPICSR的值判断中断是否发生,分析如下(为了方便理解,笔者改变了代码顺序):

or1200_pic.v
module or1200_pic(
	clk, rst, spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o, pic_wakeup, intr, pic_int
);

……
output		pic_wakeup;	                    //输出到PM模块
output		intr;		                        //输出到CPU模块
input	[`OR1200_PIC_INTS-1:0]	pic_int;    //输入的中断信号,其宽度可通过OR1200_PIC_INTS配置

`ifdef OR1200_PIC_IMPLEMENTED                 

   `ifdef OR1200_PIC_PICMR
      reg	[`OR1200_PIC_INTS-1:2]	picmr; //PICMR寄存器的宽度也和OR1200_PIC_INTS相匹配,但少了两位,
                                         //这是由于中断源0、1不可屏蔽,所以PICMR的宽度比中断输入
                                         //pic_int的宽度少了两位
`else
wire	[`OR1200_PIC_INTS-1:2]	picmr;	
`endif

`ifdef OR1200_PIC_PICSR
reg	[`OR1200_PIC_INTS-1:0]	picsr;	     //PICSR寄存器的宽度也和OR1200_PIC_INTS相匹配
`else
wire	[`OR1200_PIC_INTS-1:0]	picsr;	
`endif

……

//如果spr_cs为1,那么依据spr_addr的最低两位判断指令l.mfspr/l.mtspr的访问目标是PICMR还是PICSR
//picmr_sel为1,表示访问目标是PICMR,picsr_sel为1,表示访问目标是PICSR
assign picmr_sel = (spr_cs && (spr_addr[`OR1200_PICOFS_BITS] == `OR1200_PIC_OFS_PICMR)) 
                   ? 1'b1 : 1'b0;
                   
assign picsr_sel = (spr_cs && (spr_addr[`OR1200_PICOFS_BITS] == `OR1200_PIC_OFS_PICSR)) 
                   ? 1'b1 : 1'b0;

//将pic_int与{picmr,2’b11}相与,得出未屏蔽的中断信息保存在um_ints,注意中断源0、1不可屏蔽,
//与PICMR的值无关,此处直接就是2’b11
assign um_ints = pic_int & {picmr, 2'b11};  

//um_ints不为0,表示有中断发生,设置intr为1,intr输出到CPU模块的sig_int接口
assign intr = |um_ints;

//中断发生后还要通过pic_wakeup接口通知PM模块
assign pic_wakeup = intr;

`ifdef OR1200_PIC_PICMR
always @(posedge clk or `OR1200_RST_EVENT rst)
	   if (rst == `OR1200_RST_VALUE)
		  picmr <= {1'b1, {`OR1200_PIC_INTS-3{1'b0}}};
	   else if (picmr_sel && spr_write) begin
		  picmr <=  spr_dat_i[`OR1200_PIC_INTS-1:2];    //写PICMR,注意最低两位不受影响
	   end
`else
assign picmr = (`OR1200_PIC_INTS)'b1;
`endif

//给PICSR寄存器赋值,PICSR的值取决于指令l.mtspr写入的数据,以及当前发生的外部中断情况,
//从这里也可以发现:当中断发生时,单独使用l.mtspr清除PICSR寄存器并不会使得PICSR的值改
//变,因为外部设备没有取消中断声明,um_ints的值没变,所以必须要外部设备取消中断声明
`ifdef OR1200_PIC_PICSR
always @(posedge clk or `OR1200_RST_EVENT rst)
	    if (rst == `OR1200_RST_VALUE)
		   picsr <= {`OR1200_PIC_INTS{1'b0}};
	    else if (picsr_sel && spr_write) begin 
		   picsr <=  spr_dat_i[`OR1200_PIC_INTS-1:0] | um_ints; 
	    end else
		   picsr <=  picsr | um_ints;
`else
assign picsr = pic_int;
`endif

always @(spr_addr or picmr or picsr)
	  case (spr_addr[`OR1200_PICOFS_BITS])	// synopsys parallel_case
		`OR1200_PIC_OFS_PICMR: begin
		   spr_dat_o[`OR1200_PIC_INTS-1:0] = {picmr, 2'b11};            //读PICMR,最低两位始终为1
		   spr_dat_o[31:`OR1200_PIC_INTS] = {32-`OR1200_PIC_INTS{1'b0}};
		end
	  default: begin
	     spr_dat_o[`OR1200_PIC_INTS-1:0] = picsr;                     //读PICSR
	     spr_dat_o[31:`OR1200_PIC_INTS] = {32-`OR1200_PIC_INTS{1'b0}};
	  end
	endcase
   
`else                                                 //没有配置PIC模块的情况如下

assign intr = pic_int[1] | pic_int[0];                //没有配置PIC模块时,中断0、1还可以使用
assign pic_wakeup= intr;

assign spr_dat_o[`OR1200_PIC_INTS-1:0] = `OR1200_PIC_INTS'b0;
assign spr_dat_o[31:`OR1200_PIC_INTS] = 32-`OR1200_PIC_INTS'b0;
`endif
endmodule


      当中断发生后,PIC模块置高intr,参考图16.3可知,intr连接到CPU模块的sig_int接口,CPU内部的EXCEPTION模块接收该信号,并进行处理,与计时器中断相似,并不会立即响应该中断,而是需要满足一定条件才会响应,如下:

or1200_exception.v
assign int_pending = sig_int & (sr[`OR1200_SR_IEE] | (sr_we & to_sr[`OR1200_SR_IEE]))
                     & id_pc_val & delayed_iee[2] & ~ex_freeze & ~ex_branch_taken  
                     & ~ex_dslot & ~(sr_we & ~to_sr[`OR1200_SR_IEE]);

      各个条件的说明参考计时器中断,当条件满足后,int_pending为1,处理器进入外部中断异常的处理,具体过程与计时器中断一样,此处不再赘述。

 

 

 

 

 

OR1200处理器的可编程中断控制器PIC分析,布布扣,bubuko.com

OR1200处理器的可编程中断控制器PIC分析

原文:http://blog.csdn.net/leishangwen/article/details/36644889

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!