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

📄 硬件驱动编程.htm

📁 Vxwork的学习资料,对初学者有帮助 有关于BSP的说明介绍
💻 HTM
📖 第 1 页 / 共 4 页
字号:
      <BR>&nbsp;&nbsp;&nbsp;我曾用过IBM&nbsp;PowerPC4xx和ARM7(clps7xxx),这两种CPU都集成了两个内部的串口UART,我还在外部扩展过串口芯片ns16552,基本上是一样的. 
      <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;MPC860的结构和上面两种不同,尽管它的核也是PowerPC,它集成了两个处理块,一个处理块是嵌入的PowerPC核,另一个是通信处理模块(CPM).通信处理模块有4个SCC和2个SMC,这六个通信口可以通过设置来支持多种协议和通信方式,也可设置为串口UART模式(大概是通过寄存器GSMR或SMCMR),功能和中断的定义和通常的串口没有区别,你可以查一下寄存器SCCM/SCCE的位14和位15定义,这里定义了在何种情况下产生硬件中断. 
      <BR><BR>&nbsp;&nbsp;&nbsp;所以MPC860也有这样的机制.</P></TD></TR></TBODY></TABLE>
<TABLE width="80%" border=0>
  <TBODY>
  <TR>
    <TD class=t1>
      <P style="LINE-HEIGHT: 150%"><B>Re:Re:讨教</B>&nbsp;</P></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=10 width="80%" bgColor=#eeeeee border=0>
  <TBODY>
  <TR>
    <TD>
      <P 
      style="LINE-HEIGHT: 150%">860的cpm我还算熟悉,但我实在想不出如何能用程序触发一个中断,即使在看了你的贴子之后。你能不能说仔细些?&nbsp;</P></TD></TR></TBODY></TABLE>
<TABLE width="76%" border=0>
  <TBODY>
  <TR>
    <TD class=t1>
      <P 
style="LINE-HEIGHT: 150%"><B>Re:Re:Re:讨教</B>&nbsp;</P></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=10 width="76%" bgColor=#eeeeee border=0>
  <TBODY>
  <TR>
    <TD>
      <P 
      style="LINE-HEIGHT: 150%">&nbsp;&nbsp;&nbsp;&nbsp;根据MPC860中SCC&nbsp;UART&nbsp;Event&nbsp;Register(SCCE)的位14和位15定义,如位15是数据接收中断标志位,如果串口收到数据,则产生硬件中断,所以可以写程序向串口发数据,并不是程序产生的的中断,而是用程序发送数据,数据到达串口后,串口有数据收到就会产生RX中断,通知系统有数据到达,有相应的中断例程ISR来取数据. 
      <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;发送的情况类似,数据FIFO为空,产生中断,告诉系统发送准备就绪,可以发送,ISR把数据放入FIFO中,发送中断位清零.当发送完毕后,FIFO再为空,再次产生中断,告诉系统发送准备就绪,继续发送. 
      <BR><BR>不知这样解释的是否清楚.&nbsp;</P></TD></TR></TBODY></TABLE>
<TABLE width="72%" border=0>
  <TBODY>
  <TR>
    <TD class=t1>
      <P 
style="LINE-HEIGHT: 150%"><B>Re:Re:Re:Re:讨教</B>&nbsp;</P></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=10 width="72%" bgColor=#eeeeee border=0>
  <TBODY>
  <TR>
    <TD>
      <P style="LINE-HEIGHT: 150%">你说: 
      <BR>“所以可以写程序向串口发数据,并不是程序产生的的中断,而是用程序发送数据”。 
  <BR>如何向串口发送数据?&nbsp;</P></TD></TR></TBODY></TABLE>
<TABLE width="68%" border=0>
  <TBODY>
  <TR>
    <TD class=t1>
      <P style="LINE-HEIGHT: 150%"><B>我明白你的意思</B>&nbsp;</P></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=10 width="68%" bgColor=#eeeeee border=0>
  <TBODY>
  <TR>
    <TD>
      <P style="LINE-HEIGHT: 150%">"如何向串口发送数据?" <BR><BR>这一点主要是实现的问题,和中断关系不大 
      <BR><BR>有三种方法实现: <BR><BR>1.一般串口都支持LOOP&nbsp;BACK模式,即片子内部自发自收,设置成这种模式即可. 
      <BR>2.将串口的发送脚TX和接收脚TX连接. 
      <BR>3.用PC机上的Hyper&nbsp;Terminal和串口相连,不用做程序,直接可通过终端向串口发数据.</P></TD></TR></TBODY></TABLE>
<TABLE width="64%" border=0>
  <TBODY></TBODY></TABLE>
<TABLE width="56%" border=0></TBODY>
  <TBODY></TBODY></TABLE><!-- 文章内容显示 --></DIV>
<P style="LINE-HEIGHT: 150%" align=left> </P>
<P style="LINE-HEIGHT: 150%"><BIG><STRONG>&nbsp;&nbsp;&nbsp; ARM 
计时器中断编程实现过程</STRONG></BIG></P>
<BLOCKQUOTE>
  <BLOCKQUOTE>
    <P style="LINE-HEIGHT: 150%">&nbsp;&nbsp;&nbsp; 
    <STRONG>ARM7</STRONG>一般内部有两个16位计时器(Timer 
    counter)和一个32位实时时钟(<STRONG>RTC</STRONG>),计时器中断属于<STRONG>IRQ</STRONG>中断,这里以计时器1为例叙述一下中断的编程过程</P>
    <P style="LINE-HEIGHT: 150%">&nbsp;&nbsp;&nbsp; 设置interrup mask 
    <STRONG>INTMR1</STRONG>寄存器 0x80000240 第8位<STRONG>TC1OI</STRONG>计时器1为使能. 
    在0x800000300 计时器 1 
    的数据寄存器<STRONG>TC1D</STRONG>写入指定数据,这样数据开始从这个给定的数开始递减计数,计数递减至 0 
    后,会产生一个溢出underflow <STRONG>IRQ</STRONG>中断请求,中断状态寄存器<STRONG>INTSR1</STRONG> 
    0x80000240 第8位<STRONG>TC1OI</STRONG>置位.系统会跳到中断向量表地址 0x00000018 
    处,执行相应的中断程序,中断程序通过判断中断的类型(判断中断状态寄存器的位),来执行相应的中断服务程序<STRONG>ISR</STRONG>. 
    中断状态寄存器标志位复位,计时器开始重新开始计时.</P></BLOCKQUOTE></BLOCKQUOTE>
<P style="LINE-HEIGHT: 150%" align=center> </P>
<P style="LINE-HEIGHT: 150%" align=center><A 
href="http://www.embhelp.com/drew/mypage/driver.htm#returntop"><B>返回页首</B></A></P>
<P style="LINE-HEIGHT: 150%"> </P>
<P style="LINE-HEIGHT: 150%"><BIG><A name=FLASH></A><BIG><STRONG>Intel 
Flash芯片</STRONG></BIG></BIG> </P>
<P style="LINE-HEIGHT: 150%">&nbsp;&nbsp;参见 <A 
href="http://www.embhelp.com/drew/mypage/example/flashrom.htm" 
target=_blank>Flash ROM示例</A></P>
<BLOCKQUOTE>
  <P style="LINE-HEIGHT: 150%"><STRONG>问题 1</STRONG> :我们现在用的是intel E28F640 
  J3A120型号的falsh芯片.在该芯片上要存放配置信<BR>息、某些标志位,动态增长,减少的数据.现在有个问题: 
  在向某个地址写数据之前,是否一定要擦除该地址所在的块?</P>
  <BLOCKQUOTE>
    <P style="LINE-HEIGHT: 150%">&nbsp;&nbsp;&nbsp; 
    应该要擦除该地址所在的块block,先要Unlock这个块,然后擦除该块,再写操作.通常的操作都是这样。所以一个4K--128K块擦除要用几百或几千毫秒,全部Flash擦除用到多达30秒时间,很费时.这就是为什么现在有些Flash(如ATMEL的AT29C040等)采用较小的block,sector或page(64---512bytes)的原因.<BR></P></BLOCKQUOTE>
  <P style="LINE-HEIGHT: 150%"><STRONG>问题 2</STRONG> 
  :(一个块是128KBytes,这样我仅仅为了改写一个Byte,就必须读128Kbytes,然后擦除该块,然后再写128KBytes,太累了,不可能吧??)有没有擦除一个字节或子的方式?</P>
  <BLOCKQUOTE>
    <P style="LINE-HEIGHT: 150%"><BR>&nbsp;&nbsp;&nbsp; 
    我想肯定是这样的,因为flash的命令:Unlock,Erase,Write对flash的操作都是以块为单位的,即使你想只擦除一个字节,实际上擦除的是一个块,即128k.这是flash硬件定义的,对编程来说并不麻烦,是一样的,只是花费时间长一些。没有擦除一个字节或位的方式。 
    </P>
    <P style="LINE-HEIGHT: 150%">&nbsp; 
    为了解决以上的问题,有些芯片如AT29c040和W29c040采用小的Sector(块)方式,每个sector大小只有256bytes,写的时候,只要打开写保护,不需要擦处,直接按sector写入.尽管也要以Sector为单位操作,由于Sector非常小,所以特别适用于修改少量字节的操作。<BR></P></BLOCKQUOTE>
  <P style="LINE-HEIGHT: 150%"><STRONG>问题 3</STRONG> : 我现在要实现对INTEL 
  28F320J3A的操作,但是有一个很大的问题就是我感觉擦除和写数据都比较慢,我想和我没有使用它提供的写BUFFER的命令有关,所以想向您请教写BUFFER的问题.请问是不是每一个大小为128K的块只有32bytes的buffer,如果我想用写buffer操作,应该注意哪些问题呢?<BR></P>
  <BLOCKQUOTE>
    <P style="LINE-HEIGHT: 150%">&nbsp;&nbsp;&nbsp; 
    对Flash擦除和写数据是慢的,如果用写BUFFER的命令肯定会快一点,具手册上说,会快20倍,我没试过,不知道.32bytes的buffer不是每个block都有,是整个flash只有一个32bytes的buffer,用写BUFFER命令对所有的blocks写操作,都要用同一个buffer,写Buffer是主要要检查buffer是否available,其实buffer起缓冲作用,来提高工作效率,</P></BLOCKQUOTE>
  <BLOCKQUOTE>
    <P style="LINE-HEIGHT: 150%">写Buffer的主要步骤:<BR>1.写write 
    buffer命令到该Block的首地址.<BR>2.先查status,看buffer是否available,<BR>3.写入所写数据的的字节数到Flash的实际地址.<BR>4,写数据<BR>5.写WRITE_BUFF_CONFIRM命令到该Block的首地址<BR>6.写READ_ARRAY命令到该Block的首地址<BR><BR>其中要注意同一组数据跨越不同block时的处理.<BR><BR>上述步骤是肯定对的,你可以先试着写出程序,有什么问题,我们再交流,不要客气,<BR></P></BLOCKQUOTE>
  <P style="LINE-HEIGHT: 150%"><STRONG>问题 4</STRONG> 
  :如果我不使用写buffer的命令操作是不是就会很慢(写300多K大小的东西要半分多钟),如果写300多K大小的东西要半分多钟,我觉得是不正常的,另外,我对block 
  erase suspend command和&gt;program suspend 
  command等suspend命令的作用也不是很明白,一下子提了这么多问题,希望您没看烦,也很希望你能给我一些帮助,先谢过了<BR></P>
  <BLOCKQUOTE>
    <P style="LINE-HEIGHT: 150%">&nbsp;&nbsp;&nbsp; 
    你应该检查一下程序,是不是程序有问题,不应该这么慢.这些suspend命令,我也没有用过,应该是在对一个block造作过程中,暂停操作,来对另一个block操作(读数据或执行程序),待完成后,再恢复原来的.block 
    erase suspend command和program suspend 
command其实是一个命令B0H</P></BLOCKQUOTE></BLOCKQUOTE>
<P style="LINE-HEIGHT: 150%" align=center> </P>
<P style="LINE-HEIGHT: 150%" align=center><A 
href="http://www.embhelp.com/drew/mypage/driver.htm#returntop"><B>返回页首</B></A></P>
<P style="LINE-HEIGHT: 150%"> </P>
<P style="LINE-HEIGHT: 150%"><STRONG><BIG><A 
name=NIC></A><BIG>Cillus网卡</BIG></BIG></STRONG>CS8900A 
<STRONG><BIG>Linux驱动</BIG></STRONG></P>
<P style="LINE-HEIGHT: 150%">&nbsp;&nbsp;&nbsp; 可参见 <A 
href="http://www.embhelp.com/drew/mypage/sourcecode.htm#NIC" 
target=_blank>网卡示例</A></P><FONT class=sfont><B>
<P style="LINE-HEIGHT: 150%">Re: 谁做过网络接口控制芯片CS8900A的驱动?</B></FONT></P>
<BLOCKQUOTE>
  <P style="LINE-HEIGHT: 150%"><FONT class=nfont>&nbsp;&nbsp;&nbsp; 
  我曾经写过这种网卡的驱动,它相对来说比其它的驱动要难一些主要在于EEPROM 和 I/O MODE上,EEPROM 是你必须要操作的,因为一般网卡的 MAC 
  地址要侟在这里,另外还有一些用户设置。如果你只用网卡默认的设置,可暂时不用,网卡有两种运行模式,MEMORY MODE 和 I/O MODE,MEMORY 
  MODE 较为简单,对任何寄存器直接操作,不过你的硬件电路应支持才行,主要看有多少地址线和网卡连.<BR>如果采用 I/O MODE 
  则较为麻烦,对任何寄存器操作均要通过 I/O PORT 0X300 写入或读出. <BR>你所做的只是对一些寄存器进行必要的设置(TX RX 
  ENABLE,IP FILTER,....),然后将莫一地址的数据包放入数据寄存器即可,无须考虑 MAC 
  封包解包的事.<BR><BR></FONT>你的问题我看了一下,我没有在linux下做过这类程序,不过我原来用的操作系统<BR>VxWorks是从UNIX移植过来的,和linux的环境相似,用的都是GNU环境,另外我不清楚或模<BR>糊的地方也查了一些资料.对你的问题回答了一下.大概基本上是正确的.<BR><BR>有什么不清楚的,再来信,能帮得上你,我很高兴.<BR></P>
  <P style="LINE-HEIGHT: 150%"><BR><STRONG>问题 1</STRONG> 
  :在&lt;&lt;linux设备驱动程序&gt;&gt;P371:如果一个驱动程序做为主流Linux核心的一部分发行的话,它并不声明自己的device结构,而是使用在drivers/net/Space.c中声明的结构。Space.c声明了所有网络设备的链表,即包括plip1一类驱动程序特定的结构,也包括通用目的的eth设备。以太网根本不关心它们的device结构,因为它们使用通用目的的结构。这种通用的eth设备结构声明ethif_probe为它们的init函数。程序员要想在主流核心中插入一个新的以太网接口只需要在ethif_probe中加入一个对驱动程序初始化函数的调用。另一方面,非eth驱动程序的作者需要在Space.c中插入它们的device结构。在两种情况下,如果驱动程序必须被链到核心,只需要修改源文件Space.c。<BR><BR>在Space.c中:<BR>ethif_probe(struct 
  device *dev)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp; u_long base_addr = 
  dev-&gt;base_addr;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp; if ((base_addr == 
  0xffe0)&nbsp; ||&nbsp; (base_addr == 1))<BR>return 1;&nbsp; /* ENXIO 
  */<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp; if (1<BR>/* All PCI probes are safe, and 
  thus should be first. */<BR>#ifdef CONFIG_DE4X5 
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 
  DEC DE425, DE434, DE435 adapters */<BR>&amp;&amp; 
  de4x5_probe(dev)<BR>#endif<BR>#ifdef CONFIG_UCCS8900<BR>&amp;&amp; 
  cs89x0_probe(dev)<BR>#endif<BR>&nbsp;&nbsp;&nbsp;&nbsp; 
  .................<BR>&nbsp;&nbsp;&nbsp;&nbsp; 
  .................<BR>这里我想问的是,当我写完了自己的驱动代码比如cs89x0.c,cs89x0.h,并在space.c中#define 
  CONFIG_UCCS8900,接 下来在编译内核的时候我该去修改哪个文件,可以将cs89x0.c直接编译到内核中? &nbsp; 
  如果是按模块化方式写驱动,那么编译生成.o文件然后insmod一下就可以了;但现在要按非模块化的方式,直接编译到内核里去,该怎么做呢?</P>
  <BLOCKQUOTE>
    <P style="LINE-HEIGHT: 150%">1. 把cs89xx编译成独立模块,执行下列命令:<BR>  gcc 
    -D_KERNEL_-I/usr/src/linux/include-I/usr/src/linux/net/inet-Wall 
    -Wstrictprototypes -02 -fomit-frame-pointer -DMODULE -DCONFIG_MODVERSIONS 
    -ccs89x0.c<BR> 编译结果是名为cs89x0.o的驱动程序目标模块。要装载此驱动程序,<BR>&nbsp;&nbsp;&nbsp; 
    输入下列命令: insmod cs89x0.o io=0x360 
    irq=10<BR>//假如网卡的起始端口号为0x360,中断号为10<BR>  要卸载此驱动程序,用rmmod命令:<BR>  rmmod 
    cs89x0.o<BR>2.如果要将驱动程序编进系统核心,<BR> 修改/usr/src/linux/drivers/net/CONFIG,加入:<BR> CS89x0_OPTS=<BR> 修改/usr/src/linux/drivers/net/Config.in,加入:<BR> tristate‘CS8920 
    Support’CONFIG_CS8920<BR> 以上两行是为了让make 
    config在配置过程中询问是否增加CS89xx网卡的支<BR>&nbsp; 持。<BR>&nbsp;&nbsp;&nbsp; 
    修改/usr/src/linux/drivers/net/Makefile加入:<BR> ifeq((CONFIG_CS8920),y)  L_OBJS+=cs89x0.o<BR> endif<BR> 修改/usr/src/linux/drivers/net/Space.c,加入:<BR> extern 
    int cs89x0_probe(struct device *dev);<BR> ……<BR> #ifdef CONFIG_CS8920&& 
    cs89x0_probe(dev);<BR> #endif<BR> 以上两段是为了编译并输出网卡驱动程序及其例程。<BR> 把驱动程序源代码拷到/usr/src/linux/drivers/net目录下。<BR> 在/usr/src/linux目录下执行 
    make config或 make menuconfig,选择核心CS89xx网卡支 &nbsp;&nbsp;&nbsp;&nbsp; 
    持。<BR>  执行make dep、make clean命令。最后用 make zImage 
  编译Linux核心。<BR><BR></P></BLOCKQUOTE>
  <P style="LINE-HEIGHT: 150%"><STRONG>问题 2 
  :</STRONG>.uCcs8900.c中的send_test_pkt函数有什么用呢?其中定义的test_packet数组<BR>那样赋值该怎么理解?<BR>send_test_pkt(struct 
  device *dev)<BR>{<BR>int ioaddr = dev-&gt;base_addr;<BR>char test_packet[] = { 
  0,1,2,3,4,5,0,3,4,5,6,7,<BR>&nbsp;&nbsp;&nbsp;&nbsp; 0, 46, /* A 46 in network 
  order */<BR>&nbsp;&nbsp;&nbsp;&nbsp; 0, 0, /* DSAP=0 &amp; SSAP=0 fields 
  */<BR>&nbsp;&nbsp;&nbsp;&nbsp; 0xf3, 0 /* Control (Test Req + P bit set) */ 
  };<BR>long timenow = jiffies;<BR>unsigned short 
  event;<BR>&nbsp;&nbsp;&nbsp;&nbsp; writereg(dev, PP_LineCTL, readreg(dev, 
  PP_LineCTL) |<BR>SERIAL_TX_ON);<BR><BR>memcpy(test_packet, 
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dev-&gt;dev_addr, 
  ETH_ALEN);<BR>memcpy(test_packet+ETH_ALEN, dev-&gt;dev_addr, 
  ETH_ALEN);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  outw(TX_AFTER_ALL, ioaddr + 
  TX_CMD_PORT);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  outw(ETH_ZLEN, ioaddr + TX_LEN_PORT);<BR><BR>/* Test to see if the chip has 
  allocated memory for the packet */<BR>while (jiffies - timenow &lt; 5)<BR>if 
  (readreg(dev, PP_BusST) &amp; READY_FOR_TX_NOW)<BR>break;<BR>if (jiffies - 
  timenow &gt;= 5)<BR>return 0; /* this shouldn't happen */<BR><BR>/* Write the 
  contents of the packet */<BR>outsw(ioaddr + 

⌨️ 快捷键说明

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