Страниц: [1]
  Печать  
Автор Тема: Одновременная работа с двумя последовательными портами RS-485  (Прочитано 8005 раз)
_oligarch
Участник
*
Offline Offline

Сообщений: 19


Просмотр профиля
« : Июня 19, 2009, 09:45:29 am »

Приветствую.
Имеется плата с контроллером AT91SAM9260. Данный контроллер имеет около трех уартов, которые могут работать в режиме RS-485. Для своего проекта мне было необходимо два порта RS-485. Я перевел два уарта в этот режим (при помощи mmap_device_io() и outle32()). Теперь не запариваюсь о том как дергается нога RTS, потому что это делает аппаратно за меня контроллер.
Задача стоит такая: необходимо работать с двумя портами одновременно. Распихал обращение к этим портам в два разных потока. В каждом потоке что то типа следущего:

write(fd,out,counter1);
readcond(fd,in,counter2,counter2,1,0,1);
delay(10);

Возникает ошибка по приему у того потока, который работает с тем уартом, который настроен на больший битрейт(пробовал менять битрейты но результат тот же: в потоке с наивысшим битрейтом возникают ошибки). readcond в этом потоке принимает на два-три символа меньше чем положено.
Эти два потока никак не засинхронизированы, просто работают с двумя разными портами. Причем каждый поток по отдельности работает безукоризненно. Изза чего могут возникать эти ошибки?
спасибо.
Записан
ed1k
QOR.Moderator
*****
Offline Offline

Сообщений: 739


Просмотр профиля WWW
« Ответ #1 : Июня 19, 2009, 09:49:32 pm »

readcond() по документации принимает 6 аргументов, а вы ей около семи аргументов даете. Трудно понять, что вы хотите сделать.
Записан
rw9uao
Участник
*
Offline Offline

Сообщений: 33


Просмотр профиля
« Ответ #2 : Июня 20, 2009, 08:09:19 am »

раскидывал по разным потокам. гонял модбас. ошибок не было. подробностей не скажу, но заводил таймаут и вычитавал известное количество байт. работало стабильно.
Записан
_oligarch
Участник
*
Offline Offline

Сообщений: 19


Просмотр профиля
« Ответ #3 : Июня 22, 2009, 07:59:43 am »

ну ошибся чуть чуть:
readcond(fd,in,counter2,counter2,0,1);
два потока работают одновременно, но иногда (раз в полминуты) возникает ошибка по приему. Уже не знаю че и делать. запихать чтоли в один поток? - несимпатично это будет(
Записан
_oligarch
Участник
*
Offline Offline

Сообщений: 19


Просмотр профиля
« Ответ #4 : Июня 23, 2009, 06:53:14 am »

rw9uao, какой таймаут вы заводили и из чего вычитали колличество байт?
Записан
rw9uao
Участник
*
Offline Offline

Сообщений: 33


Просмотр профиля
« Ответ #5 : Июня 23, 2009, 04:05:09 pm »

блин, год прошел. не помню я. заводил два потока, один модбас мастер, другой модбас слэйв. оба на 9600. типа так
Код:
//open COM port   
    ser = open("/dev/ser1", O_RDWR /*| O_NOCTTY | O_NDELAY*/ | O_NONBLOCK );
    fcntl(ser, F_SETFL, 0);

//setup COM port
    tcgetattr (ser, &tattr);
    cfmakeraw (&tattr);
    cfsetospeed (&tattr, B9600);
    cfsetispeed (&tattr, B9600);
    tattr.c_cflag |= (CLOCAL | CREAD);
    tattr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    tattr.c_oflag &= ~OPOST;
    tattr.c_cc[VMIN] = 0;
    tattr.c_cc[VTIME] = 0;//без ограничения
    tcsetattr (ser, TCSANOW, &tattr);

        tcflush(ser, TCIOFLUSH);
        write(ser, buffer, 8);

        //за это время должен прийти ответ
        usleep(200000);//200 mSec
        bytes_read = read(ser, buffer, temp);
Записан
_oligarch
Участник
*
Offline Offline

Сообщений: 19


Просмотр профиля
« Ответ #6 : Июня 25, 2009, 08:40:46 am »

в моей задаче время очень важно и нельзя себе позволить простоять лишний десяток мс. поэтому я читаю по ридконду. заводить такой таймаут - неподходит для задачи. должны быть другие решения проблемы.
Записан
dmrom
Участник
*
Offline Offline

Сообщений: 12


Просмотр профиля
« Ответ #7 : Июня 25, 2009, 11:26:28 am »

в моей задаче время очень важно и нельзя себе позволить простоять лишний десяток мс.

По мануалу таймауты в readcond() измеряются по 100мс.

Когда я писал программу для работы по mоdbus, то пробовал следующие способы:
(остановился на первом)

Код:
    struct timespec t_out;
    t_out.tv_sec  = 0;
    t_out.tv_nsec = timeout * 1000;
    int res = timer_timeout( CLOCK_MONOTONIC,
      _NTO_TIMEOUT_SEND | _NTO_TIMEOUT_REPLY, &FEvent, &t_out, NULL );
    if( EOK == res ) res = read( fd, buf, 1 );
или
Код:
    ualarm( (useconds_t)timeout, 0 );
    int res = read( fd, buf, 1 );
    ualarm( 0, 0 );
или
Код:
    struct itimerspec itime;
    itime.it_value.tv_sec = 0;
    itime.it_value.tv_nsec = timeout * 1000;
    itime.it_interval.tv_sec = 0;
    itime.it_interval.tv_nsec = 0;
    timer_settime( FTimerID, 0, &itime, NULL );
    int res = read( fd, buf, 1 );
    itime.it_value.tv_sec = 0;
    itime.it_value.tv_nsec = 0;
    itime.it_interval.tv_sec = 0;
    itime.it_interval.tv_nsec = 0;
    timer_settime( FTimerID, 0, &itime, NULL );
Записан
_oligarch
Участник
*
Offline Offline

Сообщений: 19


Просмотр профиля
« Ответ #8 : Июня 25, 2009, 01:43:43 pm »

да, readcond'овские таймауты измеряются в 100 мс, но дело в том, что я знаю число байт, которые должны прийти, и поэтому не приходится ожидать 100 мс как признак конца пакета.
Проблема не в этом! Каждый из потоков работает хорошо по отдельности, но стоит включить их на выполнение одновременно, то один из них начинает время от времени выдавать ошибки (читает на несколько байт меньше чем надо). Пробовал менять приоритеты, не помогает.
« Последнее редактирование: Июня 25, 2009, 01:47:07 pm от _oligarch » Записан
_oligarch
Участник
*
Offline Offline

Сообщений: 19


Просмотр профиля
« Ответ #9 : Июня 25, 2009, 01:45:39 pm »

может это драйвер уарта че касячит? может не справляется?
Записан
rw9uao
Участник
*
Offline Offline

Сообщений: 33


Просмотр профиля
« Ответ #10 : Июня 25, 2009, 02:59:05 pm »

может и не справляется. там с PDP прерываниями сделано. особо продвинутые берут BSP от 9263 и используют драйвер на поллинге.
Записан
_oligarch
Участник
*
Offline Offline

Сообщений: 19


Просмотр профиля
« Ответ #11 : Июня 25, 2009, 04:06:23 pm »

ого какой ужжас! ) а по другому никак не решить вопрос значит (
Записан
Страниц: [1]
  Печать  
 
Перейти в: