⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 μc-os-ii的多任务信息流与can总线驱动.htm

📁 ucos的资料以及单片机dsp的经典移植程序
💻 HTM
📖 第 1 页 / 共 3 页
字号:
                  <DIV><FONT face=宋体>  恢复所有CPU寄存器;</FONT></DIV>
                  <DIV><FONT face=宋体>  执行中断返回指令;</FONT></DIV>
                  <DIV><FONT face=宋体>  这里</FONT>μC/OS-II<FONT 
                  face=宋体>提供了两个ISR与内核的接口函数:OSIntEnter和OSIntExit。OSIntEnter通知</FONT>μC/OS-II<FONT 
                  face=宋体>内核,中断服务程序开始运行了。实际上,此函数做的工作是把一个全局变量OSIntNesting加1。在x86等有累加指令的CPU中,可以用指令代替OSIntEnter:</FONT></DIV>
                  <DIV><FONT face=宋体>&nbsp;&nbsp;&nbsp; INC BYTE PTR 
                  OSIntNesting</FONT></DIV>
                  <DIV><FONT face=宋体>&nbsp;&nbsp;&nbsp; 
                  此中断嵌套计数器可以确保所有中断处理完成后再作任务调度。另一个接口函数OSIntExit则通知内核,中断服务已结束。根据相应情况,返回被中断点(可能是一个任务或者被嵌套的中断服务程序)或由内核作任务调度。</FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  用户编写的ISR必须被安装到某一位置,以便中断发生后,CPU根据相应的中断号运行准确的服务程序。许多实时操作系统都提供了安装、卸载中断服务程序的API接口函数,有些成熟的RTOS甚至对中断控制器的管理都有相应的API函数。但 
                  </FONT>μC/OS-II<FONT 
                  face=宋体>内核没有提供类似的接口函数,需要用户在对应的CPU移植中自己实现。这些接口函数与具体的硬件环境有关,接下来PC体系下的中断处理对此有详细的说明。</FONT></DIV>
                  <DIV><FONT face=宋体><B>3 PC体系下的中断</B></FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  X86系列的处理器可支持256个中断,并用向量表的方法来关联每个中断和相应ISR的位置。在实模式下,中断向量表(IVT)存于内存的低端1K。每个向量表条目占4字节,保存一个ISR的段地址和偏移信息。PC系统使用两个级联的可编程中断控制器82C59A。一个82C59A能连接8个硬件中断,编号为IRQ0~IRQ7。 
                  PC总共可管理15个外部中断源,PC的中断控制器如图4所示。(关于82C59A的详细使用可参见有关资料。)</FONT></DIV>
                  <DIV><FONT face=宋体>  在</FONT>μC/OS<FONT 
                  face=宋体>下,CAN总线I/O端口中断向量设置伪代码:</FONT></DIV>
                  <DIV><FONT face=宋体>&nbsp;&nbsp;&nbsp; void CanInitHW(UI 
                  segment,BYTE Irq0,BYTE Irq1){</FONT></DIV>
                  <DIV><FONT face=宋体>  保存原有的中断向量</FONT></DIV>
                  <DIV><FONT face=宋体>  保存掩码寄存器的值</FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  使82C59A的掩码寄存器(0x21)各位置1,关闭中断输入</FONT></DIV>
                  <DIV><FONT face=宋体>  关闭CPU中断</FONT></DIV>
                  <DIV><FONT face=宋体>  设置新的中断向量</FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  正在服务的中断禁止再次响应服务(假定当前服务中断是IRQ5)</FONT></DIV>
                  <DIV><FONT face=宋体>  开CPU中断</FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  清除82C59A的掩码寄存器(0X21、0XA1)各位,开启中断输入</FONT></DIV>
                  <DIV><FONT face=宋体>&nbsp;&nbsp;&nbsp; }</FONT></DIV>
                  <DIV><FONT face=宋体><B>4 信号量与缓冲队列支持下的CAN总线驱动</B></FONT></DIV>
                  <DIV><FONT face=宋体>  前面介绍了</FONT>μC/OS-II<FONT 
                  face=宋体>内核下多任务调度的关键技术、中断与PC体系下中断的一般方法。又以82C59A的中断5(IRQ5)、0x0D中断向量为例,介绍了中断服务子程序的重新分配和响应SJA1000控制器收发的中断服务子程序。</FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  下面介绍信号量配合下的环形缓冲队列与中断处理程序之间的关系问题,这也是设备驱动部分的核心内容。</FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  ERTOS的驱动程序与其它操作系统有所不同。比如Windows、Unix、Solaris、Linux等操作系统弱化了设备的概念,用户进程对设备的使用可以通过文件系统来完成。然而,在</FONT>μC 
                  /OS-II<FONT 
                  face=宋体>上开发CAN总线驱动程序没有那么严格,只要满足设备在连续的CPU时间上使用时不发生时间重叠就可以了。</FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  串行设备或者其它字符型设备都存在外设处理速度和CPU速度不匹配的问题,所以需要建立相应的缓冲区。向CAN口发送数据时,只要把数据写到缓冲区,然后由SJA1000控制器逐个取出往外发。从CAN口接收数据时,往往等收到若干个字节后才需要CPU进行处理,所以这些预收的数据可以先存于缓冲区。缓冲区可以设置收到若干个字节后再中断CPU,这样避免了因为CPU的频繁中断而降低系统的实时性。<BR><IMG 
                  height=250 hspace=10 
                  src="μC-OS-II的多任务信息流与CAN总线驱动.files/2006721232249360.gif" 
                  width=549 vspace=10 
                  border=0><BR>  在对缓冲区读写的过程中,经常会遇到想发送数据时,发送缓冲已满;想去读时,接收缓冲却是空的。对于用户程序端,可以采用查询工作方式,即放弃无法读写的操作,然后再频繁地去尝试这个操作直到成功,这样程序效率显然降低。如果引入读、写两个信号量分别对缓冲区两端的操作进行同步,问题将迎刃而解。用户任务想写但缓冲区满时,在信号量上睡眠,让CPU运行别的任务,待ISR从缓冲区读走数据后唤醒此睡眠的任务;类似地,用户任务想读但缓冲区空时,也可以在信号量上睡眠,待外部设备有数据来了再唤醒。由于</FONT>μC/OS-II<FONT 
                  face=宋体>的信号量提供了超时等待机制,CAN口当然也具有超时读写能力。</FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  带缓冲和信号量的CAN口接收和发送部分见本刊网络补充版(http://www.dpj.com.cn)。</FONT></DIV>
                  <DIV><FONT face=宋体>  接口函数总结如下。</FONT></DIV>
                  <DIV><FONT face=宋体>void CanInitHW(UI segment,BYTE irq0,BYTE 
                  IRQ1)</FONT></DIV>
                  <DIV><FONT face=宋体>/*设置SJA1000控制器端口中断向量*/</FONT></DIV>
                  <DIV><FONT face=宋体>int canReleaseHW() /* 
                  清除SJA1000控制器端口中断向量*/</FONT></DIV>
                  <DIV><FONT face=宋体>int canSendMsg( CANBYTE port, MSG_STRUCT 
                  msg)</FONT></DIV>
                  <DIV><FONT face=宋体>/* 向定制SJA1000控制器端口发送数据*/</FONT></DIV>
                  <DIV><FONT face=宋体>int canReceiveMsg( CANBYTE port, MSG_STRUCT 
                  msg_ptr)</FONT></DIV>
                  <DIV><FONT face=宋体>/*从定制SJA1000控制器端口接收数据</FONT></DIV>
                  <DIV><FONT face=宋体>int canConfig( CANBYTE port, CAN_STRUCT 
                  can)</FONT></DIV>
                  <DIV><FONT face=宋体>/*初始化和配置SJA1000控制器 */</FONT></DIV>
                  <DIV><FONT face=宋体>int canNormalRun( CANBYTE port 
                  )</FONT></DIV>
                  <DIV><FONT face=宋体>/*设置SJA1000正常(Normal)运行模式 */</FONT></DIV>
                  <DIV><FONT face=宋体>int canReset( CANBYTE port )</FONT></DIV>
                  <DIV><FONT face=宋体>/* 
SJA1000控制器端口重新设置,缓冲区置位0xff*/</FONT></DIV>
                  <DIV><FONT face=宋体>CANBYTE can0r( CANBYTE addr)</FONT></DIV>
                  <DIV><FONT face=宋体>/*读取SJA1000控制器端口0的定制寄存器的值 */</FONT></DIV>
                  <DIV><FONT face=宋体>CANBYTE can1r( CANBYTE addr)</FONT></DIV>
                  <DIV><FONT face=宋体>/*读取SJA1000控制器端口1的定制寄存器的值 */</FONT></DIV>
                  <DIV><FONT face=宋体>接收和发送数据缓冲区数据结构定义:</FONT></DIV>
                  <DIV><FONT face=宋体>typedef struct {</FONT></DIV>
                  <DIV><FONT face=宋体>INT16U RingBufRxCtr; /* 接收缓冲中字符数目 
                  */</FONT></DIV>
                  <DIV><FONT face=宋体>OS_EVENT RingBufRxSem; /* 接收信号量 
                  */</FONT></DIV>
                  <DIV><FONT face=宋体>INT8U RingBufRxInPtr; /* 接收缓冲中下一字符的写入位置 
                  */</FONT></DIV>
                  <DIV><FONT face=宋体>INT8U RingBufRxOutPtr; /* 接收缓冲中下一待读出字符的位置 
                  */</FONT></DIV>
                  <DIV><FONT face=宋体>INT8U RingBufRx[CAN_RX_BUF_SIZE]; /* 
                  接收环形缓冲区*/</FONT></DIV>
                  <DIV><FONT face=宋体>INT16U RingBufTxCtr;</FONT></DIV>
                  <DIV><FONT face=宋体>/* 发送缓冲中字符数目 */</FONT></DIV>
                  <DIV><FONT face=宋体>OS_EVENT *RingBufTxSem; /* 发送信号量 
                  */</FONT></DIV>
                  <DIV><FONT face=宋体>INT8U *RingBufTxInPtr;</FONT></DIV>
                  <DIV><FONT face=宋体>/* 发送缓冲中下一字符的写入位置 */</FONT></DIV>
                  <DIV><FONT face=宋体>INT8U *RingBufTxOutPtr;</FONT></DIV>
                  <DIV><FONT face=宋体>/* 发送缓冲中下一待读出字符的位置 */</FONT></DIV>
                  <DIV><FONT face=宋体>INT8U RingBufTx[CAN_TX_BUF_SIZE]; /* 
                  发送环形缓冲区*/</FONT></DIV>
                  <DIV><FONT face=宋体>} CAN_RING_BUF;</FONT></DIV>
                  <DIV><FONT face=宋体><B>结 语</B></FONT></DIV>
                  <DIV><FONT 
                  face=宋体>  本文是在嵌入式计算机技术领域的应用背景下提出的,整个工程开发结束以后,系统正常运作时间超过27天。希望本文的提出对开发嵌入式操作系统的技术人员能有所帮助,同时也希望同一领域的开发人员共同探讨、共同发展。</FONT></DIV><SPAN 
                  class=style1>(<A class=link3 href="http://www.avrw.com/" 
                  target=_parent>综合电子论坛</A>)</SPAN></TD></TR></TBODY></TABLE>
            <P 
            align=center>&nbsp;*注:部份文章为网上收录供大家共同学习参考之用,并不代表本站意见。如存在版权问题请马上通知我们,我们将马上删除。</P></TD></TR></TBODY></TABLE></P></TD></TR></TBODY></TABLE>
<SCRIPT src="μC-OS-II的多任务信息流与CAN总线驱动.files/floor.htm"></SCRIPT>

<SCRIPT src="μC-OS-II的多任务信息流与CAN总线驱动.files/homeright.js"></SCRIPT>

<SCRIPT language=javascript src="μC-OS-II的多任务信息流与CAN总线驱动.files/339405.js" 
type=text/javascript></SCRIPT>
<NOSCRIPT><A href="http://www.51.la/?339405" target=_blank><IMG 
style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none" 
alt=我要啦免费统计 src="μC-OS-II的多任务信息流与CAN总线驱动.files/go.htm"></A></NOSCRIPT>
<SCRIPT language=JavaScript src="μC-OS-II的多任务信息流与CAN总线驱动.files/stat.htm" 
charset=gb2312></SCRIPT>

<SCRIPT src="μC-OS-II的多任务信息流与CAN总线驱动.files/shownum.htm"></SCRIPT>
 </BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -