|
задержка в отправке пакета из буфера uart, lpc2478 & uClinux |
|
|
|
Jul 1 2010, 05:11
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 16)
|
Jul 1 2010, 08:25
|
Знающий
   
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jul 1 2010, 12:20
|
Частый гость
 
Группа: Участник
Сообщений: 133
Регистрация: 30-11-06
Пользователь №: 22 954

|
Цитата Нужно править драйвер uart - после передачи байта понятно, носом не ткнёте где найти уарт драйвер? конечно предполагаю что в директории drivers
|
|
|
|
|
Jul 7 2010, 19:46
|
Частый гость
 
Группа: Участник
Сообщений: 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 ); завтра наверное надо будет добавить таймаутов, а в целом код рабочий, правда по большому счёту не устраивает и надо будет искать другое решение
|
|
|
|
|
Jul 8 2010, 09:36
|
Частый гость
 
Группа: Свой
Сообщений: 166
Регистрация: 14-01-06
Пользователь №: 13 160

|
Цитата(andybeg @ Jul 8 2010, 15:30)  лучше время  будем копать Если что откопаете, пожалуйста сообщите, галерка тоже интересуется...
|
|
|
|
|
Jul 9 2010, 14:06
|
Частый гость
 
Группа: Участник
Сообщений: 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); и получаем посылку почти чётко вписанную в строб, за качество кода прошу не ругать, ибо делал енто на коленях, по наитию и не успел ещё отредактировать, опять же почему то не получаю ответа от дочернего устройства где то есть косяк, вобщем объективная критика принимается
|
|
|
|
|
Jul 12 2010, 12:40
|
Частый гость
 
Группа: Участник
Сообщений: 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" ); <---------- вылетает сюда }
|
|
|
|
|
Jul 16 2010, 06:29
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|