tag 标签: 武汉华嵌

相关博文
  • 热度 8
    2013-6-30 11:16
    717 次阅读|
    0 个评论
          2013年6月28日 ,武汉华嵌科技有限公司受托中船重工凌久信息技术有限公司关于《XXX控制系统嵌入式应用软件开发》的项目通过联合调试和验收,日前已经成功交付委托方。(因涉密,故用XXX代替具体名称)         本项目,华嵌公司主要承担:1、程序总体方案设计 2、代码编码与调试 ,经过近半年的需求分析、程序开发和测试验证,达到7(日)*24(小时)不断电无故障正常运行。在此,感谢中船重工凌久信息技术有限公司对武汉华嵌研发 团队的支持和信任,感谢委托方魏经理团队给与项目研发过程中的大力支持。         武汉华嵌作为华中地区最具影响力的专业嵌入式培训机构,在为广大嵌入式爱好者和企业用户提供优质嵌入式培训服务的同时,凭借强大的技术实力,也为众多的企 业提供嵌入式技术解决方案、项目研发服务,近年来,公司项目承接业务取得了长足的进步,与培训业务一起成为公司的两大主营业务。期待与更多的企业携手,共 创美好未来。   武汉华嵌网址: http://ww.embedhq.org ------分隔线---------------------------- 上一篇: new贺1301期就业班全体就业 下一篇:没有了 
  • 热度 10
    2013-6-3 15:02
    611 次阅读|
    0 个评论
    作者:武汉华嵌  吴老师   嵌入式web server boa 在S3C2410上的移植   开发平台:ubuntu 8.04 目标平台:S3c2410 开发工具:arm 交叉工具链版本3.4.5   boa版本:boa-0.94.13.tar.gz   一、下载源码,生成makefile      1. 下载源码:http://www.boa.org/      2. 拷贝到 /opt 目录下      3.解压 tar zxvf boa-0.94.13.tar.tar      4.cd boa-0.94.13/src      5. ./configure   二、编译前,修改文件 1.  修改Makefile文件,找到CC=gcc和CPP=gcc -E,分别将其改为交叉编译器安装的路径: CC=  arm-softfloat-linux-gnu-gcc CPP= arm-softfloat-linux-gnu-g++ 保存退出。   2. 修改编译方式:  LDFLAGS = -g –static 注: 使用静态编译可以让目标文件自动的包含所需要的 库文件,而动态编译需要手工拷贝库文件。 3.修改/src/defines.h文件:   #define SERVER_ROOT "/etc/boa"   4 修改boa-0.94/src/ util.c文件 修改char *get_commonlog_time(void)函数。 time_offset = 0;   5. 修改src/config.c:加Current_uid=1   6. 修改compat.h: 把第120 行的 #define TIMEZONE_OFFSET(foo)foo##-tm_gmtoff 修改为: #define TIMEZONE_OFFSET(foo)foo-tm_gmtoff   7.修改/src/boa.c,注释掉下面两行:  /* if (setuid(0) != -1) {             DIE("icky Linux kernel bug!");         } */   /*if (passwdbuf == NULL) {             DIE("getpwuid");         }*/   8 :config.c  /*if (!server_name) {         struct hostent *he;         char temp_name ;           if (gethostname(temp_name, 100) == -1) {             perror("gethostname:");             exit(1);         }           he = gethostbyname(temp_name);         if (he == NULL) {             perror("gethostbyname:");             exit(1);         }           server_name = strdup(he-h_name);         if (server_name == NULL) {             perror("strdup:");             exit(1);         }     }*/   9. /src/log.c中的修改:注释掉: /*     if (dup2(error_log, STDERR_FILENO) == -1) {             DIE("unable to dup2 the error log");         } */                                                            10. 在boa.conf中的修改: (1) ServerName的设置  修改#ServerName www.your.org.here 为 ServerName www.your.org.here     注意:该项默认为未打开,执行Boa会异常退出,提示“gethostbyname::No such file or directory”,所以必须打开。其它默认设置即可。       注意:以下是为改为下面这样的: (2)User与Group的修改:     User 0     Group 0 (3)ErrorLog /var/log/boa/error_log     AccessLog /var/log/boa/access_log  (4)DocumentRoot /var/www  (5)DirectoryIndex index.html  (6)KeepAliveMax 1000     KeepAliveTimeout 10  (7)MimeTypes /etc/mime.types  (8)ScriptAlias /cgi-bin/ /var/www/cgi-bin/     三、编译并移植   1.编译 boa       # make       # arm-softfloat-linux-gnu-strip boa     2,将mime.types文件复制目标板根文件系统/etc目录下   3。在开发板上         cd /etc         mkdir boa     把开发机上的 (配置文件)boa.conf  (编译结果)boa  defines.h 这3个文件拷贝到 开发板/etc/boa/ 下    4.  在开发板上       cd /var       mkdir  www  (这个文件夹内可以放网页)       mkdir /var/log/boa   四、 编写CGI脚本测试 1、编写Helloworld.c程序 int main(void) {       printf("Content-type:text/html\n\n"); //这句一定要加上       printf(" Hello,world.");       exit(0); }   arm-softfloat-linux-gnu-gcc -o helloworld helloworld.c   2、浏览     将helloworld拷贝至/var/www/cgi-bin/下,浏览器输入开发板IP地址即可看到web信息。       ------分隔线---------------------------- 上一篇:RT73 wifi无线网卡驱动移植过程 下一篇:多路复用select与poll
  • 热度 10
    2013-4-19 11:53
    980 次阅读|
    0 个评论
    Linux 进程间通信之信号量 作者:武汉华嵌技术部   信号量是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语。在UNIX下有三种分别如下: Posix有名信号量; Posix基于内存的信号量; System V信号量。 在这里只和大家分享下有关System V信号量。 System V通过定义计数信号量集来对信号量的操作,计数信号量集是一个或多个信号量构成一个集合,其中每个都是计数信号量。对于系统中的每个信号量集,内核维护一个如下的信息结构,它定义在sys/sem.h头文件中。 struct semid_ds{ struct ipc_perm  sem_perm;     /* operation permission struct */ struct sem      *sem_base;     /* ptr to array of semaphores in set */ uishort          sem_nsems;    /* #of semaphores in set */ time_t          sem_otime;    /* time of last semop() */ time_t          sem_ctime;    /* time of creation or last IPC_SET */ };   成员struct sem结构如下:          struct sem{          ushort_t   semval;    /* semaphore value , nonnegative */          short      sempid;    /* PID of last successful semop(), SETVAL, SETALL */          ushort_t   semncnt;   /* awaiting semval current value */          ushort_t   semzcnt;    /* awaiting semval = 0 */          };   注意在struct semid_ds结构中的sem_base含有指向某个sem结构数组的指针:当前信号量集中的每个信号对应其中一个数组元素。我们可以把内核中的某个选定信号量图解成指向一个sem结构数组的一个semid_ds结构。图解如下: 有了以上的理论,那么接下来我们来探讨下如何对这样的信号量进行操作,linux操作系统为我们提供了操作system v信号量的API函数,以下就开始讲解这些API函数。 semget函数创建一个信号量集或访问一个已存在的信号量集。 #include sys/sem.h int semget(key_t key, int nsems, int oflag); 该函数成功返回时,其返回值是一个称为信号量标识符的整数,semop和semctl使用它。出错则返回-1。 nsems参数指定集合中的信号量数。如果我们创建一个新的信号量集,而只是访问一个已存在的集合,那就可以把该参数指定为0。一旦创建完一个信号量集,我们就不能改变其中的信号量数。 oflag值是一些权限值的组合,如果是创建一个信号量集,那么得在此oflag的基础上或上O_CREAT或者是O_CREAT|O_EXCL。 此函数不可以对创建的信号量集中的信号量进行初始化,对信号量的初始化是通过另外的一个函数semctl进行的。 通过semctl函数对信号量集中的信号量进行初始化。 #include sys/sem.h int semctl(int semid, int semnum, int cmd, …./* union semun arg*/   ) ;          semid标识其操作待控制的信号量集。          semnum标识该信号量集内的某个成员(0, 1等待,直到nsems -1)。semnum值仅仅用于GETVAL、SETVAL、GETNCNT、GETZCNT和GETPID命令。          第四个参数是可选的,取决于第三个参数cmd。union semnu结构如下: union semnu{          int              val;     /* used for SETVAL only */          struct semid_ds   *buf;    /* used for IPC_SET and IPC_STAT */          ushort          *array;   /* used for GETALL and SETALL */          };          这个联合体并没有出现在任何头文件中,因而必须由应用程序声明。 第三个参数cmd可以取以下值: GETVAL  把semval的当前值作为函数返回值返回。 SETVAL  把semval值设置为arg.val。如果操作成功,那么相应信号量在所有进程是的信号                    量调整值(semadj)将被置为0。 IPC_RMID 把由semid指定的信号量集从系统中删除掉。 IPC_SET 设置所指定信号量集的semid_ds结构中的某些成员。 IPC_SET R 返回所指定信号量集当前的semid_ds结构。 使用semget得到一个信号量集,使用semctl设置信号量集中的信号量,那么对信号量集中的信号通过semop来进行操作。 #include sys/sem.h int semop(int semid, struct sembuf *opsptr, size_t nops); semid标识其操作的信号量集。 其中opsptr指向一个如下结构的数组: Struct sembuf{ Short    sem_num;     /* semaphore number: 0, 1, …., nsems-1 */ Short    sem_op;      /* semaphore operation: 0, 0, 0 */ Short    sem_flag;     /* semaphore flags : 0, IPC_NOWAITE, SEM_UNDO */ }; nops参数指出由opsptr指向的sembuf结构数组中元素的数目。该数组中的生个元素给目标信号量集内某个特定的信号量指定一个操作。这个特定的信号量由sem)num指定,0代表第一个元素,1代表第二个元素,依次类推,直到nsems-1,其中nsems是目标信号量集内成员信号量的数目。 semop对信号的操作是由sem_op的值确定的,以下是对sem_op取值的分析: 、sem_op 为正数时,会把sem_op的值加到操作的信号量的信号值上。如果sem_***被设置为IPC_UNDO,无论程序正常结束与否,都会把信号值重新设置为调用semop函数前得值。这对应于进程释放占用的资源数。 、sem_op为负数时,如果要操作的信号量的值大于或者等于sem_op的绝对值,则从信号量值中加上sen_op的值。如果信号量值小于sem_op的绝对值,则有如下: 如果sem_***的值为IPC_NOWAIT,那么semop出错,返回EAGAIN。 如果sem_***没有设置为IPC_NOWAIT,则该信号量的semncnt的值加1,然后此进程挂起,直到此信号量的值大于sem_op的绝对值,才执行semop操作;或者此信号量从系统中删除,此时semop返回EIDRM;或者该挂起进程捕捉到信号,从信号处理程序返回,此时,semop出错返回EINTR。 如果sen_op的值为0,则调用进程希望等到该信号量值变成0。 、sem_op为0时,那么调用者希望等待到semval变为0。如果sem_op已经是0,那就立即返回。   以下是利用信号量来进行一个PV操作,实现代码如下:   //初始化信号量 int init_sem(int semid, int semval) {          SYS_NUM semnu;          semnu.sem_val = semval;          if((semctl(semid, 0, SETVAL, semnu)) 0)          {                    perror("init_sem semctl");                    return -1;          }          return 0; }   //对信号量进行p操作 int sem_p(int semid) {          SYS_SEM sembu;            sembu.sem_num = 0;          sembu.sem_op = -1;          sembu.sem_*** = SEM_UNDO;            if((semop(semid, sembu, 1)) 0)          {                    perror("sem_p semop");                    return -1;          }          return 0; }   //对信号量进行v操作 int sem_v(int semid) {          SYS_SEM sembu;            sembu.sem_num = 0;          sembu.sem_op = 1;          sembu.sem_*** = SEM_UNDO;                   if((semop(semid, sembu, 1)) 0)          {                    perror("sem_v semop");                    return -1;          }          return 0; }   //删除信号量集 int del_sem(int semid) {          if((semctl(semid, 0, IPC_RMID)) 0)          {                    perror("del_sem semctl");                    return -1;          }          return 0;  }     总结:          信号量往往是用来同步的,保护共享内存。 ------分隔线----------------------------   上一篇:Linux进程间通信之消息队列 下一篇:Linux进程间通信之共享内存
  • 热度 9
    2012-8-18 10:46
    792 次阅读|
    0 个评论
    在嵌入式系统的设计中,仿真应用的范围主要集中在对程序的仿真上。在ARM的开发过程中,一种最简单和原始的开发流程是:编写程序,然后烧写到芯片上验证功能,这种方法对于简单的小系统是可以对付的,但在大系统中使用这种方法则是完全不可能的。所以很多时候我们需要在不烧写代码的情况下调试程序,这就是仿真调试技术。 现代调试技术可以分为软件仿真调试和硬件仿真调试两种: 一.软件仿真(指令集仿真): 概念: 用数据结构描述目标机CPU中各个寄存器和其他资源(内存等),通过软件模拟,可以逐条指令解释执行目标机可执行映象中的程序。 应用场合: ●  当嵌入式软件开发在目标硬件平台不存在的情况下进行,就要使用这种软件来模拟目标CPU,以验证代码逻辑。         ●  是学习嵌入式开发有效地工具,可以让学习者从底层具体硬件细节中解脱出来,专注于软件,尤其是与具体硬件无关的系统软件(TCP/IP协议栈)。 几个不错的硬件模拟平台: ●  Skyeye:清华大学计算机系博士后陈渝发起,开源项目,主要模拟ARM内核CPU。         ●  ARMulator:ARM公司推出,ARM指令集模拟器(ADS,Realview MDK上就用这个)。         ●  ZIX:一个快捷高效、功能强大、易于配置的嵌入式Linux开发环境。 软件仿真的缺点: 无法完全仿真与硬件相关的部分,最终还要通过硬件仿真来完成最终的设计。 二.硬件仿真调试: 以前的芯片没有JTAG调试逻辑,要向仿真它就必须要有专门的仿真器,这种仿真器成本较高,而且每种芯片都不一样,现在这种仿真器已经不存在了。 现在的芯片一般都内置了JTAG调试逻辑,并不需要CPU仿真器,需要的只是一个JTAG协议转接器(现在还称其为仿真器,其实叫做调试器比较合适)。所以下面主要介绍JTAG及其仿真技术。 JTAG简介 JTAG是Joint Test Action Group的简称,该组织致力于统一芯片的测试标准,它们最初向IEEE提出了IEEE1149.1标准,后来经过IEEE批准并且标准化,所以IEEE1149.1标准又叫JTAG标准,它是一套芯片测试接口和标准,现在几乎所有的CPU核里面都会实现JTAG逻辑单元。JTAG原本是用来测试芯片设计是否正确,其基本原理就是在芯片的各个管脚上放置锁存器,然后串联起来构成移位寄存器,可以监控芯片管脚的输入和输出。后来大家发现用JTAG在线调试芯片非常方便(其实就是利用JTAG控制CPU内核),还不需要设计专门的仿真芯片,因此就出现了用JTAG调试风行的局面。 边界扫描技术(Boundary-Scan): JTAG调试主要就是基于这种边界扫描技术。 边界扫描技术的基本思想是在靠近芯片的输入输出管脚上增加一个移位寄存器单元。因为这些移位寄存器单元都分布在芯片的边界上,所以被称为边界扫描寄存器 (Boundary-Scan Register Cell) 。当芯片处于调试状态的时候,这些边界扫描寄存器可以将芯片和外围的输入输出隔离开来。通过这些边界扫描寄存器单元,可以实现对芯片输入输出信号的观察和控制。 JTAG的主要作用: ●    检测芯片是否良好                 ■这是JTAG最初设计的目标 ●    镜像文件的烧写功能                 ■可以烧写编译出来的二进制或者十六进制可执行文件到目标板的Flahs芯片上                 ■当开发板为裸板(没有固化任何程序)的时候,通常需要通过JTAG接口下载bootloader                 ■调试功能                 ■JTAG接口为宿主机和目标系统之间的通信、控制提供了方便的途径 ARM7TDMI调试架构: 一个调试系统通常包含三个部分: ●    调试主机                 ■是一台运行调试软件(ADS,Keil等)的计算机                 ■可以发出一些高层的调试命令,设置断点,访问内存等 ●    协议转换器                 ■将调试主机发出的高层调试命令转换为底层的ARM JTAG调试命令                 ■调试目标                 ■基于目标芯片的开发板 ARM7TDMI典型的调试架构如下图所示: 经过协议转换器进行命令解释,主机上运行的调试软件就可以通过JTAG接口直接和目标芯片对话了。 为了支持底层的调试,ARM7TDMI提供了硬件上的调试扩展,包括: ●  停止程序的运行         ●  检查和修改ARM7TDMI的内核状态         ●  观察和修改内存         ●  恢复程序的运行 常见ARM调试工具: ●    BDI1000/2000/3000                 ■非常好的调试工具,可以调试ARM、MIPS、PowerPC、Xscale等多种架构处理器                 ■JTAG下载速度可以上兆,以太网接口                 ■性能优越但是价格不菲,可以调试Linux内核这种复杂的代码 ●    U-Link                 ■U-Link是Keil公司做的用于ARM和某些增强型8051单片机调试的工具                 ■由于Keil公司做的时候没有加密,导致现在盗版满天飞                 ■U-link仅仅支持Keil,JTAG下载速度20K~30K U-Link下载程序不是简单通过JTAG,而是先用JTAG下载一段固件程序到目标板,然后再用这个固件程序和JTAG把用户代码写入Flash以提高速度 ●    J-Link                 ■J-Link是IAR公司为ARM芯片开发的调试工具                 ■支持RDI协议的调试工具,如Keil、ADS、IAR等                 ■J-Link不支持ARM10以上的内核                 ■JTAG下载速度400K~500K ●    Multi-ICE                 ■ARM公司原创调试工具,支持全系列ARM芯片                 ■JTAG下载速度130K左右 ●    Wiggler电缆                 ■Wiggler是世界上最泛滥的一种调试工具                 ■结构非常简单:一片74HC244 + 一个9013 + 几个电阻                 ■性能一般,但是价格非常便宜                 ■后人又在Wiggler的硬件基础上开发了很多的调试工具,例如大名鼎鼎的H-Jtag   更多技术文章敬请关注:武汉华嵌-嵌入式培训专家,国内领先的嵌入式服务机构, http://www.embedhq.org
  • 热度 6
    2012-8-17 14:01
    1155 次阅读|
    0 个评论
    共享内存区是可用IPC形式中最快的。一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传递就不再涉及内核(这里说的不涉及内核的含义是:进程不再通过执行任何进入内核的系统调用来彼此传递数据)。然而往该共享内存区存放信息或从中取走信息的进程间通常需要某种形式的同步,同步的方式有多种,比如:信号量、互斥锁等等。     以下两图分别描述了读写消息时,一个要进入内核,而一个不进入内核的情况:   对于System V共享内存区,内核维护如下的信息结构,它定义在sys/shm.h头文件中: struct shmid_ds{ struct ipc_perm      shm_perm;    /* operation permission struct */ size_t              shm_segsz;     /* segment size */ . . . };   有了以上的知识,那么如何来对共享内存进行操作呢,以下就开始讲解如何来操作: 创建一个新的共享内存区,或者访问一个已存在的共享内存区。 #include sys/shm.h int shmget(key_t key, size_t size, into flag); size以字节为单位指定内存区的大小。当实际操作为创建一个新的共享内存区时,必须指定一个不为0的size值。如果实际操作为访问一个已存在的共享内存区,那么size应为0。 oflag为读写权限值的组合。它还可以与IPC_CREAT或IPC_CREAT|IPC_EXCL按位或。 当实际操作为创建一个共享内存区时,该内存区被初始化为size字节的0。 由shmget创建或打开一个共享内存区后,通过调用shmat把它附接到调用进程的地址空间。 #include sys/shm.h void *shmat(int shmid, const void *shmaddr, int flag); shmid是由shmget返回的标识符。Shmat的返回值是所指定的共享内存区在调用进程内的起始地址。确定这个地址的规则如下: 如果shmaddr是一个空指针,那么系统替调用者选择地址。(这个是推荐的方法) 如果shmaddr是一个非空指针,那么返回地址取决于调用者是否给flag参数指定了SHM_RND: 如果没有指定SHM_RND,那么相应的共享内存区附接到由shmaddr参数指定的地址; 如果指定了SHM_RND,那么相应的共享内存区附接到由shmaddr参数指定的地址向下舍入一个SHMLBA常值。 当一个进程完成共享内存区的使用时,它可调用shmdt断接这个内存区。 #include sys/shm.h int shmdt(const void *shmaddr); 当一个进程终止时,它当前附接着的所有共享内存区都自动断接掉。 注意:本函数调用并不删除所指定的共享内存区。 shmctl提供了对一个共享内存区的多种操作。 #icnldue sys/shm.h int shmctl(int shmid, int cmd, struct shmid_ds *buff); 该函数提供了三个命令: IPC_RMID  从系统中删除由shmid标识的共享内存区并拆除它。 IPC_SET    给所描写的共享内存区设置其shmid_ds结构的某些成员。 IPC_STAT   向调用者返回所指定共享内存区当前的shmid_ds结构。   以下是共享内存结合信号量进行操作的部份代码:   发关进程的部份代码: //创建一个共享内存区 if((shmid1 = shmget(shmkey1, MAX_SHEARE_MEM_SIZE, IPC_CREAT|0666)) 0) {            perror("shmget"); } //把共享内存区附接到调用进程的地址空间 if((sharmem = shmat(shmid1, NULL, 0)) 0) {            perror("shmat"); }   while(1) {            sem_p(semid1);   //semid1进行p操作,保护共享区            memset(buff, 0, MAX_SHEARE_MEM_SIZE);            printf("Input ou want to say with you friend!\n");            fgets(buff, MAX_SHEARE_MEM_SIZE, stdin);            if(strncmp(buff, "quit", 4))            {                     //往共享内存区放入数据                     strncpy(sharmem, buff, MAX_SHEARE_MEM_SIZE);                     sem_v(semid2);  //semid2进行v操作,释放对共享区的保护            }            else            {                     strncpy(sharmem, buff, MAX_SHEARE_MEM_SIZE);                     sem_v(semid2);                     break;            } } 接收进程部份代码: while(1) {            sem_p(semid2);  //semid2进行p操作,保护共享区            memset(buff, 0, MAX_SHEARE_MEM_SIZE);            strncpy(buff, sharmem, MAX_SHEARE_MEM_SIZE); //从共享内存区取出数据            printf("receive from you friend : %s\n", buff);            if(!strncmp(buff, "quit", 4))            {                     del_sem(semid1);                     del_sem(semid2);                                  break;            }            sem_v(semid1);  //semid1进行v操作,释放对共享区的保护 } //删除共享内存区 if((shmctl(shmid1, IPC_RMID, NULL)) 0) {            perror("shmctl"); }   更多技术文章敬请关注:武汉华嵌-嵌入式培训专家,国内领先的嵌入式服务机构, http://www.embedhq.org