LINUX.ORG.RU

BeagleBone interrupts

 


0

1

Подскажите пожалуйста, стоит следующая задача. Имеется процессорный модуль BeagleBone Bkack, на нем Debian (версия ядра 3.8). Требуется написать приложение на с, с++, которое при возникновении прерывания (пришли данные на uart) выполняет определенные действия (чтение данных). Насколько я понял, для этого требуется библиотека interrupt.h. (опрос состояния регистра в цикле не подходит, низкая надежность и скорость метода). Данной библиотеки, как я понял, в стандартных библиотеках си линукс нет, однако, в linux headers есть linux/interrupt.h, для работы с которой требуется писать модуль ядра. Если писать модуль ядра, не получится использовать стандартные библиотеки. Вопрос, можно ли решить задачу без написания модулей ядра, и если нет, то подскажите пожалуйста, где искать аналоги обычных библиотек для модулей ядра, и возможно ли их найти.

если у тебя там дебиан (версия ядра 3.8), то почему бы просто не написать приложение на с, с++, которое будет open(«/dev/ttyS0»), потом select и read когда там данные появятся?

Зачем сразу речь о каких-то прерываниях?

aol ★★★★★ ()
Ответ на: комментарий от aol

Благодарю за ответ! open и read использовал, а про функцию select просто не знал. Сейчас почитал про нее, насколько понял, в данном случае её можно настроить, что бы она заданное время ожидала изменение файла «/dev/ttyS0». Тогда возникает вопрос, не будет ли такой вариант значительно уступать по скорости аналогичной программе, основанной на прерываниях (не знаю как устроена функция внутри, возможно тем же самыфм опросом)? Для меня это очень важный вопрос.

Aleksis_92 ()
Ответ на: комментарий от deterok

на вкус и цвет все фломастеры разные ;)

aol ★★★★★ ()
Ответ на: комментарий от Aleksis_92

не будет ли такой вариант значительно уступать по скорости аналогичной программе, основанной на прерываниях

если для тебя это очень важный вопрос, снеси дебиан и пиши bare metal.

во всех остальных случаях всё будет хорошо :)

aol ★★★★★ ()
Ответ на: комментарий от deterok

Подскажите пожалуйста, нашел в интернете следующий код

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <stdlib.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/epoll.h>
 
#define BAUD B4800
#define PORT "/dev/ttyS0"
#define DATABITS CS8
#define STOPBITS 0 /* 1 - 0 | 2 - CSTOPB */
 
/*
 * //none
 * PARITYON = 0;
 * PARITY = 0;
 * //odd
 * PARITYON = PARENB;
 * PARITY = PARODD;
 * //even
 * PARITYON = PARENB;
 * PARITY = 0;
 */
#define PARITYON PARENB
#define PARITY 0
 
#define MAX_EVENTS 10
 
/* 24ms */
#define TIMEOUT 24 
 
#define BUFF_SIZE 1024
 
void com_port_on_read(int fd, char *buf, int size) {
    int i;
    for (i = 0; i < size; ++i) {
        char ch = ((unsigned char)buf[i] > 3 ? 0 : 1);
        /* шлём 0 если принятое число больше 3 иначе шлём 1 */
        write(fd, &ch, 1);
        printf("%02X ", (unsigned int)buf[i]);
    }
    printf("\n");
}
 
int main(int argc, char *argv[])
{
    int fd, epollfd, run;
    struct epoll_event event, events[MAX_EVENTS];
    /* place for old and new port settings for serial port */
    struct termios oldtio, newtio;
    /* open the device(com port) to be non-blocking (read will return immediately) */
    fd = open(PORT, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
    if (fd == -1)
    {
         perror("open("PORT")");
         exit(EXIT_FAILURE);
    } else
        fcntl(fd, F_SETFL, 0);
 
    /* save current port settings */
    tcgetattr(fd, &oldtio);
    /* set new port settings for canonical input processing */
    /* Control options */
    newtio.c_cflag = BAUD | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
    /* Input options */
    newtio.c_iflag = IGNPAR;
    /* Output options */
    newtio.c_oflag = 0;
    /* Line options */
    newtio.c_lflag = 0; /*ICANON*/
    newtio.c_cc[VMIN] = 0;
    newtio.c_cc[VTIME] = 0;
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &newtio);
 
    epollfd = epoll_create(1);
    event.data.fd = fd;
    event.events = EPOLLIN;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
 
    run = 1;
    while (run) {
        int n;
        int nfds = epoll_wait(epollfd, events, MAX_EVENTS, TIMEOUT);
        if (nfds == -1) {
            if (errno == EINTR)
                continue;
            perror("epoll_wait()");
            break;
        }
 
        if (nfds == 0) {
            /* TIMEOUT!!! */
            /* Здесь может например наглядно отрисовываться взрыв завода */
            printf("timeout\n");
            continue;
        }
        for (n = 0; n < nfds; ++n) {
            if (events[n].events & EPOLLIN) {
                char buf[BUFF_SIZE];
                int bytes = read(events[n].data.fd, buf, BUFF_SIZE);
                if (bytes <= 0) {
                    perror("read()");
                    run = 0;
                    break;
                }
                com_port_on_read(events[n].data.fd, buf, bytes);
            }
        }
    }
    /* restore old port settings */
    tcsetattr(fd,TCSANOW,&oldtio);
    /* close the com port */
    close(fd);
    /* close epoll discriptor */
    close(epollfd);
 
    return (EXIT_SUCCESS);
}


Вписал своё имя устройства, скорость и тд, остальное пока не 
изменял. На компьютере все работает замечательно, на 
Beaglebone тоже, однако, во втором случае хавает порядка 80%
 загрузки ЦПУ (проверял командой top), и если я занимаю 
процессор чем либо другим, то просто принимает количество 
байт меньше пропорционально свободным ресурсам компьютера,
 при то что посылаю ему всегда одно и тоже (для проверки 
просто посылаю по uart байт максимум сколько посылается в 
цикле с малой задержкой, получается порядка 70300 
информативных бит/с реально при выставленной скорости 115200 
(цифру смотрел с BeagleBone, так что если предположить что он 
немного теряет, то может чуть больше). Получается большое 
количество информации просто теряется. Работает UART на 
скоросто 115200. Подскажите, дело в коде, или в процессорном 
модуле?

Думал сначала что надо повысить частоту процессора (стандарт 
300 МГц, исправил на 1 ГГц), однако, что меня сильно 
удивило.ю не поменялось решительно ничего. Изменял частоту 
путем записи в /sys/devices/system/cpu/cpu0/cpufreq
/scaling_governors "perfomance", т.е. меняя режим работы 
процессора. Далее при чтении cpu_cur_freq значение менялось 
на 1000000, из чего сделал вывод что частота сменилась 
успешно.
Aleksis_92 ()
Ответ на: комментарий от anonymous

А что, если я скажу что это нихрена не поможет? Нет, нагрузка на проц конечно упадет, вот только количество принимаемых данных тоже. А если делать слип малой, который не повлияет на количество принимаемых данных - от него и толку близко к нулю, ну не 80 а 78% нагрузка

Aleksis_92 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.