Chinaunix首页 | 论坛 | 博客
  • 博客访问: 588648
  • 博文数量: 752
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(752)

文章存档

2011年(1)

2008年(751)

我的朋友

分类:

2008-10-13 16:51:13

   现在很多笔记本都不带有标准串口,但在工作环境中又需要使用串口,在window下我们还可以使用USBRS232设备来将就一下,但这种设备带的驱动程序一般都只有window的,偶尔也有提供Linux的,但由于linux下的驱动要根据linux的内核版本来区分安装,厂商一般都很难根据linux的发展来及时更新,如果要碰到驱动和自己使用的linux内核版本不同会是一件很麻烦的事。最近发现使用VMware这个变通的方法可以解决这个问题,拿出来和大家共享一下:)。

       说起来很简单,首先机器上要有window操作系统,一个USBRS232设备(当然在window下能正常使用),然后安装VMware,在虚拟环境中安装一个linux系统,准备工作就这些了,然后进行一下简单的设置,让VMware来接管window的串口。选择VM-Settings,在Hardware属性页中点击Add,根据提示选择增加一个Serial Port设备,选择windowUSBRSR232设备转换后的串口号,就OK了。在虚拟的linux中接管的串口一般都是/dev/ttyS0

      


--------------------next---------------------

Linux串口编程的一些问题解决

 

       Linux下串口编程的文章网上是满天飞,但大都是出自一篇文章,而且写的都是些基本的操作,像控制RTS/CTS等串口引脚状态,接收发送二进制数据等,都没有很好的说明,我在使用中遇到了些问题,写出来,希望能对大家有所帮助,少走弯路,呵呵!

       我使用的操作系统是Redhat9gcc版本是3.2.2

       其实在linux下对串口的设置主要是通过termios这个结构体实现的,但是这个结构体却没有提供控制RTS或获得CTS等串口引脚状态的接口,可以通过ioctl系统调用来获得/控制。

获得:

ioctl(fd, TIOCMGET, &controlbits);

if (controlbits & TIOCM_CTS)

      printf(“有信号\n”);

else

      printf(“无信号\n”);

设置:

       ioctl(fd, TIOCMGET, &ctrlbits)

       if (flag)

           ctrlbits |= TIOCM_RTS;

       else

           ctrlbits &= ~TIOCM_RTS;

      ioctl(fd, TIOCMSET, &ctrlbits);

 

其实TIOCM_RTS有效后是把串口的RTS设置为有信号,但串口的电平为低时是有信号,为高时为无信号,和用TIOCMGET获得的状态正好相反,也就是说TIOCMGET/TIOCMSET只是获得/控制串口的相应引脚是否有信号,并不反应当前串口的真实电平高低。

网上许多流行的linux串口编程的版本中都没对c_iflagtermios成员变量)这个变量进行有效的设置,这样传送ASCII码时没什么问题,但传送二进制数据时遇到0x0d,0x110x13却会被丢掉。不用说也知道,这几个肯定是特殊字符,被用作特殊控制了。关掉ICRNLIXON选项即可解决。


       c_iflag &= ~(ICRNL | IXON);

 

0x0d 回车符CR

0x11 ^Q VSTART字符

0x13 ^S VSTOP字符

ICRNL 将输入的CR转换为NL  

IXON 使起动/停止输出控制流起作用  

 

在《UNIX环境高级编程 第二版》第18章第11小节看到把终端I/O设置为原始模式(串口通讯就是终端I/O的原始模式)时输入属性设置为

term.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);

屏蔽了许多属性,怪不得有人说如果是使用串口通讯c_iflagc_oflag都设置为0就行了!

以下是我的设置的一些重要的串口属性

term.c_cflag |= CLOCAL | CREAD;

       term.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

       term.c_oflag &= ~OPOST;

term.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);

 


--------------------next---------------------

Yaffs2的ecc校验

 

S3C2410的一个板子上移植内核2.6.14和yaffs2文件系统,但ecc校验总是设置不对,总是警告未使用ecc校验,内核配置如下

Device Drivers --->
Memory Technology Devices (MTD) --->
   NAND Flash Device Drivers --->

·  NAND Device Support

[ ] Verify NAND page writes

·  NAND Flash support for S3C2410/S3C2440 SoC

·  S3C2410 NAND driver debug

[ ] S3C2410 NAND Hardware ECC

File systems --->
    Miscellaneous filesystems --->

·  YAFFS2 file system support

 --- 512 byte / page devices

·  Lets Yaffs do its own ECC

·  Use the same ecc byte order as Steven Hill's nand_ecc.c

 --- 2048 byte (or larger) / page devices 

·  Autoselect yaffs2 format 

·  Disable lazy loading 

·  Turn off wide tnodes 

·  Turn off debug chunk erase check 

·  Cache short names in RAM

 

drivers/mtd/nand/s3c2410.c中使用chip->eccmode = NAND_ECC_SOFT;

kernel启动没有出现警告,通过nfs启动后,安装文件系统

mount -t yaffs /dev/mtdblock/3 /mnt
cd mnt
tar xvzf /fa-yaffs-v5.tgz

然后就出现如下警告
./
Reading data from NAND FLASH without ECC is not recommended
Writing data without ECC to NAND-FLASH is not recommended
Writing data without ECC to NAND-FLASH is not recommended
Writing data without ECC to NAND-FLASH is not recommended
./bin/
Writing data without ECC to NAND-FLASH is not recommended
Writing data without ECC to NAND-FLASH is not recommended
……………………………………………………………………
省略几千行

 

耐心等文件系统解压完后,使用/dev/mtdblock/3能正常启动,但只要读/写文件系统内容就会出现上述的警告,看着真是不爽。

上网查看说去掉这种警告有两种方法

1.  去掉警告信息(~掩耳盗铃@_@)

2.  使用MTDecc校验,而不使用yaffs2ecc校验(不知道到底为什么)

在内核选项中去掉Lets Yaffs do its own ECC这个选项,果然成功了。

察看yaffs2源码

yaffs_mtdif.c有如下内容:

if (data && spare) {

        if (dev->useNANDECC) {  /* 配置了Lets Yaffs do its own ECC选项 */

            retval =

                mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,

                      &dummy, data, spareAsBytes,

                      &yaffs_oobinfo);

        } else {

            retval =

                mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,

                      &dummy, data, spareAsBytes,

                      &yaffs_noeccinfo);

        }

mtd关于nand的驱动中nand_base.c有如下内容:

static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,

              size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)

{

    /* use userspace supplied oobinfo, if zero */

    if (oobsel == NULL) /* 当使用yaffs_noeccinfo时,条件语句为真 */

        oobsel = &mtd->oobinfo;

    return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff);

}

nand_do_read_ecc函数中有

eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;

 

在使用yaffs2的ecc校验时在这句就把eccmode赋值为NAND_ECC_NONE(要不就不会出现警告),也就是说oobsel->useecc的值为0,真不知道对不对,使用yaffs2自己的ecc校验时怎么会把这个选项置为0呢?但是从实验看这个猜测应该是对的!

 

真不知道yaffs2的ECC校验和MTD的ECC校验之间到底是个什么样的关系!不知道大家有什么意见!

 


--------------------next---------------------

初装Debian

    公司刚给配了个台式机,正好装个Linux学习学习,选来选去选中了Debian,据说是安全稳定,符合GNU且速度快,而且工具链很全,获得软件的方式简单(正好适合我这样的懒人)。由于没有光驱,所以想用硬盘安装,在网上又google了一番,终于找到了一篇傻瓜式安装教程《》,虽然这篇文章写的已经很详细了,但我在安装时还是遇到了一些问题。

    我安装的是debian 310a sarge版。公司给配的是方正的品牌机,买来时机器上就有windowxp和一个方正自己开发的“方正智能护理专家”的软件,可以备份/恢复系统,还在硬盘上创建了一个6G大小的分区,估计是放系统备份的吧。在装debian的时候需要在MBR中安装GRUB,一开始装到这里就继续不了了,说什么写入MBR失败,后来发现电脑在启动时先引导的是方正的护理软件,是不是把MBR锁住了不让修改呀,格式化掉那个6G的分区,卸载掉方正的那个软件,安装GRUB成功!到了网络检测,使用DHCP自动检测失败,那就稍后在配置吧。这样一步步安装,xwindow终于启动起来了,啊,怎么全是乱码,不过没关系,可以从网络安装字体,完了,刚才网络没配置成功选的稍后配置,而在genome下全是乱码,也不知道在那配置网络,没办法只好重启电脑,进入windows,下载字体文件ttf-arphic-gbsn00lp_2.11-6_all.deb和ttf-arphic-gkai00mp_2.11-6_all.deb重启进入Debian,安装字体,终于可以显示熟悉的中文了。

    配置网络,输入IP地址、网关、DNS,提示网络不可达,怎么回事,仔细一看原来是IP地址和网关不在一个网段内,那windows怎么行呢,上网查找了许文章,也试了几种方法,还是不行,只能问网关本网段的网关地址了,输入后成功上网(唉,早知道这么简单也不用折腾了)。然后配置了数据源,一通apt-get,呵呵,终于可以用来工作/学习了:)


--------------------next---------------------

基于文档视图的NT服务程序

 

    由于工作原因要求开发一个服务程序,需要有人机交互的界面,本想使用对话框模式来完成,但由于菜单、工具栏、分割窗口处理太麻烦,所以选择了文档视图结构,其中遇到了一些困难(其实说白了是对服务程序的理解不够详细)共享出来,以便大家再遇到这个问题时少走弯路。

    先来简要说一下NT服务程序的主要几个环节:

1.       调用main方法来设置service_main方法。

2.       调用service_main方法设置ServiceCtrlHandler方法并启动工作循环(注意是工作循环)。

3.       利用ServiceCtrlHandler方法处理SCM(Service Control Manager)发给服务程序的消息。

第二步是使用工作循环,即代表着service_main方法不能返回直到服务停止,所以使用对话框实现服务程序时就自动符合了这个要求,因为DoMoudle函数直到对话框关闭后才返回,通常程序的处理流程都在对话框中处理,关闭对话框也就代表着要关闭服务程序,这时关闭对话框、DoMoudle函数返回、服务结束,很自然的一个流程就走了下来。但要使用文档视图结构上边这个流程就要做些变动了,因为文档视图结构程序初始化时是先创建文档模板,然后程序初始化完成并返回,所有工作都在MainFrame中完成,这样工作循环就没有建立起来,所以只能想一个变通的办法来实现工作循环,看下代码吧。

 

对话框模式:

 

void Service_start(DWORD dwArgc, LPTSTR *lpszArgv)

{

         CxxxDlg dlg(&dlgParent);

         theApp.m_pMainWnd = &dlg;

         int nResponse = dlg.DoModal();         //       直到对话框关闭函数才返回

         if (nResponse == IDOK)

         {

         }

         else if (nResponse == IDCANCEL)

         {

         }

        

         dlgParent.DestroyWindow();

}

 

文档视图模式:

 

void Service_start(DWORD dwArgc, LPTSTR *lpszArgv)

{

         CSingleDocTemplate* pDocTemplate;

         pDocTemplate = new CSingleDocTemplate(

                  IDR_MAINFRAME,

                  RUNTIME_CLASS(CPLMSPrefixServiceDoc),

                  RUNTIME_CLASS(CMainFrame),      

                  RUNTIME_CLASS(CPLMSPrefixServiceView));

         AddDocTemplate(pDocTemplate);

        

         CCommandLineInfo cmdInfo;

         ParseCommandLine(cmdInfo);

        

         if (!ProcessShellCommand(cmdInfo))

                   return;

        

         m_pMainWnd->ShowWindow(SW_SHOW);

         m_pMainWnd->UpdateWindow();

 

//       m_bIsRunning是服务程序控制开关,

//       TRUE - 服务正在运行,

//       FALSE - 服务程序关闭

//       如果服务程序在运行就一直执行循环(模拟工作循环,

//       但具体工作都在MainFrame中完成)

 

while (m_bIsRunning)           

         {

                   MSG msg;

 

                   while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))

                   {

                            TranslateMessage(&msg);

                            DispatchMessage(&msg);

                   }

 

                  Sleep(50);

         }

}

 

参考文章


--------------------next---------------------

阅读(335) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~