Archive

Archive for the ‘学习笔记’ Category

编程读取注册表获取串口信息(支持Vista)

March 10th, 2010 will No comments

在编写串口通信程序时,经常需要列举计算机上目前可用的串口。最简单的方法是通过CreateFile串口号1~256(XP系统系统下最大支持的串口号为256),查看返回值,如果返回非INVALID_HANDLE_VALUE就证明此串口号存在。此方法简单实用,因为在只有一个串口的情况也需要遍历256个串口,需CreateFile256次,效率较低,而且不能显示目前正在使用的串口号。

下面介绍通过读取注册表获取串口号与串口个数的方法。

#define MAXCOMNO 256  //最大COM号256
typedef struct{
 char name[8];
 short no;
}SCOM;

/////用读注册表的方式查看系统的串口设备
void GetAvailableCom(SCOM *port,int &cnt)
{
 HKEY  hKey; 
 LONG  ret; 
 OSVERSIONINFO    osvi; 
 BOOL  bOsVersionInfoEx; 
 CString  keyinfo;
 unsigned char comm_name[40];
 char ValueName[40];
 char szNO[3];
 int  i=0,j=0;
 cnt=0;
 DWORD  sType,Reserved,cbData,cbValueName;
 
 ZeroMemory(&osvi,  sizeof(OSVERSIONINFO)); 
 osvi.dwOSVersionInfoSize  =  sizeof(OSVERSIONINFO); 
 
 keyinfo.Format(_T("HARDWARE\\DEVICEMAP\\SERIALCOMM"));
 //CString  keyinfo=_T("HARDWARE\\DEVICEMAP\\SERIALCOMM");

 i=0;  sType=REG_SZ;Reserved=0; 
 bOsVersionInfoEx  = GetVersionEx(&osvi); 

 ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyinfo,0,KEY_ALL_ACCESS,&hKey); 
 if  (ret==ERROR_SUCCESS)
 {
  if  (osvi.dwPlatformId  ==  VER_PLATFORM_WIN32_WINDOWS)    //WIN32,not used
  { 
   for(i=1;i<=MAXCOMNO;i++) 
   {
    memset(comm_name, 0, 40);
    sprintf((char*)comm_name,"COM%d",i);
    ret=RegEnumValue(hKey, i, ValueName, &cbValueName, NULL, &sType, comm_name, &cbData);
    if(ret==ERROR_SUCCESS)
    {
     i++;
    }

   } 
  } 
  else  if  (osvi.dwPlatformId  ==  VER_PLATFORM_WIN32_NT) //WINNT XP 2000
  { 
   do   
   { 
    cbData=40;cbValueName=40; 
    memset(comm_name,0,40);   
    memset(ValueName,0,40);
    memset(szNO,     0, 3);
    ret=RegEnumValue(hKey, i, ValueName, &cbValueName, NULL, &sType, comm_name, &cbData); 
    if  (ret==ERROR_SUCCESS) 
    { 
     for(j=0;j<cbData;j++)
     {
      port->name[j]=comm_name[j];
      if(j>2 && j<6)
      {
       szNO[j-3] = comm_name[j];
      }
     }
     port->no = atoi(szNO);
     port++;
     cnt++;
     i++; 
    } 
   }while(ret==ERROR_SUCCESS); 
  } 
 }
 RegCloseKey(hKey);
}

port包含串口名称与编号,由于注册表中的串口名称排列并非安装串口号顺序排列而是随即排列的,便于界面中顺序列出串口号,故分别保存便于判断。cnt返回当前计算机中包含的串口数量。

注:由于在串口号大于8之后,不能直接用COM10来CreateFile,而要用\\\\.\\COM10的形式,而在COM8一下采用\\\\.\\COM1来CreateFile也是可以的。
在Vista下用此程序来读取串口号失败,其实并没有失败而是在Vista下访问注册表需要管理员权限。解决办法单击你的程序,右键属性,选择“兼容性”选项卡,勾选最下面的“请以管理员身份运行改程序”。

Categories: 学习笔记 Tags: , ,

FPGA中的多时钟设计

January 27th, 2010 will No comments

多种独立时钟在SoC(system-on-chip)设计中已普遍存在。很多SoC设备接有许多接口,这些接口根据标准运用了完全不同的时钟频率。

很多现代的串行接口继承了片上其它接口的异步性;而有些则直接从输入数据流中继承时钟。通过设计主要的SoCs子模块运行独立的时钟解决大片子中的时钟脉冲相位差,已经成为一种趋势。

由于这些原因,做SoC项目的设计人员一定会遇到多时钟和面对设计使用两个独立时钟芯片的逻辑连接问题。每个不同的时钟部分被认为是一个时钟域。在不同时钟上的逻辑接口被称作时钟域交叉或时钟域边界。对穿越时钟域边界的信号的处理是成功设计SoC的关键。

问题1:亚稳定性
设计人员必须考虑的第一个多时钟问题是信号从一个时钟域到另一个时钟域的亚稳定性问题。许多设计人员明白在实际电路中亚稳定性确实是个问题,现代RTL(寄存传输级)设计的抽象概念和静态的时序分析并不能完全屏蔽设计者对根本物理实现的担心。

无论何时一个信号进入一个时钟域的元件,如触发器,无论此时钟域与信号时钟多接近,都存在潜在的亚稳态问题。每当发生这样的情况,触发器立即产生不确定的值,在触发器的值被设置之前它的输出信号将不能使用。

在一个异步时钟边界,接收端时钟用来捕获发送端触发器的每一个信号。因为没有定义时钟与信号间的时间关系,所以它们完全可以同时传输。这样,在接收时钟域存在亚稳定性的问题。

这不是理论的、潜在的。在实际系统运行中,GHz时钟速率芯片的设计错误可以很快表现出亚稳态的效果。这些影响通常包括在时钟域之间丧失关键握手信号,以及失效多比特数据的严重问题,很有可能需要芯片的重新设计。

很多设计师也知道,教科书中通过在每路穿越时钟域边界的信号上使用两级触发器解决亚稳定性问题。即使第一级触发器没有成为亚稳态,也有极高的可能性使信号通过第二级的时间将被确定。这种两级触发器结构被称为同步器,和设计师通常讲的穿越时钟域同步信号。

问题2:复位同步
复位信号不同步是多时钟设计的一个相关问题。设计师有时会忘记,复位信号为受到亚稳定影响,应该加同步器加以保护。一般来说,整个系统可以使用单一信号复位,因此,必须传到所有时钟域的所有时钟元件。

复位信号的有效沿没有必要同步,因为所有的状态元件复位定义为初始值,并且复位信号会保持足够的时钟周期,取出所有的亚稳定状态。

但是,复位停止必须保持同步,这样触发器在复位状态恢复后不会处于亚稳态。在设计中,通过给进入每一个时钟域的复位信号一个独立的同步器来实现。

问题3:毛刺消除跨时钟域
尽管出于实际的目的同步消除了亚稳态,但是它不足以解决其它类型的多时钟设计错误。在多时钟设计中第三类常见错误是允许毛刺从驱动时钟域传播到接收时钟域。

因为一个接收时钟域的触发器可以及时的从驱动时钟域的任意点采样信号,甚至是很窄的毛刺也可能被捕获,并视为一个有效值。由于时钟关系的变化特性,这种毛刺电压不能通过静态时序分析检测。

避免种类问题最常见的方式是,使从驱动时钟域触发器输出的信号直接进入同步器。这有效地定义了一个三个阶段同步器,第一个触发器由驱动时钟驱动,剩余的两级由接收时钟驱动。尽管设计及时钟结构的自动分析更加可靠,但这种方法可以作为设计审查。

问题4:接收时钟域不恰当的保持时间(hold times)
在多时钟设计中第四类问题是,不稳定数据从一个时钟域到另一个没有遵守保持时间。信号从一个快速时钟域到一个慢速时钟域时,在驱动时钟域必须稳定几个时钟周期,保证接收域中的慢速时钟不会完全丢失转换。

如果这个转换丢失,数据将丢失。例如一个信号从33MHz的PCI域到12MHz的USB域,必须保持稳定3个时钟周期,才能保证被接收。

当数据信号在逻辑控制信号的保护下,跨越时钟边界,保持时间(hold times)也是非常重要的。

问题5:跨越式中边界丢失信号间的相关性
在多时钟设计中的最后一类问题是,相关信号在跨越时钟边界后失去相关。这个问题是最不直观的。这将导致非常不确定的行为,如数据丢失,算术结果破坏。

这类不直观的问题在可视化的检查中很难被发现,特别是用RTL电路形式,在设计审查是经常被忽视。必须将严格的设计规则和有效的自动分析用于这类问题。

在广泛的相关信号中,可能产生相关性丢失的几种不同方式,包括:

  • 总线的多数据位
  • 单信号的多次复制
  • 握手信号,如请求与应答信号
  • 明显不相关的信号合并在接收时钟域的同一逻辑中

无论何时一个信号进入亚稳态,可以使用同步器确定它的值,但是在接收时钟域不能保证在信号有效之前的精确周期数。因此,任何一个多位信号,每位有独立的时钟同步,每位在到达接收时钟域时,相对其它位将产生倾斜。

即使亚稳定不发生,任何成对数据位信号在到达相应的同步器之前,通过不同的线路或者电特性使两个信号产生不同的延时,都可能丢失同步。

可能一个同步器采样输入信号,并且在另一个同步器捕获信号变化之前,先捕获信号的变化,这样,两个信号将在一个时钟周期内倾斜,并且不再相关。

两个明显独立的信号来两个分离的时钟域,最终反馈进相同的接收时钟域,这是可能产生丢失相关性。这一模式被称作再收敛。在设计复查中,通过同步原理的手动检查方式很发现。

解决方法:时钟验证(Clock intent verification)

尽管多时钟设计的挑战的确让人沮丧,但是幸运的是以上所有描述的问题,是可以自动分析的。然而不是所有的问题都是完全一致的。可能为了避免可疑逻辑的细节警告,设计人员可以检查逻辑是否正确。时钟验证(CIV)是分析时钟结构,报告错误与警告的一个过程,然后使用详细正式的报告验证这些不能被证明问题。

任何CIV必须解决多时钟设计中五个问题的一个。这一进程始于RTL的结构分析,追查设计中从触发器到其它级元器件的时钟与复位。这一过程可以自动设别:

  • 设计中的所有异步时钟域
  • 穿越时钟域的所有控制和数据信号
  • 任何丢失同步或者不正确同步的跨时钟域信号
  • 任何在输入端有潜在毛刺的同步器
  • 任何信号有扇出倍同步器
  • 任何在接收时钟域再收敛的独立同步信号
  • 任何复位信号没有合理同步的时钟域
  • 任何存在潜在毛刺的门时钟或派生时钟

如果合理实现,这些结构的分析可以很快的在SoC上实现,最少的设计输入要求,尽管在对输入信号做简单的描述,对分析是有好处的。

根据这些信息,分析可以极端正确,以至于虚假的错误和警告将不会报告。设计者将只会看到真正的问题,或者是有关设计的有用反馈信息(例如一系列合理同步的信号)。

尽管很多类型的多时钟设计问题可以通过CIV的结构分析来检测,但还是有部分不能。对于变化的多时钟域信号处理与跨时钟域数据的稳定性验证,需要彻底地分析与正式的验证。

既然正式的验证需要对设计断定,一个CIV解决方案必须能够产生三种类型的断定,来表现信号穿过多时钟域的期望行为:

  • 断定多位数据跨域时钟域时,必须是灰数据(每次仅有一位数据改变);这是为了避免丢失相关性
  • 断定具有同步器的信号能够保持稳定,持续足够长的时钟周期,以便接收时钟域能够检测,这是为了避免丢失数据
  • 断定没有同步器的信号(比如数据总线),在接收时钟域采样时间内,能够保持稳定,这也是为了避免数据丢失

正式的验证试图证明这些断定在任何假定下都不能违反,或者试图通过举反例来证明断言不能违反。

无论何时一个证据被发现,设计者将信心大增,因为他们知道没有可能特定时钟跨越错误将会发生。无论何时一个范例被发现,正式验证已经发现了一个实际的bug,如果不解决,将导致芯片不能工作。正式的工具必须能够提供足够的信息让设计者解决问题,然后重新运行观察是否能够找到证据,去除心中久留的顾虑。

尽管正式验证是一个彻底的技术,但是在复杂的SoC设计中,并不是所有的断定都能够被证明的。出于这个原因,如果CIV方法能够产生符合仿真形式的断定,将是有价值的。如果无法找到证据,但是断定在整个成百万甚至上十亿个时钟周期内运行都不产生冲突,那么,设计师仍然可以获得一项多时钟设计正确性推断的重要措施。

Categories: 学习笔记 Tags:

解决"应用程序配置不正确,程序无法启动"问题

June 28th, 2009 will No comments

其实这是一个常见的问题,很多软件卸载重装都可能会出现这样的问题——“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题”。

将AVR Studio从4.12版升级到4.14版的过程中,出现提示框,说是xxx文件没有注册成功之类,当时点确定continue过去了,安装完成后,运行AVR Studio就出现了上面的错误提示。

百度一下发现原来是缺少运行时态库,解决办法:
1.下载Microsoft Visual C++ 2005 Redistributable Package (x86): http://www.microsoft.com/downloads/details.aspx?familyid=32BC1BEE-A3F9-4C13-9C99-220B62A191EE&displaylang=zh-cn
2.下载Microsoft Visual C++ 2005 Redistributable Package (x64): http://www.microsoft.com/downloads/details.aspx?familyid=90548130-4468-4BBC-9673-D6ACABD5D13B&displaylang=zh-cn
以上x86与x64是针对不同系统的,32位系统选择x86,64位选择x64。一般选择x86即可。目前vcredist_x86.exe已有VC 2005和VC 2008两个版本,如果一个不行可以试一下另一个。

记得曾经写过一个关于VC++2005编写的应用程序如何打包的问题,有兴趣的朋友可以看看。

在安装vcredist_x86.exe的时候可能会出现“不能访问WINDOWS INSTALLER服务”的错误提示。解决办法:
1、下载安装Microsoft Windows Installer 3.1 简体中文版http://www.skycn.com/soft/11601.html
2、点击开始–运行– 输入cmd 依次输入;先用msiexec /unregserver命令, 停掉windows installer服务;再用msiexec.exe /regserver 命令启用windows installer服务。

3077c806

Categories: 学习笔记 Tags:

UART收发数据的讨论

June 22nd, 2009 will No comments

UART(Universal Asynchronous Receiver )是通用异步收发接口,在很多芯片中都有应用。一般UART的收与发共用一个数据寄存器(8bit),通过相应的状态寄存器来判断UART的工作情况。

接收可以有两种方式:一种是查询,另一种是中断。通常使用中断方式。

接收查询方式是通过CPU不停读取UART的状态寄存器,当有数据到来时,读取数据,此方法占用太多的CPU时间,很少使用,在CPU只做数据转发时可以考虑使用。

接收中断方式是通过数据到达后产生中断,在中断处理函数中读取数据。每一个数据(8bit)到来产生一次中断。如果在每个数据中断都调用数据处理函数,当波特率较高,数据帧较长,数据处理时间较长时,可能会出现丢数据的情况。如果在一次中断进入后,while(数据寄存器满){读取数据},但波特率不高时,可能出现将一帧数据分多次中断读取,给后来的数据处理带来不便。

Windows中是将串口(UART)当做一个文件,直接对文件进行读写操作。一般是以一个线程去查询读取数据,基本可以保证整帧数据一次全部读出。也可以一次一个字符(8bit)来读。实际上是Windows的底层驱动将UART(串口)数据接收之后放到一个FIFO缓冲区中。显然在单片机或DSP等专用芯片中也应该用一个FIFO来缓存数据,然后在程序中读FIFO来处理数据。

发送也可以分为两种方式:一种是查询,另一种是中断。通常使用查询方式。

发送查询方式是通过CPU查询UART发送寄存器的状态,当为空的时候,发送数据;当不为空时,等待(适合用while循环判断)。

发送中断方式是将需要发送的数据存入一个缓冲区(FIFO),当发送寄存器为空,进入中断时,将数据发送。需要注意时,一旦开启发送中断,当没有数据发送时,就会一直跳入发送中断处理函数,所以在数据发送完之后一定要关闭发送中断使能。

Categories: 学习笔记 Tags: , ,

090614FB

June 14th, 2009 will No comments

昨天晚饭时,TWT同学电话小寨百盛JACKJONES全场5-6折,当时有些心动,但毕竟没有发工资,加上去年买的T与短衬较多,不打算去,但TWT同学盛情邀请通往,一时间我也找到了前往的理由,买鞋,本来打算领了工资之后再去的,又可以提前完成任务了。这次是工作之后的第一次血拼,全部用信用卡。看一下战利品吧。

第一站小寨百盛,就在一楼的一角,打折商品还较多。帮同学挑了挑,我淘了一件短衬,原因去年买的短衬由于身体发胖,明显感觉有些小了,这次买了180的。原价249元,6折下来149.4元。TWT同学买了一T恤和一仔裤。还在百盛办理了一张积分卡。到4楼JACKJONES专柜看中一皮带正价199拿下。到一楼麦当劳吃中午饭,坐车到交大五环店买鞋。下车后就进百盛了,在门口的地方有个卖包的,万博龙(KLIYAWANBLONG)3折,原价248,折后74.4,顺便积分。然后到五环折扣店,看了看匡威(converse),折扣一般最低5折,想想以前4折都没买,现在还是不卖。再看看Nike的鞋,发现年前买的鞋子,正价买的,现在7折,伤心啊。最终决定在Nike360买了双板鞋(Terminator Low),也算没有白跑一趟啊。

今天不仅超前完成了下个月的任务,还超额完成了O(∩_∩)O哈哈~

PS:百盛的积分卡,办理比较简单只要凭当日的购物单+身份证号就可以办理。而五环的积分卡比较麻烦,需要当日消费累加满5K。

Categories: 学习笔记 Tags: