Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как отследить КЗ на шине CAN ?  (Прочитано 18411 раз)
0 Пользователей и 1 Гость смотрят эту тему.
demon051
Помогающий

ru
Offline Offline

« : 29-12-2018 07:10 » 

Всем привет! Всех с НГ.

Вопросик такой.
Есть код обмена по шине CAN.

Код:
while(!stop)
    {
        try
        {
            if(ss[0]!=-1)
            {
                try
                {
                    close(ss[0]);
                }
                catch(...){}
                ss[0] = -1;
            }
            if(pthread_mutex_trylock(&can_data->mutex_lock)==0)
            {
                stop = can_data->stopThread;
                pthread_mutex_unlock(&can_data->mutex_lock);
                if(stop)
                    break;
            }
            if((ss[0] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
            {
                generateSignal(signoCan1Red);
                if(can_data->eventHandler!=0)
                    can_data->eventHandler->onCanStart(socketError::socket_create_error);
                nanosleep(&sp, NULL);
                continue;
            }

            if(fcntl(ss[0], F_SETFL, SOCK_NONBLOCK)<0)
            {
                generateSignal(signoCan1Red);
                if(can_data->eventHandler!=0)
                    can_data->eventHandler->onCanStart(socketError::socket_setnonblock_error);
                nanosleep(&sp, NULL);
                continue;
            }

           strcpy(ifr.ifr_name, can_data->name.data());

            ioctl(ss[0], SIOCGIFINDEX, &ifr);

            addr.can_family  = AF_CAN;
            addr.can_ifindex = ifr.ifr_ifindex;

            if(bind(ss[0], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
                generateSignal(signoCan1Red);
                if(can_data->eventHandler!=0)
                    can_data->eventHandler->onCanStart(socketError::socket_bind_error);
                nanosleep(&sp, NULL);
                continue;
            }

        }
        catch(...)
        {
            generateSignal(signoCan1Red);
            if(can_data->eventHandler!=0)
                can_data->eventHandler->canOperationError(socketError::socket_unknown_error);
            continue;
        }

        if(can_data->eventHandler!=0)
            can_data->eventHandler->onCanStart();

        while(!stop)
        {
            try
            {
                if(pthread_mutex_trylock(&can_data->mutex_lock)==0)
                {
                    stop = can_data->stopThread;
                    pthread_mutex_unlock(&can_data->mutex_lock);
                    if(stop)
                        break;
                }

                FD_ZERO(&read_fs);
                FD_SET(ss[0], &read_fs);

                FD_ZERO(&write_fs);
                FD_SET(ss[0], &write_fs);

                FD_ZERO(&error_fs);
                FD_SET(ss[0], &error_fs);

                if ((ret = select(ss[0]+1, &read_fs, &write_fs, &error_fs, &timeout_config)) <= 0)
                {
                    continue;
                }

                if (FD_ISSET(ss[0], &read_fs))//проверяем дескриптор на готовность к чтению
                {
                    frame_read = new can_frame;
                    frame_read->can_id = 0;
                    frame_read->can_dlc = 0;
                    auto numBytes = read(ss[0], frame_read, CAN_MTU);
                    if(numBytes>0)
                    {
                      if(can_data->eventHandler!=0)
                          can_data->eventHandler->newCanFrame(frame_read);
                      continue;
                    }
                }

                if (!can_data->queueIn.isEmpty() && FD_ISSET(ss[0], &write_fs))//проверяем дескриптор на готовность к записи
                {
                    frame_write = can_data->queueIn.dequeue();
                    if(frame_write != 0)
                    {
                        auto numBytes = sendto(ss[0], frame_write, sizeof(struct can_frame),
                                               0, (struct sockaddr*)&addr, sizeof(addr));

                        delete frame_write;
                        frame_write = 0;
                        if(numBytes == 0)
                        {
                            generateSignal(signoCan1Red);
                            if(can_data->eventHandler!=0)
                                can_data->eventHandler->canOperationError(socketError::socket_write_error);
                            break;
                        }
                        else
                        {
                            generateSignal(signoCan1GreenPulse);
                            continue;
                        }
                    }
                }

                if (FD_ISSET(ss[0], &error_fs))//проверяем дескриптор на наличие ошибок
                {
                    generateSignal(signoCan1Red);
                    if(can_data->eventHandler!=0)
                        can_data->eventHandler->canOperationError(socketError::socket_error);
                    break;
                }

            }
            catch(...)
            {
                generateSignal(signoCan1Red);
                if(can_data->eventHandler!=0)
                    can_data->eventHandler->canOperationError(socketError::socket_unknown_error);
                break;
            }
        }
        if(ss[0]!=-1)
        {
            try
            {
                close(ss[0]);
            }
            catch(...){generateSignal(signoCan1Red);}
            ss[0] = -1;
        }
    }

Всё это работает.
Но не получается отследить ситуацию КЗ на шине. Т.е. замыкаем, а никаких ошибок и исключений не вылазит...
Выскочить из внутреннего цикла во внешний не получается.
Кто-нить знает, должна ли вылезать ошибка в if (FD_ISSET(ss[0], &error_fs)) ?
Понятно что можно накрутить проверку что если какое-то колво раз не выбран ни один дескриптор, то это значит, что что-то не в порядке. Но это частная ситуация, когда ты уверен что обмен идет не прерываясь и запросы по кан гуляют постоянно. А если кан тупо простаивает без регулярного обмена, то как отмониторить КЗ?
« Последнее редактирование: 29-12-2018 07:15 от demon051 » Записан
darkelf
Молодой специалист

no
Offline Offline

« Ответ #1 : 29-12-2018 07:42 » 

К сожалению с CAN дела иметь не приходилось, так-что это будут скорее предположения. Здесь пишут, что необходимо включить соответствующий фильтр и в этом случае Вашей прикладной задаче будут доставляться специализированные сообщения, называемые CAN error message frame. Формат их приведён в include/uapi/linux/can/error.h. Задать фильтр можно через setsockopt():
Код: (C)
can_err_mask_t err_mask = ( CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF );

setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask))
Записан
demon051
Помогающий

ru
Offline Offline

« Ответ #2 : 29-12-2018 07:44 » new

К сожалению с CAN дела иметь не приходилось, так-что это будут скорее предположения. Здесь пишут, что необходимо включить соответствующий фильтр и в этом случае Вашей прикладной задаче будут доставляться специализированные сообщения, называемые CAN error message frame. Формат их приведён в include/uapi/linux/can/error.h. Задать фильтр можно через setsockopt():
Код: (C)
can_err_mask_t err_mask = ( CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF );

setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask))

спасибо. буду изучать.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines