реклама на сайте
подробности

 
 
> задержка в отправке пакета из буфера uart, lpc2478 & uClinux
andybeg
сообщение Jul 1 2010, 05:11
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



странная картина наблюдается - из уарта делаем RS485, соответственно при посылке пакета в порт на конвертер 485го на одной ноге выставляю строб начала передачи
Цитата
stat = write( ttyfd, query, length );
setP01(0,24, 1);
delay(20);

но посмотрев по осцилографу вижу что delay отрабатывается ровно, а посылка гуляет на протяжении 200милисекунд от начала строба, но не случайно, а по какой то линейной зависимости. пробовал следить за U3LSR, но толи что не так делал, толи этот регистр тут не помошник

Сообщение отредактировал andybeg - Jul 1 2010, 05:12
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 16)
etoja
сообщение Jul 1 2010, 07:35
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 121
Регистрация: 14-01-05
Из: Москва
Пользователь №: 1 952



Линукс не является системой реального времени и вы наблюдаете его штатное поведение.
Для синхронизации в вашем случае надо править функцию putchar(), которая физически выдаёт байт в uart, и перекомпилировать ядро.
Go to the top of the page
 
+Quote Post
sasamy
сообщение Jul 1 2010, 08:25
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858



Цитата(etoja @ Jul 1 2010, 11:35) *
Для синхронизации в вашем случае надо править функцию putchar(), которая физически выдаёт байт в uart, и перекомпилировать ядро.


putchar все еще в userspace к тому же понятия не имеет - сколько байт в посылке, смысла править ее честно говоря не вижу. Нужно править драйвер uart - после передачи байта смотреть в прерывании есть ли новые данные в буфере для передачи и если нет переключаться на прием аналогично если там используется dma (я не знаком с этим soc) тогда все еще проще - там и так ясно сколько байт передается.

PS "putchar все еще в userspace" - это я к тому что задержки в linux гарантируют что время выдержки будет не меньше того что запрошено, поэтому никто не гарантирует что задержка может оказаться раз в 5 больше что может привести к потере данных которые подчиненное устройство за это время уже может начать передавать а мы все еще не переключились на прием.

Сообщение отредактировал sasamy - Jul 1 2010, 08:31
Go to the top of the page
 
+Quote Post
etoja
сообщение Jul 1 2010, 09:01
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 121
Регистрация: 14-01-05
Из: Москва
Пользователь №: 1 952



согласен
Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 1 2010, 12:20
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



Цитата
Нужно править драйвер uart - после передачи байта
понятно, носом не ткнёте где найти уарт драйвер? конечно предполагаю что в директории drivers
Go to the top of the page
 
+Quote Post
etoja
сообщение Jul 1 2010, 14:04
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 121
Регистрация: 14-01-05
Из: Москва
Пользователь №: 1 952



A driver for 8250/16550 compatible serial ports are integrated in the kernel source tree. That
driver is possible to use without modification for the LPC24xx. The source code is available
in the uClinux-dist/linux-2.6.x/drivers/serial/8250.c file.


Документ "Getting_started_with_uClinux_A.pdf" (4Мбайта) находится здесь: http://slil.ru/29418617

Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 1 2010, 14:31
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



спасибо, ценный документ smile.gif
Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 5 2010, 06:30
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



интересно, а флаг O_DIRECT для записи в порт в uClinux работает? компилятор ругается на него, хотя <fcntl.h> прописан

Сообщение отредактировал andybeg - Jul 5 2010, 06:35
Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 7 2010, 19:46
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



проблему не решил, но обуздал фронт посылки. сначала, посмотрел в сторону регистра U3LSR в итоге имеем - ставим строб отправки пакета, отправляем пакет данных и ждём пока этот регистр сообщит нам , что данные сначала поступили на отправку, а затем , что они ушли из буфера , затем ставим строб на приём ответа и слушаем ...
Цитата
int write_stat,fd;
unsigned char *U3LSR,data,res;
fd = open("/dev/mem", O_RDWR);
U3LSR = mmap(0, 0x100, PROT_READ, MAP_SHARED, fd, 0xE007C000);
if (U3LSR == MAP_FAILED)
{
printf("Error mmapping the file");
return 0;
}
#ifdef DEBUG
int i;
#endif
modbus_query( query, string_length );
string_length += 2;
#ifdef DEBUG
fprintf( stderr, "\n" );
for( i = 0; i < string_length; i++ )
{
fprintf( stderr, "[%0.2X]", query[ i ] );
} fprintf( stderr, "\n" );
#endif
tcflush( ttyfd, TCIOFLUSH );
setP01(1,13, 1);

write_stat = write( ttyfd, query, string_length );
data = 1; //ждём захода данных в буфер отправки
while(data) { data = *(U3LSR+0x14)&(1<<6); res = *(U3LSR+0x14); printf("\ndata =%x",res); }
printf("\n"); //ждём когда они покинут буфер
while(!data) { data = *(U3LSR+0x14)&(1<<6); res = *(U3LSR+0x14); printf("\nres =%x",res); }
printf("\n");
//delay(220);
setP01(1,13, 0); if (munmap(U3LSR, 0x100) == -1) { perror("Error un-mmapping the file");

} close(fd); return( write_stat );


завтра наверное надо будет добавить таймаутов, а в целом код рабочий, правда по большому счёту не устраивает и надо будет искать другое решение
Go to the top of the page
 
+Quote Post
etoja
сообщение Jul 8 2010, 07:00
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 121
Регистрация: 14-01-05
Из: Москва
Пользователь №: 1 952



Есть очевидное решение: запретить прерывания и работать напрямую с регистрами UARTa и регистрами ножки ввода-вывода.
Как уже говорилось, uCLinux это позволяет.
Тут уж либо реальное время, либо многозадачность.
Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 8 2010, 09:30
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



лучше время smile.gif будем копать
Go to the top of the page
 
+Quote Post
LeshaL
сообщение Jul 8 2010, 09:36
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 14-01-06
Пользователь №: 13 160



Цитата(andybeg @ Jul 8 2010, 15:30) *
лучше время smile.gif будем копать


Если что откопаете, пожалуйста сообщите, галерка тоже интересуется...
Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 8 2010, 10:38
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



откопаю, ибо деваться некуда, с понедельнка начну
Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 9 2010, 14:06
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



ооооо ееее нииигааа ... нашёл регистр для отправки посылки путём прямого доступа в память
Цитата
4.2 UARTn Transmit Holding Register (U0THR - 0xE000 C000, U2THR -
0xE007 8000, U3THR - 0xE007 C000 when DLAB = 0, Write Only)
The UnTHR is the top byte of the UARTn TX FIFO. The top byte is the newest character in
the TX FIFO and can be written via the bus interface. The LSB represents the first bit to
transmit.
The Divisor Latch Access Bit (DLAB) in UnLCR must be zero in order to access the
UnTHR. The UnTHR is always Write Only.
Table 379. UART0 Transmit Holding Register (U0THR - address 0xE000 C000,
U2THR - 0xE007 8000, U3THR - 0xE007 C000 when DLAB = 0, Write Only) bit
description
Bit Symbol Description Reset Value
7:0 THR Writing to the UARTn Transmit Holding Register causes the data NA
to be stored in the UARTn transmit FIFO. The byte will be sent
when it reaches the bottom of the FIFO and the transmitter is
available.


пишем функцию отсылки чара

Цитата
int putC(unsigned char ch)
{
int write_stat,fd;
unsigned char *map,data,res;

fd = open("/dev/mem", O_RDWR);
map = mmap(0, 0x100, PROT_READ, MAP_SHARED, fd, UnLCR_BASE_ADDR);
if (map == MAP_FAILED)
{
printf("Error mmapping the file");
return 0;
}

while(!(U0LCR && 0x20));

if (munmap(map, 0x100) == -1)
{
perror("Error un-mmapping the file");
}
close(fd);

fd = open("/dev/mem", O_RDWR);
map = mmap(0, 0x100, PROT_READ, MAP_SHARED, fd, UnTHR_BASE_ADDR);
if (map == MAP_FAILED)
{
printf("Error mmapping the file");
return 0;
}
U3THR = ch;
if (munmap(map, 0x100) == -1)
{
perror("Error un-mmapping the file");
}
close(fd);
return 0;
}


модернизируем отправку
Цитата
tcflush( ttyfd, TCIOFLUSH ); /* flush the input & output streams */
setP01(1,13, 1);

//write_stat = write( ttyfd, query, string_length );
for( i = 0; i < string_length; i++ )
putC(query[i]);

fd = open("/dev/mem", O_RDWR);
map = mmap(0, 0x100, PROT_READ, MAP_SHARED, fd, UnLCR_BASE_ADDR);
if (map == MAP_FAILED)
{
printf("Error mmapping the file");
return 0;
}

while(!(U0LCR && 0x20));

if (munmap(map, 0x100) == -1)
{
perror("Error un-mmapping the file");
}
close(fd);

printf("\n");


setP01(1,13, 0);

и получаем посылку почти чётко вписанную в строб, за качество кода прошу не ругать, ибо делал енто на коленях, по наитию и не успел ещё отредактировать, опять же почему то не получаю ответа от дочернего устройства где то есть косяк, вобщем объективная критика принимается
Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 9 2010, 17:58
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



насчёт дочернего устройства я ошибся - оно мою посылку принимает и отвечает, это я где то при приёме дал косяка, короче код рабочий, его только надо оптимизировать и сделать красивым
Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 12 2010, 12:40
Сообщение #16


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



возвращаясь к вопросу о подчинённом устройстве - модифицированная отправка работает исправно, устройство получает команду, реагирует соответствующе, но приём который работал раньше не отрабатывает
Цитата
fd_set rfds;

struct timeval tv;

tv.tv_sec = 1;
tv.tv_usec = 0;

FD_ZERO( &rfds );
FD_SET( ttyfd, &rfds );


#ifdef DEBUG
fprintf( stderr, "Waiting for response.\n");
#endif

/* wait for a response */
data_avail = select( FD_SETSIZE, &rfds, NULL, NULL, &tv );

if( !data_avail )
{
bytes_received = 0;
fprintf( stderr, "Comms time out\n" ); <---------- вылетает сюда
}
Go to the top of the page
 
+Quote Post
andybeg
сообщение Jul 16 2010, 06:29
Сообщение #17


Частый гость
**

Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954



товарищ столкнулся с сабжевой проблемой, покопался в драйвере компорта и нашёл неплохое решение - в коде в 8250.с есть строчки:
Цитата
mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout) + HZ/5);
и
poll_timeout(up->port.timeout) + HZ/5);


я моём случае меняем на

Цитата
mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout) + HZ/200);
и
poll_timeout(up->port.timeout) + HZ/200);

и получаем строб в 20 мс, который накрывает посылку длящуюся 9-10мс, с такими показателями можно жить.
товарищ поставил отключение строба прямо в драйвере ... я пока что отключаю после отправки write
Цитата
fd = open("/dev/mem", O_RDWR);
map = mmap(0, getpagesize(), PROT_READ, MAP_SHARED, fd, UnLSR_BASE_ADDR);
if (map == MAP_FAILED)
{
#ifdef DEBUG
printf("Error mmapping the file");
setP01(1,13, 0);
#endif
return 0;
}
data = 1;

//ждём когда в отправляющем буфере появятся данные
goal = 10 * CLOCKS_PER_SEC / 1000 + clock();
while(data)
{
data = (U3LSR)&(1<<6);
res = (U3LSR);
#ifdef DEBUG
printf("\ndata =%x",res);
#endif
if(goal < clock())
{
#ifdef DEBUG
printf("outbuf timeout");
#endif
setP01(1,13, 0);
return 1;
}
}
//------------------------------------------------
#ifdef DEBUG
printf("\n");
#endif
//ждём когда из отправляющего буфера данные уйдут
goal = 10 * CLOCKS_PER_SEC / 1000 + clock();
while(!data)
{
data = (U3LSR)&(1<<6);
res = (U3LSR);
#ifdef DEBUG
printf("\nres =%x",res);
#endif
if(goal < clock())
{
#ifdef DEBUG
printf("sendbuf timeout");
#endif
setP01(1,13, 0);
return 1;
}
}
setP01(1,13, 0);
//------------------------------------------------
if (munmap(map, getpagesize()) == -1)
{
#ifdef DEBUG
perror("Error un-mmapping the file");
#endif
}
close(fd);


Сообщение отредактировал andybeg - Jul 16 2010, 06:35
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 12th August 2025 - 03:19
Рейтинг@Mail.ru


Страница сгенерированна за 0.01513 секунд с 7
ELECTRONIX ©2004-2016