<?xml version="1.0" encoding="gbk"?> <rss version="2.0"><channel> <title>定阅帖子更新</title> <link>http://www.broadkey.com.cn/XML.ASP</link><description>TEAM Board - 意得法电子</description> <copyright>TEAM 2.0.5 Release</copyright><generator>TEAM Board by TEAM5.Cn Studio</generator> <ttl>30</ttl><item><link>http://www.broadkey.com.cn/Thread.asp?tid=78 </link><title>PowerPC&amp;nbsp;VxWorks&amp;nbsp;BSP分析(3.2)——POWERQUICC硬件</title><author>page</author><pubDate>2009-11-26 21:23:35</pubDate><description><![CDATA[<a name="_Toc161134743"><u>1.2 内存管理单元MMU</u></a>
<div><a href="http://img1.51cto.com/attachment/200903/3/109393_1236097317LOZb.jpg"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" onclick="window.open(&quot;http://blog.51cto.com/viewpic.php?refimg=&quot; + this.src)" border="0" alt="clip_image018" src="http://img1.51cto.com/attachment/200903/3/109393_12360973213aFV.jpg" height="241" /></a></div>
<div><a href="http://img1.51cto.com/attachment/200903/3/109393_1236097327TCCU.jpg"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" onclick="window.open(&quot;http://blog.51cto.com/viewpic.php?refimg=&quot; + this.src)" border="0" alt="clip_image020" src="http://img1.51cto.com/attachment/200903/3/109393_1236097332GJa1.jpg" height="111" /></a></div>
<a name="_Toc161134744"><u>1.3 MPC860</u></a>中断
<div><a href="http://img1.51cto.com/attachment/200903/3/109393_1236097333QmR6.jpg"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" onclick="window.open(&quot;http://blog.51cto.com/viewpic.php?refimg=&quot; + this.src)" border="0" alt="clip_image022" src="http://img1.51cto.com/attachment/200903/3/109393_1236097335wFbd.jpg" height="79" /></a></div>
<div>MPC860的整个中断体系结构有3个模块：PowerPC 核、SIU 中断控制器SIU IC(SIU Interrupt Controller)和CPM 中断控制器CPMIC(CPM Interrupt Controller)。</div>
<div>PowerPC Core 是指令执行单元，使用异常(Exception)的目的就是要打断它的正常执行，使它转入处理紧急事件的异常处理程序中执行。对于每一类异常，异常发生后PowerPC跳转执行的位置是不同的。这些不同的位置组成了一个表&mdash;&mdash;异常向量表。不同类型的异常在异常向量表中的偏移量不同。例如系统重启异常在异常向量表中的偏移量是0x100，机器自检异常的偏移量是0x200，而外部中断在异常向量表中的偏移量是0x500等等。</div>
<div><a href="http://img1.51cto.com/attachment/200903/3/109393_12360973368ms0.jpg"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" onclick="window.open(&quot;http://blog.51cto.com/viewpic.php?refimg=&quot; + this.src)" border="0" alt="clip_image024" src="http://img1.51cto.com/attachment/200903/3/109393_1236097350qRQU.jpg" height="195" /></a></div>
<div>SIU 中断控制器负责管理8 个外部中断源(IRQ0 ～7 )和8 个内部中断源(Level0～7)。其中IRQ0一般用作不可屏蔽中断，通过NMI 向PowerPC 内核请求中断，其余15个通过IREQ请求中断。对于8 个内部中断源，包括周期性的中断时钟(PIT)、实时时钟(RTC)、PCMCIA以及CPM等，用户可以通过对寄存器的操作，把它们设定为Level 0～7中的任何一级。这16个中断源之间的优先级SIU IC 已经设定了。其中IRQ0的优先级最高，Level0 其次，IRQ1 再次，依此类推，Level7的优先级最低。</div>
<div><a href="http://img1.51cto.com/attachment/200903/3/109393_1236097354ZguZ.jpg"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" onclick="window.open(&quot;http://blog.51cto.com/viewpic.php?refimg=&quot; + this.src)" border="0" alt="clip_image026" src="http://img1.51cto.com/attachment/200903/3/109393_1236097354wBAm.jpg" height="188" /></a></div>
<div>在SIU IC进行SIU中断处理时，有几个重要的寄存器与之相关。它们是中断悬挂寄存器SIPEND、中断屏蔽寄存器SIMASK和中断向量寄存器SIVEC。</div>
<div>CPM中断控制器是对SIU中断控制器的下一级扩展。它管理通信处理模块的各个中断源，并向SIU IC申请中断处理。CPIC接收12个外部中断源和17个内部中断源的中断请求，经过屏蔽和判优处理后，把中断请求送往SIU中断控制器。通过设置CPIC的配置寄存器，CPM在SIU IC中的优先级可以是Level0～7中的任何一级，并且所有的CPM中断源都将以这个优先级向SIU 申请中断。在CPM IC内部，它也为每个中断源分配了一个中断向量号，并且分配了不同的优先级，还可以编程设定哪个中断源为最高优先级。</div>
<div>在CPM的中断源中，如果一个中断源有多个子功能可以产生中断请求，并且每一项子功能的中断请求都可以屏蔽，那么这个中断源称为子块可屏蔽中断。例如，对串行管理通道SMC(Serial Management Channels)，每一个SMC有一个事件寄存器SMCE和一个屏蔽寄存器SMCM。用户可以通过对SMCM进行编程，屏蔽掉某项子功能的中断请求功能。假如用户要使用中断接收功能，就应该置位SMCM的RX位以打开接收中断。在中断服务程序中还要读取SMCE，以判断是哪个子功能产生的中断。如果SMCE的RX位已被置位，就表明产生了接收中断，应进入接收中断处理函数。</div>
<div><a href="http://img1.51cto.com/attachment/200903/3/109393_123609735822tj.jpg"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" onclick="window.open(&quot;http://blog.51cto.com/viewpic.php?refimg=&quot; + this.src)" border="0" alt="clip_image028" src="http://img1.51cto.com/attachment/200903/3/109393_1236097367HpiF.jpg" height="78" /></a></div>
<div>CPM IC中提供了一些可编程寄存器。通过对这些寄存器进行设置，可以设定CPM IC的工作方式。这些寄存器分别是CPM中断配置寄存器CICR、CPM中断屏蔽寄存器CIMR、CPM中断向量寄存器CIVR、CPM中断悬挂寄存器CIPR和CPM中断服务寄存器CISR。</div>
<div>编写MPC860中断应用程序主要有两个方面的内容：一个是中断初始化程序，另一个是中断服务程序。中断初始化程序首要的工作是初始化中断寄存器，包括打开SIMASK对应的屏蔽位、使能外部中断。如果要使用SIU的外部中断，应该初始化SIEL寄存器，以设定中断是低电平触发还是低跳变触发。如果使用了CPM中断，还应该初始化CICR、CIMR寄存器，以设定CPM在SIUIC中的中断优先级，以及它自身内部的最高优先级中断源。对于子块可屏蔽中断源，还应该打开对应的事件屏蔽寄存器。只有在初始化这些寄存器后，中断源产生的中断才能得到响应。</div>
<div>对于外部中断，PowerPC内核接收到中断请求信号后，会转入异常向量表中的外部中断偏移地址处(0x500)执行。这一段最大长度为256个字节的代码，也可以说是SIU中断的服务程序。在中断初始化程序中，还必须把SIU中断服务程序放到正确的位置。中断服务程序是中断产生后自动跳转执行的程序，它对中断进行处理。对于其中比较复杂的CPM中断，它有两级处理程序，分别是SIU中断服务程序和CPM中断服务程序。</div>
<div><a href="http://img1.51cto.com/attachment/200903/3/109393_1236097374wkiu.jpg"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" onclick="window.open(&quot;http://blog.51cto.com/viewpic.php?refimg=&quot; + this.src)" border="0" alt="clip_image030" src="http://img1.51cto.com/attachment/200903/3/109393_1236097382Tkpf.jpg" height="176" /></a></div>
<div>在SIU中断服务程序中，要读取产生SIU中断的中断向量号，根据中断向量号判断中断源，然后跳转到对各个中断源处理的服务程序中执行。如果读到的中断向量号对应的是CPM，要转入CPM中断服务程序中执行。</div>
<div>CPM又有29个中断源，每个中断源对应不同CPM中断向量号。在CPM中断服务程序中，也要读取CPM中断向量号，然后根据中断向量号调用对应的中断处理程序。这样，所有的CPM中断源，在进入中断处理程序之前，都经过了SIU IC和CPM IC两级处理。另外，由于MPC860是RISC处理器，它有许多通用寄存器，在中断服务程序中应该把影响到的寄存器压入到堆栈中，在退出中断服务程序之前再恢复。</div>
<div>下面以CPM的SMC1用作串口，使用中断接收数据为例，说明MPC860的中断应用程序编写过程。</div>
<div>本程序的主函数是main()。它调用smc_init()进行smc初始化，然后循环等待接收数据。smc_init()是初始化函数。它设定smc1的工作方式，初始化接收描述字，然后初始化中断寄存器，并且把SIU中断服务程序拷贝到异常向量表的0x500处。Initbrn()是SIU中断服务程序，也就是外部中断产生后的入口程序。它读取SIU的中断向量号，如果是CPM中断，就调用CPM中断处理程序CPMHandler（），在这个程序中再读取CPM中断向量号，如果是CPM中断，就调用CPM中断处理程序CPMHandler()，在这个程序中再读取CPM中断向量号，处理SMC1发送过来的数据。</div>
<div>另外，函数getimmr()的作用是用汇编指令得到芯片内端口寄存器的基址，getmsr()的作用是读取机器状态字（MSR）的值，getevt（）利用MSR的值得到的异常向量表的基址。整个程序代码如下：</div>
<div>#include &quot;pc860.h&quot; /*MPC860寄存器宏定义头文件*/</div>
<div>struct dprbase *pdpr; /*指向双端口内存基址的地址*/</div>
<div>void smc_init() /*初始化SMC函数*/</div>
<div>{</div>
<div>void intbrn(); /*定义SIU中断服务程序*/</div>
<div>int *ptrs,*ptrd; /*SIU中断服务程序搬移的源和目的地址*/</div>
<div>char intlv1=4；/*CPM中断级别*/</div>
<div>pdpr=(struct dprbase *)(getimmr() &amp; 0xFFFF0000); /*得到端口寄存器的基址*/</div>
<div>&hellip;&hellip; /*初始化SMC的寄存器和工作参数，如工作模式，波特率等*/</div>
<div>&hellip;&hellip; /*初始化串口数据收发缓冲区的描述字，注意要把接收缓冲区描述字RxBD的中断位置为1*/</div>
<div>ptrs=(int *)intbrn; /*需要搬移的SIU中断服务程序源地址*/</div>
<div>ptrd=(int *)(getevt()+0x500);/*目标地址*/</div>
<div>do /*把SIU中断服务程序搬移到外部中断入口处*/</div>
<div>*ptrd++=*ptrs;</div>
<div>while(*ptrs++!=0x4c000064);/*0x4c000064是SIU中断服务程序返回指令RFI指令的二进制代码*/</div>
<div>pdpr-&amp;gt;CICR.IRL2=(unsigned)(intlv1);/*设定CPM的中断级别为4*/</div>
<div>pdpr-&amp;gt;CICR.HP0_HP4=0x1F; /*设定PC15为最高优先级中断*/</div>
<div>pdpr-&amp;gt;CIMR.SMC1=1;/*打开CPM IC的SMC1中断屏蔽位*/</div>
<div>pdpr-&amp;gt;SIMASK.ASTRUCT.LVM4=1;/*打开SIU IC的CPM中断屏蔽位*/</div>
<div>pdpr-&amp;gt;CICR.IEN=1;/*使能CPM中断*/</div>
<div>pdpr-&amp;gt;SMCE1=0xFF;/*清除SMC1的事件寄存器*/</div>
<div>pimm-&amp;gt;SMCM1=1;/*打开子模块可屏蔽的接收中断*/</div>
<div>asm(&quot;mtspr 80,0&quot;);/*使能中断*/</div>
<div>&hellip;&hellip; /*使能SMC1的发送和接收功能*/</div>
<div>}</div>
<div>main() /*主函数*/</div>
<div>{</div>
<div>smc_init() /*初始化SMC1*/</div>
<div>while(1);/*等待接收*/</div>
<div>}</div>
<div>#pragma interrupt intbrn /*SIU中断服务程序</div>
<div>void intbrn()</div>
<div>{</div>
<div>void CPMHandler();/*定义CPM中断服务程序*/</div>
<div>asm(&quot;stwu r9,-4(r1&quot;);/*把GRR9压入堆栈*/</div>
<div>switch(pdpr-&amp;gt;SIVEC.IC)/*读取SIU的中断向量号，转入相应处理程序*/</div>
<div>{</div>
<div>case 0x24;/*为CPM对应的中断向量号*/</div>
<div>asm(&quot;mfspr r9,8&quot;);/*把LR压入堆栈*/</div>
<div>asm(&quot;mfspr r9,8&quot;);/*把LR压入堆栈*/</div>
<div>asm(&quot;mfspr r9,8&quot;);/*把LR压入堆栈*/</div>
<div>asm(&quot;stwu r9,-4(r1)&quot;);</div>
<div>asm(&quot;bla CPMHandler&quot;)/*调用CPM中断处理函数*/</div>
<div>asm(&quot;lwz r9,0(r1)&quot;);/*把LR从堆栈中弹出*/</div>
<div>asm(&quot;addi r1,r1,4&quot;);/*恢复堆栈指针*/</div>
<div>asm(&quot;mtspr8,r9&quot;);</div>
<div>break;</div>
<div>default:;</div>
<div>}</div>
<div>asm(&quot;lwz r9,0(r1); /*把GPR9从堆栈中弹出/*</div>
<div>asm(&quot;addi r1,r1,4&quot;);/*恢复堆栈指针*/</div>
<div>}</div>
<div>void CPMHandler() /*CPM中断处理程序*/</div>
<div>{</div>
<div>unsigned v1;</div>
<div>pdpr-&amp;gt;CIVR.IACK=1;/*把CIVR的IACK位置为1，以读取CIVR中的中断向量号*/</div>
<div>v1=pdpr-&amp;gt;CIVR.VN;/*读取中断向量号*/</div>
<div>switch(pimm-&amp;gt;CIVR.VN)/*根据中断向量号进行处理*/</div>
<div>{</div>
<div>case 4: /*SMC1的中断向量*/</div>
<div>&hellip;&hellip; /*SMC1中断处理程序，对接收到的数据进行处理*/</div>
<div>pimm-&amp;gt;CISR=1&amp;lt;&amp;lt;(31-11);/*清除IN-SRVCE位*/</div>
<div>break;</div>
<div>default:;</div>
<div>}</div>
<div>}</div>
<div>getimmr() /*得到双端口寄存器的基址*/</div>
<div>{ asm(&quot;mfspr3,638&quot;);</div>
<div>}</div>
<div>getevt() /*得到中断入口的基址*/</div>
<div>{</div>
<div>if((getmsr() &amp; 0x40)==0)/*如果MSR.IP等于0*/</div>
<div>return(0); /*中断入口在低位*/</div>
<div>else</div>
<div>return(0xFFF00000);/*中断入口在高位*/</div>
<div>}</div>
<div>getmsr() /*得到机器状态寄存器MSR的值*/</div>
<div>{</div>
<div>asm(mfmsr 3; /*把MSR的值读到r3中*/&nbsp;<br />
｝</div>]]></description></item></channel></rss>