读书人

是高手就进来帮帮忙!ARM9(2440)多线

发布时间: 2012-02-13 17:20:26 作者: rapoo

是高手就进来帮帮忙!ARM9(2440)多线程串口编程,运行错误:__gnu_cxx::__concurrence_broadcast_error
在ARM9运行多线程串口程序是抛出这样的异常:terminate called after throwing an instance of '__gnu_cxx::__concurrence_broadcast_error'
what(): __gnu_cxx::__concurrence_broadcast_error

只要以调用OpenPort就报错。

该源代码在Fedora9上编译、运行都没问题,程序中用了网上找到的一个多线程串口类。
编译器用的是gcc 4.4.3

Google、百度边了也没找到解决方法,各位有什么解决方法或思路不?
希望大家能帮帮忙,多谢!!!!!!!!

C/C++ code
//主程序#include "CSerial.h"#include <string>using namespace std;int main(int argc, char* argv[]){    CSerial::CSerial serial;    serial.OpenPort("/dev/ttySAC0", 115200, 8, 1, 'N');//报错!!    while(1);    return 0;}


C/C++ code
/*自定义串口类* CSerial.h**  Created on: 2010-7-20*      Author: yzm*/#ifndef CSERIAL_H_#define CSERIAL_H_#include      <pthread.h>#include      <time.h>#include      <stdio.h>#include     <sys/types.h>#include     <sys/stat.h>#include     <fcntl.h>      /*文件控制定义*/#include     <termios.h>    /*PPSIX 终端控制定义*/#include     <errno.h>      /*错误号定义*/#include      <string.h>#include     <string>#include      "CCriticalSection.h"using namespace std;#define      BUFFER_LENGTH 1024namespace CSerial {class CSerial{private:    string m_PortName;    int  m_baudrate;    int m_databits;    int m_stopbits;    char m_parity;     //通讯线程标识符ID     pthread_t      m_thread;     CCriticalSection  mutex;     // 串口数据接收线程     static void* ReceiveThreadFunc( void* lparam );public:     CSerial();     virtual ~CSerial();     // 已打开的串口文件描述符     int                m_fd;     int                m_DatLen;     unsigned char      DatBuf[BUFFER_LENGTH];     int                m_ExitThreadFlag;     // 按照指定的串口参数打开串口,并创建串口接收线程     int OpenPort( string PortName, int baudrate, int databits, int stopbits, char parity );     // 关闭串口并释放相关资源     int ClosePort( );     // 向串口写数据     int WritePort( unsigned char* Buf, int len );     // 接收串口数据处理函数     virtual int PackagePro( unsigned char* Buf, int len );private:    void set_speed(int fd, int speed);    int  set_Parity(int fd,int databits,int stopbits,int parity);};}#endif /* CSERIAL_H_ */


C/C++ code
/** CSerial.cpp**  Created on: 2010-7-20*      Author: yzm*/#include "CSerial.h"#include <sys/select.h>#include <sys/time.h>#include <stdlib.h>#include <unistd.h>     /*Unix 标准函数定义*/namespace CSerial {int speed_arr[] = {B115200,B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400,        B19200, B9600, B4800, B2400, B1200, B300, };int name_arr[] = {115200,38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200,        9600, 4800, 2400, 1200, 300, };string BYTE2HEX(unsigned char* buffer,int nSize){    char buf[1024];    memset(buf,0,1024);    int len = 0;    for(int i = 0;i < nSize;i++)    {        int tmp = sprintf(buf + len,"%02x ",buffer);        len += tmp;    }    string str(buf);    return str;}CSerial::CSerial(){    m_ExitThreadFlag = false;    m_PortName = "/dev/ttyS0";    m_baudrate = 2400;    m_databits = 8;    m_stopbits = 1;    m_parity = 'e';}CSerial::~CSerial(){    ClosePort( );}int CSerial::OpenPort(string PortName, int baudrate, int databits,        int stopbits, char parity) {    /*以读写方式打开串口*/    m_fd = open(PortName.data(), O_RDWR);    if (-1 == m_fd) {        /* 不能打开串口一*/        perror(" 提示错误!");        return -1;    } else {        m_PortName = PortName;        m_baudrate = baudrate;        m_databits = databits;        m_stopbits = stopbits;        m_parity = parity;        //设置参数        set_speed(m_fd, baudrate);        set_Parity(m_fd, databits, stopbits, parity);        pthread_create(&m_thread,NULL,CSerial::CSerial::ReceiveThreadFunc,this);        return 1;    }}int CSerial::ClosePort( ){     m_ExitThreadFlag = true;     close(m_fd);     pthread_join(m_thread,NULL);     return 1;}int CSerial::PackagePro( unsigned char* Buf, int len ){    string str = BYTE2HEX(Buf,len);    printf("%s\r\n",str.data());    WritePort(Buf,len);    return 1;}void* CSerial::ReceiveThreadFunc(void* lparam) {    CSerial *pSer = (CSerial*) lparam;    fd_set fdRead;    int ret;    struct timeval aTime;    while (1) {        //收到退出事件,结束线程        //printf("Thread...\r\n");        if (pSer->m_ExitThreadFlag) {            break;        }        FD_ZERO(&fdRead);        FD_SET(pSer->m_fd,&fdRead);        aTime.tv_sec = 2;        aTime.tv_usec = 100;        ret = select(pSer->m_fd + 1, &fdRead, NULL, NULL, &aTime);        if (ret < 0) {            //关闭串口            pSer->ClosePort();            break;        }        if (ret > 0) {            //判断是否读事件            if (FD_ISSET(pSer->m_fd,&fdRead)) {                //data available, so get it!                pSer->m_DatLen = read(pSer->m_fd, pSer->DatBuf, BUFFER_LENGTH);                // 对接收的数据进行处理,这里为简单的数据回发                if (pSer->m_DatLen > 0) {                    pSer->PackagePro(pSer->DatBuf, pSer->m_DatLen);                }                // 处理完毕            }        }    }    printf("ReceiveThreadFunc finished\n");    pthread_exit(NULL);    return 0;}/***@brief  设置串口通信速率*@param  fd     类型 int  打开串口的文件句柄*@param  speed  类型 int  串口速度*@return  void*/void CSerial::set_speed(int fd, int speed) {    unsigned int i;    int status;    struct termios Opt;    tcgetattr(fd, &Opt);    for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {        if (speed == name_arr) {            tcflush(fd, TCIOFLUSH);            cfsetispeed(&Opt, speed_arr);            cfsetospeed(&Opt, speed_arr);            status = tcsetattr(fd, TCSANOW, &Opt);            if (status != 0) {                perror("tcsetattr fd1");                return;            }            tcflush(fd, TCIOFLUSH);        }    }}/***@brief   设置串口数据位,停止位和效验位*@param  fd     类型  int  打开的串口文件句柄*@param  databits 类型  int 数据位   取值 为 7 或者8*@param  stopbits 类型  int 停止位   取值为 1 或者2*@param  parity  类型  int  效验类型 取值为N,E,O,,S*/int CSerial::set_Parity(int fd, int databits, int stopbits, int parity) {    struct termios options;    if (tcgetattr(fd, &options) != 0) {        perror("SetupSerial 1");        return (false);    }    options.c_cflag &= ~CSIZE;    switch (databits) /*设置数据位数*/    {    case 7:        options.c_cflag |= CS7;        break;    case 8:        options.c_cflag |= CS8;        break;    default:        fprintf(stderr, "Unsupported data size\n");        return (false);    }    switch (parity) {    case 'n':    case 'N':        options.c_cflag &= ~PARENB; /* Clear parity enable */        options.c_iflag &= ~INPCK; /* Enable parity checking */        break;    case 'o':    case 'O':        options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/        options.c_iflag |= INPCK; /* Disnable parity checking */        break;    case 'e':    case 'E':        options.c_cflag |= PARENB; /* Enable parity */        options.c_cflag &= ~PARODD; /* 转换为偶效验*/        options.c_iflag |= INPCK; /* Disnable parity checking */        break;    case 'S':    case 's': /*as no parity*/        options.c_cflag &= ~PARENB;        options.c_cflag &= ~CSTOPB;        break;    default:        fprintf(stderr, "Unsupported parity\n");        return (false);    }    /* 设置停止位*/    switch (stopbits) {    case 1:        options.c_cflag &= ~CSTOPB;        break;    case 2:        options.c_cflag |= CSTOPB;        break;    default:        fprintf(stderr, "Unsupported stop bits\n");        return (false);    }    options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN);  /*Input*/    options.c_iflag  &= ~(IXON | IXOFF | IXANY);//关流控    options.c_iflag  &= ~(INLCR | IGNCR | ICRNL | IUCLC | IGNBRK|BRKINT|PARMRK|ISTRIP);    options.c_oflag  &= ~(ONLCR | OCRNL | ONLRET | ONOCR | OLCUC | OFILL | CRTSCTS);    options.c_oflag  &= ~OPOST;   /*Output*/    /* Set input parity option */    if (parity != 'n')        options.c_iflag |= INPCK;    tcflush(fd, TCIFLUSH);    options.c_cc[VTIME] = 50; /* 设置超时15 seconds*/    options.c_cc[VMIN] = 0; /* Update the options and do it NOW */    if (tcsetattr(fd, TCSANOW, &options) != 0) {        perror("SetupSerial 3");        return (false);    }    return (true);}int CSerial::WritePort( unsigned char* Buf, int len ){    mutex.Lock();    int ToWrite = len;    int hasWrite = 0;    int wPos = 0;    while(ToWrite > 0){        hasWrite = write(m_fd, Buf + wPos, ToWrite);        if(hasWrite <= 0)break;        ToWrite -= hasWrite;        wPos += hasWrite;    }    mutex.Unlock();    return len - ToWrite;}} 



C/C++ code
#ifndef __CCRITICALSECTION_H#define __CCRITICALSECTION_H#include <pthread.h>class CCriticalSection{private:   pthread_mutex_t mutex;public:   CCriticalSection();   ~CCriticalSection();public:   void Lock();   void Unlock();};#endif


C/C++ code
#include "CCriticalSection.h"CCriticalSection::CCriticalSection(){    pthread_mutex_init(&mutex,NULL); }CCriticalSection::~CCriticalSection(){   pthread_mutex_destroy(&mutex); }void CCriticalSection::Lock(){   pthread_mutex_lock(&mutex);}void CCriticalSection::Unlock(){  pthread_mutex_unlock(&mutex);}


[解决办法]
楼主是使用的arm编译器是哪个?
terminate called after throwing an instance of '__gnu_cxx::__concurrence_broadcast_error'

这样的错误之前俺也遇到过。
问题是程序编译通过,但是运行是来main函数都没有跑到,然后就抛出异常了。
后来查明是该编译器对stl的支持不好,所以将
C/C++ code
<iostream><string>using namespace std;
[解决办法]
第一个可能原因是pthread的问题
看看你用的arm工具链的pthread库是否正确复制到目标机里了
如果不是系统路径,链接时使用-Wl,-rpath=... -Wl,--dyanmic-linker=...来确定路径

第二个可能原因是有的嵌入式系统不支持异常,这也是1L的说法
如果你确定没有在代码里使用异常,那么尝试在编译开关里加入-fno-exceptions。

读书人网 >UNIXLINUX

热点推荐