Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Большое число программных прерываний в ОС Linux при приеме информации по интерфейсу CAN на AM3517
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > Linux
Таратухин Сергей
На AM3517 при получении информации через интерфейс CAN (скорость передачи данных 1 Мбит/с шина CAN загружена около 80%) в ОС Linux генерируется много программных прерываний (около 45% загрузки процессора). Можно ли уменьшить количество программных прерываний при приеме?
kurtis
У вас случайно прерывания не по gpio идут? Если по gpio, то по фронту или по уровню?
Tarbal
Цитата(Таратухин Сергей @ Sep 18 2013, 13:49) *
На AM3517 при получении информации через интерфейс CAN (скорость передачи данных 1 Мбит/с шина CAN загружена около 80%) в ОС Linux генерируется много программных прерываний (около 45% загрузки процессора). Можно ли уменьшить количество программных прерываний при приеме?


Уточните насчет программных прерываний. Может все-таки это реальные прерывания вызванные железом?

Если так, то число прерываний должно совпадать с числом принятых сообщений, переданых сообщений и еще какой-нибудь байды, которая разрешена. В контроллере CAN должен быть регистр маски прерывания. Вам следует разрешить в нем только прерывания относящиеся к делу. С передачей сообщений бывает следующая проблема. Флаг прерывания установлен всегда, пока буфер передатчика пуст. Иногда бывает флаг, что гасится тем или иным способом и не восстанавливается до следующей передачи. В устройстве могут присутствовать оба механизма. В первом случае необходимо маскировать прерывание передатчика в обработчике и разрешать, когда есть что передать.
_3m
Цитата(Tarbal @ Sep 18 2013, 21:00) *
Уточните насчет программных прерываний. Может все-таки это реальные прерывания вызванные железом?
Если так, то число прерываний должно совпадать с числом принятых сообщений, переданых сообщений и еще какой-нибудь байды, которая разрешена.

Я посмотрел драйвер TI тот что в mainline. Там обработка приема делается поллингом так что количество хардверных прерываний от кан интерфейса будет меньше либо равно количеству принятых пакетов.
С подтверждением прерываний может быть проблема это есть смысл проверить.
Также не исключено что высокая загрузка это норма для скорости 1М. Ядро обрабатывает принятые пакеты софтверно. Какой софт у вас получает пакеты ?
Tarbal
Положим одна транзакция 100 бит. Значит при 80% загрузке в секунду приходит 8000 сообщений. А сколько у вас прерываний случается?
Таратухин Сергей
Цитата(_3m @ Sep 19 2013, 01:24) *
Я посмотрел драйвер TI тот что в mainline. Там обработка приема делается поллингом так что количество хардверных прерываний от кан интерфейса будет меньше либо равно количеству принятых пакетов.
С подтверждением прерываний может быть проблема это есть смысл проверить.
Также не исключено что высокая загрузка это норма для скорости 1М. Ядро обрабатывает принятые пакеты софтверно. Какой софт у вас получает пакеты ?


Чтобы проверить прием была написана технологическая программа. Она ни чего не выводит, просто читает из сокета пакеты CAN в фоновом режиме и увеличивает счетчик принятых пракетов (по шине CAN непрерывно передается информация). Загрузку смотрю утилитой top. Так же привожу кол-во прерываний, кол-во принятых пакетов и размер принятых данных (cat /proc/interrupts ; ifconfig).

CODE
Mem: 32336K used, 204116K free, 0K shrd, 1568K buff, 6260K cached
CPU: 0% usr 21% sys 0% nic 35% idle 0% io 0% irq 42% sirq
Load average: 0.03 0.04 0.05 1/58 1009
PID PPID USER STAT VSZ %MEM %CPU COMMAND
1008 951 root R 1472 1% 44% ./a.out
622 2 root SW 0 0% 6% [kworker/0:2]
644 2 root SW 0 0% 1% [ksdioirqd/mmc1]
1009 951 root R 2844 1% 1% top
45 2 root SW 0 0% 0% [irq/74-serial i]
951 949 root S 2844 1% 0% -sh
924 1 root S 2732 1% 0% /sbin/syslogd -n -C64 -m 20
926 1 root S 2668 1% 0% /sbin/klogd -n
917 1 root S 2668 1% 0% /usr/sbin/telnetd
912 1 messageb S 2436 1% 0% /usr/bin/dbus-daemon --system
949 1 root S 2400 1% 0% login -- root
692 1 root S < 2188 1% 0% /sbin/udevd -d
726 692 root S < 2184 1% 0% /sbin/udevd -d
727 692 root S < 2184 1% 0% /sbin/udevd -d
933 1 root S 2064 1% 0% /usr/sbin/thttpd -d /srv/www -p 8080 -
1 0 root S 1628 1% 0% init [5]
588 2 root SW 0 0% 0% [w1_bus_master1]
5 2 root SW 0 0% 0% [kworker/u:0]
633 2 root SW 0 0% 0% [mmcqd/0]
3 2 root SW 0 0% 0% [ksoftirqd/0]


CODE
root@am3517-evm:~# cat /proc/interrupts ; ifconfig
CPU0
11: 0 INTC prcm
12: 1873 INTC DMA
20: 0 INTC gpmc
24: 12114477 INTC can0
25: 2 INTC OMAP DSS
37: 454780 INTC gp timer
56: 1874385 INTC omap_i2c
57: 0 INTC omap_i2c
58: 84972 INTC omap_hdq
61: 0 INTC omap_i2c
71: 1 INTC musb-hdrc.0
72: 0 INTC serial idle
73: 0 INTC serial idle
74: 22509 INTC serial idle, OMAP UART2
77: 0 INTC ehci_hcd:usb2
83: 2765 INTC mmc0
86: 286560 INTC mmc1
160: 0 GPIO tps6507x
162: 1 GPIO mmc1
184: 0 GPIO ds1374
186: 0 GPIO tca8418-keypad
224: 0 GPIO mmc0
Err: 0

can0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:16 Metric:1
RX packets:12732263 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10
RX bytes:88788609 (84.6 MiB) TX bytes:0 (0.0 B)
Interrupt:24


CODE
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/socket.h>
4 #include <sys/ioctl.h>
5 #include <net/if.h>
6
7 #include <linux/can.h>
8 #include <linux/can/raw.h>
9 #include <string.h>
10
11 /* At time of writing, these constants are not defined in the headers */
12 #ifndef PF_CAN
13 #define PF_CAN 29
14 #endif
15
16 #ifndef AF_CAN
17 #define AF_CAN PF_CAN
18 #endif
19
20 int main(int argc, char *argv[])
21 {
22 /* create a frame */
23 struct can_frame frame;
24 /* interface */
25 struct ifreq ifr;
26 /* number of te */
27 int bytes_read;
28 /* create the socket */
29 int skt = socket( PF_CAN, SOCK_RAW, CAN_RAW );
30 /* socket address */
31 struct sockaddr_can addr;
32 /* counter SFF */
33 unsigned long countSFF;
34 /* counter EFF*/
35 unsigned long countEFF;
36
37 countSFF = 0;
38 countEFF = 0;
39 /* locate the interface you wish to use */
40 strcpy( ifr.ifr_name, "can0" );
41 ioctl( skt, SIOCGIFINDEX, &ifr ); /* ifr.ifr_ifindex gets filled with that device's index */
42 /* select that CAN interface, and bind the socket to it. */
43 addr.can_family = AF_CAN;
44 addr.can_ifindex = ifr.ifr_ifindex;
45 bind( skt, ( struct sockaddr * ) &addr, sizeof( addr ) );
46 while(1)
47 {
48 bytes_read = read( skt, &frame, sizeof( frame ) );
49 if( bytes_read < 0 )
50 {
51 printf( "CAN\n" );
52 }
53 else if ( bytes_read > 0 )
54 {
55 if( !( frame.can_id & 0x80000000U ) )
56 {
57 countSFF++;
58 }
59 else
60 {
61 countEFF++;
62 }
63 }
64 }
65
66 return 0;
67 }


Цитата(kurtis @ Sep 18 2013, 18:45) *
У вас случайно прерывания не по gpio идут? Если по gpio, то по фронту или по уровню?


Прерывания CAN осуществляется не по GPIO (фрагмент из команды "cat /proc/interrupts" 24: 12114477 INTC can0).

Цитата(Tarbal @ Sep 19 2013, 07:13) *
Положим одна транзакция 100 бит. Значит при 80% загрузке в секунду приходит 8000 сообщений. А сколько у вас прерываний случается?


Из "cat /proc/interrupts" следует, что за несколько минут, при загрузки шины CAN примерно 80% количество прерываний 12114477.
_3m
Цитата(Таратухин Сергей @ Sep 19 2013, 09:54) *
Чтобы проверить прием была написана технологическая программа. Она ни чего не выводит, просто читает из сокета пакеты CAN в фоновом режиме и увеличивает счетчик принятых пракетов
...

Пока не вижу криминала. По вашим данным
12114477 INTC can0
12732263 RX packets
У вас 0,95 прерывания на пакет. Абсолютное большинство пакетов система успевает забрать и обработать до прихода следующего.
Возможно это нормальная работа socketcan. Там довольно накручено поэтому еще живы альтернативные решения, например lincan.
Вот бенчмарки
CAN driver benchmark
В бенчмарке есть хорошая идея - тестировать socketcan при одновременной нагрузке ethernet.

Цитата(Tarbal @ Sep 19 2013, 05:13) *
Положим одна транзакция 100 бит. Значит при 80% загрузке в секунду приходит 8000 сообщений. А сколько у вас прерываний случается?

По моим расчетам (я мог ошибиться) для скорости 1М максимальный темп передачи пакетов CAN при 100% загрузке шины и длине данных 8 бит составляет 63 и 81мкс для стандартных и расширенных пакетов соответственно что дает 15873 и 12345 пакетов в секунду.
У ТС загрузка шины 80% значит пакеты поступают каждые 79мкс.
Tarbal
Цитата(_3m @ Sep 19 2013, 11:16) *
Пока не вижу криминала. По вашим данным
12114477 INTC can0
12732263 RX packets
У вас 0,95 прерывания на пакет. Абсолютное большинство пакетов система успевает забрать и обработать до прихода следующего.
Возможно это нормальная работа socketcan. Там довольно накручено поэтому еще живы альтернативные решения, например lincan.
Вот бенчмарки
CAN driver benchmark
В бенчмарке есть хорошая идея - тестировать socketcan при одновременной нагрузке ethernet.


По моим расчетам (я мог ошибиться) для скорости 1М максимальный темп передачи пакетов CAN при 100% загрузке шины и длине данных 8 бит составляет 63 и 81мкс для стандартных и расширенных пакетов соответственно что дает 15873 и 12345 пакетов в секунду.
У ТС загрузка шины 80% значит пакеты поступают каждые 79мкс.

Ваши рассчеты точнее моих. Я просто оценил порядок величины. Похоже система работает правильно. На каждый принятый пакет прерывание. Просто пакетов много.
Таратухин Сергей
Цитата(Tarbal @ Sep 19 2013, 19:19) *
Ваши рассчеты точнее моих. Я просто оценил порядок величины. Похоже система работает правильно. На каждый принятый пакет прерывание. Просто пакетов много.



Проанализировал ситуацию (после прочтения предложений участников) и посмотрел в интернете насчет LinCAN наткнулся на одну интересную статью
CAN driver benchmark
В итоге пришел к выводу, что эта проблема драйвера и механизма доступа к нему, который реализовали сотрудники TI. Так что AM3517 с драйвером CAN от TI не обеспечивает низкую загрузку центрального процессора при приеме CAN пакетов сильно загруженной шины CAN. Буду уменьшать загрузку шины CAN, чтобы уменьшить нагрузку на центральный процессор при приеме. Всем спасибо за помощь.
sasamy
Цитата(Таратухин Сергей @ Sep 20 2013, 13:13) *
наткнулся на одну интересную статью
CAN driver benchmark


В статье описан типичный поллинг - ISR отрабатывает первый пакет а остальные (если они есть) отрабатываются в контексте soft irq (bottom half) или обычного процесса проверкой бита готовности данных. Для ethernet в ядре есть готовый механизм - NAPI. В общем техника широко применяемая.
A. Fig Lee
Цитата(Таратухин Сергей @ Sep 18 2013, 05:49) *
На AM3517 при получении информации через интерфейс CAN (скорость передачи данных 1 Мбит/с шина CAN загружена около 80%) в ОС Linux генерируется много программных прерываний (около 45% загрузки процессора). Можно ли уменьшить количество программных прерываний при приеме?

Не знаю везде ли, но у СТМ и майкрочипа фильтр стоит на ИД, принимает только те, которые нужно
Таратухин Сергей
Цитата(sasamy @ Sep 20 2013, 16:42) *
В статье описан типичный поллинг - ISR отрабатывает первый пакет а остальные (если они есть) отрабатываются в контексте soft irq (bottom half) или обычного процесса проверкой бита готовности данных. Для ethernet в ядре есть готовый механизм - NAPI. В общем техника широко применяемая.


Про методику читал (NAPI), но как им пользоваться не знаю (найти примеры не получилось). Если есть возможность рассказать про этот механизм подробнее буду очень благодарен.

Цитата(A. Fig Lee @ Sep 20 2013, 18:11) *
Не знаю везде ли, но у СТМ и майкрочипа фильтр стоит на ИД, принимает только те, которые нужно


Фильтровать на аппаратном уровне могу (необходимо принимать примерно 15% от максимальной загрузки шины, при этом нагрузка центрального процессора действительно маленькая порядка 4-7%), но есть ситуации когда необходимо будет принять большой объем пакетов (примерно 80% загрузки шины).
Tarbal
Цитата(Таратухин Сергей @ Sep 20 2013, 13:13) *
Проанализировал ситуацию (после прочтения предложений участников) и посмотрел в интернете насчет LinCAN наткнулся на одну интересную статью
CAN driver benchmark
В итоге пришел к выводу, что эта проблема драйвера и механизма доступа к нему, который реализовали сотрудники TI. Так что AM3517 с драйвером CAN от TI не обеспечивает низкую загрузку центрального процессора при приеме CAN пакетов сильно загруженной шины CAN. Буду уменьшать загрузку шины CAN, чтобы уменьшить нагрузку на центральный процессор при приеме. Всем спасибо за помощь.


У любого устройства есть свои пределы. CAN довольно неудобно обрабатывать на Линуксе. Она довольно неоднородна (имею ввиду сложность сообщений) и на каждое сообщение может требоваться индивидуальная реакция. Поэтому классический подход разгрузки прерываний в Линусе -- ПДП применить непросто, а может и невозможно.

Я уверен что процессор без ОС или с какой-нибудь реал-тайм ОС покажет лучшие результаты чем Линукс. Дело в том, что в Линуксе плата за универсальность долгий вход в обработчик прерывания.

Если вам будет интересно сделать CAN на другом процессоре, я лет 10 назад писал драйверы для RTOS SALVO на микрочипе. Причем там есть как с внутренним контроллером так и с подключенным как в статье по SPI. Mогу дать код.

Прерывание тупо кладет (если нет ошибок) в очередь, а тред уже забирает оттуда и обрабатывает. Система быстро выходит из прерывания, а значит имет лучше динамические характеристики.
sasamy
Цитата(Таратухин Сергей @ Sep 20 2013, 16:23) *
Про методику читал (NAPI), но как им пользоваться не знаю (найти примеры не получилось). Если есть возможность рассказать про этот механизм подробнее буду очень благодарен.


Посмотрите как сделано у Freescale для flexcan
http://lxr.free-electrons.com/source/drive.../flexcan.c#L564
sasamy
Цитата(sasamy @ Sep 20 2013, 16:55) *
Посмотрите как сделано у Freescale для flexcan


Кстати - в ванильном ядре и HECC NAPI поддерживает
http://lxr.free-electrons.com/source/drive.../ti_hecc.c#L604

насколько я понял
http://processors.wiki.ti.com/index.php/Si...29_Linux_Driver

у вас на процессоре такой контроллер используется.

PS я пропустил сообщение _3m
http://electronix.ru/forum/index.php?showt...t&p=1194005
он вам об этом уже говорил
Таратухин Сергей
Цитата(Tarbal @ Sep 20 2013, 18:30) *
У любого устройства есть свои пределы. CAN довольно неудобно обрабатывать на Линуксе. Она довольно неоднородна (имею ввиду сложность сообщений) и на каждое сообщение может требоваться индивидуальная реакция. Поэтому классический подход разгрузки прерываний в Линусе -- ПДП применить непросто, а может и невозможно.

Я уверен что процессор без ОС или с какой-нибудь реал-тайм ОС покажет лучшие результаты чем Линукс. Дело в том, что в Линуксе плата за универсальность долгий вход в обработчик прерывания.

Если вам будет интересно сделать CAN на другом процессоре, я лет 10 назад писал драйверы для RTOS SALVO на микрочипе. Причем там есть как с внутренним контроллером так и с подключенным как в статье по SPI. Mогу дать код.

Прерывание тупо кладет (если нет ошибок) в очередь, а тред уже забирает оттуда и обрабатывает. Система быстро выходит из прерывания, а значит имет лучше динамические характеристики.



Сейчас поставлена задача реализовать все под Linux, к тамуже там еще будет графическое приложение на Qt. Да к томуже сейчас мне работодатель не даст возможности эксперементировать с другими операционными системами, в целом интересно, но пока нет времени рассматривать это направление, а вот на исходники интересно будет посмотреть.
Tarbal
Цитата(Таратухин Сергей @ Sep 21 2013, 19:53) *
Сейчас поставлена задача реализовать все под Linux, к тамуже там еще будет графическое приложение на Qt. Да к томуже сейчас мне работодатель не даст возможности эксперементировать с другими операционными системами, в целом интересно, но пока нет времени рассматривать это направление, а вот на исходники интересно будет посмотреть.


Ну тогда я вижу только один способ уменьшить нагрузку. Сделать меньше сообщений.
Не знаю насколько это приемлимо. Дайте ваш емайл адрес в приватном сообщении и я пошлю вам примеры кода драйвера.
AndrewN
QUOTE (sasamy @ Sep 20 2013, 18:30) *
Кстати - в ванильном ядре и HECC NAPI поддерживает
http://lxr.free-electrons.com/source/drive.../ti_hecc.c#L604
Ну и жуткий же акцент в комментариях, страх божий... Не зря весельчаки так странно контроллер назвали, от комментариев так и хочется спросить "what the heck?!"... :)))
Таратухин Сергей
Цитата(sasamy @ Sep 20 2013, 20:30) *
Кстати - в ванильном ядре и HECC NAPI поддерживает
http://lxr.free-electrons.com/source/drive.../ti_hecc.c#L604

насколько я понял
http://processors.wiki.ti.com/index.php/Si...29_Linux_Driver

у вас на процессоре такой контроллер используется.

PS я пропустил сообщение _3m
http://electronix.ru/forum/index.php?showt...t&p=1194005
он вам об этом уже говорил


Все верно, но как задействовать NAPI?
Таратухин Сергей
Цитата(Tarbal @ Sep 21 2013, 22:39) *
Ну тогда я вижу только один способ уменьшить нагрузку. Сделать меньше сообщений.
Не знаю насколько это приемлимо. Дайте ваш емайл адрес в приватном сообщении и я пошлю вам примеры кода драйвера.


Мне форум не дает послать вам сообщение.
Tarbal
Цитата(Таратухин Сергей @ Sep 23 2013, 15:54) *
Мне форум не дает послать вам сообщение.




Я попробовал послать вам, но получил такую ошибку:

"Обнаружены следующие ошибки
Невозможно отправить это сообщение, так как получатель отключил свой личный ящик, или он попросту переполнен.

Это личное сообщение не отправлено"

Может у вас есть сообщения, которые можно стереть? Я не знаю правил функционирования личной почты. Может хранятся посланные сообщения и их предел достигнут.
Таратухин Сергей
Цитата(Tarbal @ Sep 23 2013, 18:05) *
Я попробовал послать вам, но получил такую ошибку:

"Обнаружены следующие ошибки
Невозможно отправить это сообщение, так как получатель отключил свой личный ящик, или он попросту переполнен.

Это личное сообщение не отправлено"

Может у вас есть сообщения, которые можно стереть? Я не знаю правил функционирования личной почты. Может хранятся посланные сообщения и их предел достигнут.


У меня такая же ошибка, у меня сообщений вообще нет, так же пробовал настраивать обмен сообщениями, ни к чему положительному не привело, помощь тоже не работает.
Tarbal
Цитата(Таратухин Сергей @ Sep 23 2013, 10:26) *
Все верно, но как задействовать NAPI?


Для ARM архитектуры, я делаю так

В корне кернела исполнить команду:
make ARCH=arm menuconfig

Нажмите прмяой слеш : '/'
в строке поиска введите NAPI

Получите список всех возможных функций имэущих NAPI в названии ключа компиляции.
Там будет отражено состояние ключа, разрешающего функцию, путь к нему и зависимость его от других ключей.
Таратухин Сергей
Цитата(Tarbal @ Sep 23 2013, 18:20) *
Для ARM архитектуры, я делаю так

В корне кернела исполнить команду:
make ARCH=arm menuconfig

Нажмите прмяой слеш : '/'
в строке поиска введите NAPI

Получите список всех возможных функций имэущих NAPI в названии ключа компиляции.
Там будет отражено состояние ключа, разрешающего функцию, путь к нему и зависимость его от других ключей.


Это я делал, находил две опции:

CODE
Symbol: TULIP_NAPI [=n]
Type : boolean
Prompt: Use RX polling (NAPI)
Defined at drivers/net/tulip/Kconfig:79
Depends on: NETDEVICES [=y] && NET_ETHERNET [=y] && NET_TULIP [=n] && TULIP [=n]
Location:
-> Device Drivers
-> Network device support (NETDEVICES [=y])
-> Ethernet (10 or 100Mbit) (NET_ETHERNET [=y])
-> "Tulip" family network device support (NET_TULIP [=n])
-> DECchip Tulip (dc2114x) PCI support (TULIP [=n])


Symbol: TULIP_NAPI_HW_MITIGATION [=n]
Type : boolean
Prompt: Use Interrupt Mitigation
Defined at drivers/net/tulip/Kconfig:93
Depends on: NETDEVICES [=y] && NET_ETHERNET [=y] && NET_TULIP [=n] && TULIP_NAPI [=n]
Location:
-> Device Drivers
-> Network device support (NETDEVICES [=y])
-> Ethernet (10 or 100Mbit) (NET_ETHERNET [=y])
-> "Tulip" family network device support (NET_TULIP [=n])
-> DECchip Tulip (dc2114x) PCI support (TULIP [=n])
-> Use RX polling (NAPI) (TULIP_NAPI [=n])


но как эти опции влияют на CAN не понимаю, я их не включал. Если их включить как они повлияют на обработку приема по интерфейсу CAN и как необходимо переписать программу приема, чтоб использовать NAPI?
Tarbal
Цитата(Таратухин Сергей @ Sep 23 2013, 16:45) *
но как эти опции влияют на CAN не понимаю, я их не включал. Если их включить как они повлияют на обработку приема по интерфейсу CAN и как необходимо переписать программу приема, чтоб использовать NAPI?


Я не знаком с NAPI и CAN драйверы на Линуксе я тоже не делал. Полагаю, что CAN драйвер надо настроить (или дописать), чтобы использовал механизм NAPI. Если вы не работали с кернелом, то вам будет непросто выполнить эту задачу.

Прежде чем начинать надо оценить насколько оно вам поможет.
Я отношусь скептически к использованию поллинга при большом количестве сообщений. Уменьшение нагрузки на процессор в случае поллинга возможно за счет потери сообщений. Возможно более короткий обработчик (чем прерывание) положительный фактор, однако частые обращения, когда не надо и запоздалые, когда надо -- это негативная сторона поллинга.
Ведь вашему процессору все-равно необходимо работать над каждым сообщением в прерывании или нет. Он все равно потратит на обработку сообщений много времени. Использование поллинга не всегда гарантирует, что все сообщения будут приняты. Особенно в сложной обстановке с массовым потоком сообщений.

Решение задачи я вижу только в одном из направлений:
1. Снижение интенсивности сообщений
2. Использование более мощного процессора.
3. Установка дополнительного устройства, ответственного за обработку (хотя бы частичную) сообщений.

В третьем случае может понадобится написать драйвер.
sasamy
Цитата(Таратухин Сергей @ Sep 23 2013, 16:45) *
Это я делал, находил две опции:
..
но как эти опции влияют на CAN не понимаю, я их не включал.


Эти - никак не влияют.

Цитата
как необходимо переписать программу приема, чтоб использовать NAPI?


Ничего переписывать не надо - NAPI должен поддерживать драйвер, некоторые делают опциаональные настройки - выбор между обычным и New API, у вашего контроллера NAPI используется всегда

http://lxr.free-electrons.com/source/drive.../ti_hecc.c#L860

почему поллинг не снижает количество прерываний - это надо разбираться с этим драйвером и контроллером.
AndrewN
QUOTE (sasamy @ Sep 23 2013, 16:38) *
почему поллинг не снижает количество прерываний - это надо разбираться с этим драйвером и контроллером
Коллеги, никак не пойму, что за проблему вы тут обсуждаете? Один мегабит в секунду - это 128KB/s, т.е. цыплячья скорость UARTа, и это нагружает Ослинукс на 600 мегагерцовом процессоре???? Я или сам ослинукс или мне просто смешно...

Интервал между двумя последовательными байтами 4,700 клоков - этого мало _один_ байт обработать???? А 0.8 на шине, т.е. 0.8*128 это уже 5,900 клоков на байт - за такое время не только пообедать, но и посуду можно вымыть...
A. Fig Lee
Цитата(AndrewN @ Sep 23 2013, 17:51) *
Коллеги, никак не пойму, что за проблему вы тут обсуждаете? Один мегабит в секунду - это 128KB/s, т.е. цыплячья скорость UARTа, и это нагружает Ослинукс на 600 мегагерцовом процессоре???? Я или сам ослинукс или мне просто смешно...

Интервал между двумя последовательными байтами 4,700 клоков - этого мало _один_ байт обработать???? А 0.8 на шине, т.е. 0.8*128 это уже 5,900 клоков на байт - за такое время не только пообедать, но и посуду можно вымыть...

Мда..

Вы линукс то видали?
Сколько там процессов/тредов бежит смотрели?
Tarbal
Цитата(AndrewN @ Sep 24 2013, 01:51) *
Коллеги, никак не пойму, что за проблему вы тут обсуждаете? Один мегабит в секунду - это 128KB/s, т.е. цыплячья скорость UARTа, и это нагружает Ослинукс на 600 мегагерцовом процессоре???? Я или сам ослинукс или мне просто смешно...

Интервал между двумя последовательными байтами 4,700 клоков - этого мало _один_ байт обработать???? А 0.8 на шине, т.е. 0.8*128 это уже 5,900 клоков на байт - за такое время не только пообедать, но и посуду можно вымыть...


Цыплячья скорость UART в 10 раз ниже 115kBit/S. У UART сообщения однобайтовые и все. У CAN надо каждое сообщение обрабатывать. Значит ПДП не обойдешься как можно было бы на UART сделать.

Сколько времени занимает вход в в прерывание (~5uS)? Умножте это на 2000 (128000/64). Столько времени надо отдать на накладные расходы каждую секунду. Идет борьба за это время.
2000*5uS = 10mS. Что есть один процент. Похоже вы правы. Надо исследовать и найти что пожирает время.

Я честно боролся за оптимизацию sm.gif


Простейший способ проверить время обработки прерывания дергать свободную ножку при входе вверх, а при завершении обработки вниз. Правда одной ножкой не обойдешся.
надо одну дергать вверх при входе в прерывание и вскоре вниз. Вторую в нашем обработчике CAN. В начале вверх, а в конце вниз. Синхронизироваться от второй ножки и посмотрель осциллографом время от начала первого импульса до конца второго.

Могу помочь найти как сконфигурировать ножки и место куда вставить команды.

Цитата(A. Fig Lee @ Sep 24 2013, 04:34) *
Мда..

Вы линукс то видали?
Сколько там процессов/тредов бежит смотрели?


Как я понял разница когда есть поток сообщений и когда нет отличаются на 60% занятости процессора.
AndrewN
QUOTE (Tarbal @ Sep 24 2013, 04:54) *
Цыплячья скорость UART в 10 раз ниже 115kBit/S
Упс..., промашку давал... Утячья скорость получается - в полёте... :)

QUOTE (Tarbal @ Sep 24 2013, 04:54) *
Сколько времени занимает вход в в прерывание (~5uS)? Умножте это на 2000 (128000/64)
Интересно. Т.е. 1 интеррапт на каждые 64 байта? Это облегчает задачу. EDMA же привязана к ивенту, она и сложит эти 64 байта в угол, т.е. в буфер...

5 микросек это 3000 клоков процессора. На вход многовато, вход прост (разумно предположить такое?), а вот выход сложнее из-за перепланировки (знать бы алгоритм...). Ну условно можно считать, что 5 на вход и выход - разумное число. Хотя, это же Ослинукс, кто его разберёт... При 0.8 загрузке 5,900*64 клоков на 64 байта это 377К, от коего числа 3К на оверхед интеррапта составляет 0.0079 - т.е. 8 промилле. Меньше, чем процент.
Tarbal
Цитата(AndrewN @ Sep 24 2013, 06:56) *
Упс..., промашку давал... Утячья скорость получается - в полёте... sm.gif

Интересно. Т.е. 1 интеррапт на каждые 64 байта? Это облегчает задачу. EDMA же привязана к ивенту, она и сложит эти 64 байта в угол, т.е. в буфер...

5 микросек это 3000 клоков процессора. На вход многовато, вход прост (разумно предположить такое?), а вот выход сложнее из-за перепланировки (знать бы алгоритм...). Ну условно можно считать, что 5 на вход и выход - разумное число. Хотя, это же Ослинукс, кто его разберёт... При 0.8 загрузке 5,900*64 клоков на 64 байта это 377К, от коего числа 3К на оверхед интеррапта составляет 0.0079 - т.е. 8 промилле. Меньше, чем процент.


1 message 64 бита.
Значит я ошибся в 8 раз, что уже приближается к порядку величины, полученной экспериментально.
Еще надо на обработку прерывания сколько-то дать. Потом апликация начинает обрабатывать. Выходим на порядок десятков процентов.
_3m
Цитата(AndrewN @ Sep 24 2013, 06:56) *
Интересно. Т.е. 1 интеррапт на каждые 64 байта? Это облегчает задачу. EDMA же привязана к ивенту, она и сложит эти 64 байта в угол, т.е. в буфер...

DMA слабо помогает в случае приема кан пакетов. Пакеты короткие и их из-за специфики применений шины кан приходится обрабатывать все программно.

Цитата
5 микросек это 3000 клоков процессора. На вход многовато, вход прост (разумно предположить такое?), а вот выход сложнее из-за перепланировки (знать бы алгоритм...). Ну условно можно считать, что 5 на вход и выход - разумное число. Хотя, это же Ослинукс, кто его разберёт... При 0.8 загрузке 5,900*64 клоков на 64 байта это 377К, от коего числа 3К на оверхед интеррапта составляет 0.0079 - т.е. 8 промилле. Меньше, чем процент.

Такты считать бессмысленно потому что нужно плюсовать: промах I-cache с загрузкой строки с кодом обработчика прерывания (в это время цпу стоит), промах D-cache с загрузкой строки стека прерываний (в это время цпу стоит), плюсуйте латентность DDR2/3, плюсуйте задержки шинных коммутаторов. Прерывания каждые 50мкс для процессора это существенная нагрузка, причем чем больше гигагерц и ядер тем тяжелее

Также смотрим исходник драйвера кан (любого) и видим что на каждый пакет вызываются такие интересные функции как:
alloc_can_skb()
netif_receive_skb() которая в свою очередь вызывает совсем забавную функцию __netif_receive_skb()

Удивляет что оно вообще успевает принимать пакеты без потерь.
AndrewN
QUOTE (_3m @ Sep 24 2013, 10:17) *
Такты считать бессмысленно потому что нужно плюсовать: промах I-cache с загрузкой строки с кодом обработчика прерывания (в это время цпу стоит), промах D-cache с загрузкой строки стека прерываний (в это время цпу стоит), плюсуйте латентность DDR2/3, плюсуйте задержки шинных коммутаторов. Прерывания каждые 50мкс для процессора это существенная нагрузка, причем чем больше гигагерц и ядер тем тяжелее
Они (ЦПУ столлы) с необходимостью входят в итоговый счёт. Но, всё-таки полагаем, что кеши увеличивают производительность, а не уменьшают :)

Поток с интервалом 50мкс, т.е. 20KHz, это даже меньше чем хай-фай аудио 2Х4 байта @96KHz, а ведь и стереозвук обрабатывают.

У меня получилось чуть больше, 65мкс на 8 байт. Предположим, что 5мкс оверхед прерывания, остаётся 60мкс или 36К клоков на расфасовку 8 байт. На первый взгляд - выполнимо...
Tarbal
Цитата(AndrewN @ Sep 25 2013, 01:50) *
Поток с интервалом 50мкс, т.е. 20KHz, это даже меньше чем хай-фай аудио 2Х4 байта @96KHz, а ведь и стереозвук обрабатывают.

У меня получилось чуть больше, 65мкс на 8 байт. Предположим, что 5мкс оверхед прерывания, остаётся 60мкс или 36К клоков на расфасовку 8 байт. На первый взгляд - выполнимо...


Стерео звук обрабатывает дополнительное ядро DSP или специальный хардвер. Да и обработать большой буфер без метаний в прерывание легче если он уже принять при помощи ПДП.
5 мкс это вход в прерывание, потом еще обработка и вызов тасклета или work, что возьмет дополнительное время. Некоторые сообщения вызовут действия в пользовательском пространстве. Получится значительно больше.
Таратухин Сергей
Цитата(Tarbal @ Sep 23 2013, 19:33) *
Я не знаком с NAPI и CAN драйверы на Линуксе я тоже не делал. Полагаю, что CAN драйвер надо настроить (или дописать), чтобы использовал механизм NAPI. Если вы не работали с кернелом, то вам будет непросто выполнить эту задачу.

Прежде чем начинать надо оценить насколько оно вам поможет.
Я отношусь скептически к использованию поллинга при большом количестве сообщений. Уменьшение нагрузки на процессор в случае поллинга возможно за счет потери сообщений. Возможно более короткий обработчик (чем прерывание) положительный фактор, однако частые обращения, когда не надо и запоздалые, когда надо -- это негативная сторона поллинга.
Ведь вашему процессору все-равно необходимо работать над каждым сообщением в прерывании или нет. Он все равно потратит на обработку сообщений много времени. Использование поллинга не всегда гарантирует, что все сообщения будут приняты. Особенно в сложной обстановке с массовым потоком сообщений.

Решение задачи я вижу только в одном из направлений:
1. Снижение интенсивности сообщений
2. Использование более мощного процессора.
3. Установка дополнительного устройства, ответственного за обработку (хотя бы частичную) сообщений.

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


Приношу извинения за задержку немного погрузился в проблему загрузки ОС. Ситуацию удалось изменить, сейчас загрузка ОС Linux составляет примерно 10-11% при той же ~80% загрузке шины CAN (при компиляции не обратил внимание, что в ядро включено много не нужного). Данная загрузка приемлемая, но возникла другая проблема.

CODE
Mem: 52544K used, 191492K free, 0K shrd, 1796K buff, 43212K cached
CPU: 0% usr 5% sys 0% nic 78% idle 0% io 0% irq 14% sirq
Load average: 0.11 0.06 0.03 1/54 832
PID PPID USER STAT VSZ %MEM %CPU COMMAND
831 828 root R 1472 1% 10% ./a.out
355 2 root SW 0 0% 1% [kworker/0:1]
832 828 root R 2844 1% 0% top
507 2 root SW 0 0% 0% [ksdioirqd/mmc1]
828 801 root S 2844 1% 0% -sh
768 1 root S 2732 1% 0% /sbin/syslogd -n -C64 -m 20
770 1 root S 2668 1% 0% /sbin/klogd -n
518 1 root S 2668 1% 0% /bin/sh /etc/rcS.d/S01psplash start
761 1 root S 2668 1% 0% /usr/sbin/telnetd
521 518 root S 2536 1% 0% sleep 120
756 1 messageb S 2436 1% 0% /usr/bin/dbus-daemon --system
801 1 root S 2400 1% 0% login -- root
539 1 root S < 2188 1% 0% /sbin/udevd -d
557 539 root S < 2184 1% 0% /sbin/udevd -d
567 539 root S < 2184 1% 0% /sbin/udevd -d
1 0 root S 1628 1% 0% init [5]
5 2 root SW 0 0% 0% [kworker/u:0]
495 2 root SW 0 0% 0% [mmcqd/0]
3 2 root SW 0 0% 0% [ksoftirqd/0]
45 2 root SW 0 0% 0% [irq/74-serial i]


CODE
root@am3517-evm:~# cat /proc/interrupts
CPU0
11: 0 INTC prcm
12: 2658 INTC DMA
20: 0 INTC gpmc
24: 999278 INTC can0
25: 4 INTC OMAP DSS
37: 177708 INTC gp timer
56: 921263 INTC omap_i2c
57: 0 INTC omap_i2c
58: 33368 INTC omap_hdq
61: 0 INTC omap_i2c
71: 1 INTC musb-hdrc.0
72: 0 INTC serial idle
73: 0 INTC serial idle
74: 30619 INTC serial idle, OMAP UART2
77: 0 INTC ehci_hcd:usb2
83: 4935 INTC mmc0
86: 178303 INTC mmc1
160: 0 GPIO tps6507x
162: 1 GPIO mmc1
184: 0 GPIO ds1374
186: 0 GPIO tca8418-keypad
224: 0 GPIO mmc0
Err: 0


CODE
root@am3517-evm:~# ifconfig
can0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:16 Metric:1
RX packets:1000000 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10
RX bytes:8000000 (7.6 MiB) TX bytes:0 (0.0 B)
Interrupt:24

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)


Цитата(_3m @ Sep 24 2013, 12:17) *
DMA слабо помогает в случае приема кан пакетов. Пакеты короткие и их из-за специфики применений шины кан приходится обрабатывать все программно.


Такты считать бессмысленно потому что нужно плюсовать: промах I-cache с загрузкой строки с кодом обработчика прерывания (в это время цпу стоит), промах D-cache с загрузкой строки стека прерываний (в это время цпу стоит), плюсуйте латентность DDR2/3, плюсуйте задержки шинных коммутаторов. Прерывания каждые 50мкс для процессора это существенная нагрузка, причем чем больше гигагерц и ядер тем тяжелее

Также смотрим исходник драйвера кан (любого) и видим что на каждый пакет вызываются такие интересные функции как:
alloc_can_skb()
netif_receive_skb() которая в свою очередь вызывает совсем забавную функцию __netif_receive_skb()

Удивляет что оно вообще успевает принимать пакеты без потерь.


Действительно при превышении 15% загрузки шины CAN при скорости 1МБит/с начинаются потери пакетов (потери наблюдались при загрузки шины CAN ~20%). Максимально замеченные потери составили 0.03% на 1000000 пакетов. Как побороть эту проблему пока не понимаю. Если у кого то есть идеи или вариант решения буду благодарен.
Tarbal
Цитата(Таратухин Сергей @ Oct 8 2013, 09:27) *
Действительно при превышении 15% загрузки шины CAN при скорости 1МБит/с начинаются потери пакетов (потери наблюдались при загрузки шины CAN ~20%). Максимально замеченные потери составили 0.03% на 1000000 пакетов. Как побороть эту проблему пока не понимаю. Если у кого то есть идеи или вариант решения буду благодарен.


Вы пользуетесь поллингом или интерраптом?
Не исключено, что возникают ошибки. Посмотрите как обрабатываются ошибки.

Поставить счетчик обработаных сообщений интерраптом и проверить равно ли количество интерраптов этому значению. Если они не равны то:
Заведите на каждую ошибку по переменной, инициализируйте их нулем, вставьте инкрементировани этих переменных в обработчики ошибок. После эксперимента проверьте переменные, так можно будет узнать о характере проблемы.

Если используете поллинг, то он может пропустить пакет, а если ошибка -- выбросить испорченый.
Если interrupt, то неплохо бы время реакции померять. Самый простой способ -- дернуть пин в обработчике прерывания и двухлучевым осциллографом посмотреть на шину CAN и этот пин. Посмотреть сколько времени занимает от конца сообщения до дергания пина.

Попробовать слать сообщения с интервалом между сообщениями и без интервала. Сравнить статистику.
Таратухин Сергей
Цитата(Tarbal @ Oct 8 2013, 18:21) *
Вы пользуетесь поллингом или интерраптом?
Не исключено, что возникают ошибки. Посмотрите как обрабатываются ошибки.

Поставить счетчик обработаных сообщений интерраптом и проверить равно ли количество интерраптов этому значению. Если они не равны то:
Заведите на каждую ошибку по переменной, инициализируйте их нулем, вставьте инкрементировани этих переменных в обработчики ошибок. После эксперимента проверьте переменные, так можно будет узнать о характере проблемы.

Если используете поллинг, то он может пропустить пакет, а если ошибка -- выбросить испорченый.
Если interrupt, то неплохо бы время реакции померять. Самый простой способ -- дернуть пин в обработчике прерывания и двухлучевым осциллографом посмотреть на шину CAN и этот пин. Посмотреть сколько времени занимает от конца сообщения до дергания пина.

Попробовать слать сообщения с интервалом между сообщениями и без интервала. Сравнить статистику.


Экспериментируя с приемом по CAN заметил такую закономерность: если во время приема вылетело сообщение omap_device: omap_i2c.1: new worst case deactivate latency 0: 518798 или omap_device: omap_i2c.1: new worst case activate latency 0: 183105, то происходит потеря пакетов, если таких сообщений нет, то прием проходит без потерь. Что это за задержки и как они могут влиять на CAN?
Tarbal
Цитата(Таратухин Сергей @ Oct 15 2013, 13:11) *
Экспериментируя с приемом по CAN заметил такую закономерность: если во время приема вылетело сообщение omap_device: omap_i2c.1: new worst case deactivate latency 0: 518798 или omap_device: omap_i2c.1: new worst case activate latency 0: 183105, то происходит потеря пакетов, если таких сообщений нет, то прием проходит без потерь. Что это за задержки и как они могут влиять на CAN?


latency имеет немного не такой смысл как задержка. Это скорее интервал временной недоступности рессурса. Вот например имеем мы обработчик прерывания на 10 микросекунд и в это время менее приоритетные прерывания не могут быть обработаны, значит имеем latency 10 мкс. Другой пример видео устройство обрабатывает видеопоток, но между входным и выходным кадром четыре находятся внутри видео устройства. Имеем latency 4 кадра.

Полагаю, что если где-то запрещены прерывания, то это тоже вызывает latency.

Я бы поискал кто пишет сообщения и выяснил бы сценарий. Каким боком к вашему CAN относится i2c? Возможно они борятся за какой-то общий рессурс или их обоих кто-то третий тормозит.
строка 231:
http://lxr.free-electrons.com/source/arch/..._device.c?v=3.6


Про сообщение:
http://git.igep.es/?p=pub/scm/linux-omap-2...1a6f2cb4f79b6c0
Таратухин Сергей
Цитата(Tarbal @ Oct 15 2013, 18:12) *
latency имеет немного не такой смысл как задержка. Это скорее интервал временной недоступности рессурса. Вот например имеем мы обработчик прерывания на 10 микросекунд и в это время менее приоритетные прерывания не могут быть обработаны, значит имеем latency 10 мкс. Другой пример видео устройство обрабатывает видеопоток, но между входным и выходным кадром четыре находятся внутри видео устройства. Имеем latency 4 кадра.

Полагаю, что если где-то запрещены прерывания, то это тоже вызывает latency.

Я бы поискал кто пишет сообщения и выяснил бы сценарий. Каким боком к вашему CAN относится i2c? Возможно они борятся за какой-то общий рессурс или их обоих кто-то третий тормозит.
строка 231:
http://lxr.free-electrons.com/source/arch/..._device.c?v=3.6


Про сообщение:
http://git.igep.es/?p=pub/scm/linux-omap-2...1a6f2cb4f79b6c0


Сделал следующим образом, в файле omap_device.c поправил функцию _omap_device_activate
было
CODE
124 odpl = od->pm_lats + od->pm_lat_level;
125
126 if (!ignore_lat &&
127 (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit))
128 break;
129
130 read_persistent_clock(&a);

сделал
CODE
124 odpl = od->pm_lats + od->pm_lat_level;
125
126 if (!ignore_lat)
127 break;
128
129 read_persistent_clock(&a);

Так же поправил функцию _omap_device_deactivate
было
CODE
191 odpl = od->pm_lats + od->pm_lat_level;
192
193 if (!ignore_lat &&
194 ((od->dev_wakeup_lat + odpl->activate_lat) >
195 od->_dev_wakeup_lat_limit))
196 break;
197
198 read_persistent_clock(&a);

сделал
CODE
190 odpl = od->pm_lats + od->pm_lat_level;
191
192 if (!ignore_lat)
193 break;
194
195 read_persistent_clock(&a);

При таком раскладе работает. Сейчас буду стучать в поддержку TI, чтоб нормально все поправили.
Tarbal
Вы уверены, что вы починили функциональность, а не только предотватили печатание сообщения?
Я бы разобрался что происходит для начала.
Таратухин Сергей
Цитата(Tarbal @ Oct 16 2013, 17:42) *
Вы уверены, что вы починили функциональность, а не только предотватили печатание сообщения?
Я бы разобрался что происходит для начала.


После правки, проверил работоспособность периферии сидящей на i2c, а так же проверил прием по CAN интерфейсу, потери пакетов не наблюдалось. Проверки продолжу, потому что действительно пока сам не уверен, что все работает должным образом. Параллельно буду донимать поддержку TI, чтоб они подтвердили, наличие ошибки и сделали корректный патч, не как я поступил, просто обрезал латентности.
Tarbal
Цитата(Таратухин Сергей @ Oct 16 2013, 15:53) *
Параллельно буду донимать поддержку TI, чтоб они подтвердили, наличие ошибки и сделали корректный патч, не как я поступил, просто обрезал латентности.


И не рассчитывайте sad.gif
У них (как и у Фрискейла) сейчас кампания за Андроид. Все что напрямую не связано с Андроидом ими игнорируется. Однако в e2e написать стоит.
Таратухин Сергей
Цитата(Tarbal @ Oct 16 2013, 18:47) *
И не рассчитывайте sad.gif
У них (как и у Фрискейла) сейчас кампания за Андроид. Все что напрямую не связано с Андроидом ими игнорируется. Однако в e2e написать стоит.


Вот ответ из TI:
CODE
If you make some search on the src code you will fond out that the fct the print this messages are _omap_device_activate and _omap_device_deactivate from arch/arm/plat-omap/omap_device.c.

Seems to be called from I2c driver context in this case. You will need to investigate when this code is called and why it would prevent the CAN driver to capture packets.


Нашел, более правильное решение, в файле omap_device.c для функции _omap_device_activate внес немного другое изменение.
было:
CODE
144 if (act_lat > odpl->activate_lat) {
145 odpl->activate_lat_worst = act_lat;
146 if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
147 odpl->activate_lat = act_lat;
148 pr_warning("omap_device: %s.%d: new worst case "
149 "activate latency %d: %llu\n",
150 od->pdev.name, od->pdev.id,
151 od->pm_lat_level, act_lat);
152 } else
153 pr_warning("omap_device: %s.%d: activate "
154 "latency %d higher than exptected. "
155 "(%llu > %d)\n",
156 od->pdev.name, od->pdev.id,
157 od->pm_lat_level, act_lat,
158 odpl->activate_lat);
159 }

сделал
CODE
144 if (act_lat > odpl->activate_lat) {
145 odpl->activate_lat_worst = act_lat;
146 if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
147 odpl->activate_lat = act_lat;
148 } else
149 pr_warning("omap_device: %s.%d: activate "
150 "latency %d higher than exptected. "
151 "(%llu > %d)\n",
152 od->pdev.name, od->pdev.id,
153 od->pm_lat_level, act_lat,
154 odpl->activate_lat);
155 }


И для функции _omap_device_deactivate
было
CODE
212 if (deact_lat > odpl->deactivate_lat) {
213 odpl->deactivate_lat_worst = deact_lat;
214 if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
215 odpl->deactivate_lat = deact_lat;
216 pr_warning("omap_device: %s.%d: new worst case "
217 "deactivate latency %d: %llu\n",
218 od->pdev.name, od->pdev.id,
219 od->pm_lat_level, deact_lat);
220 } else
221 pr_warning("omap_device: %s.%d: deactivate "
222 "latency %d higher than exptected. "
223 "(%llu > %d)\n",
224 od->pdev.name, od->pdev.id,
225 od->pm_lat_level, deact_lat,
226 odpl->deactivate_lat);
227 }

сделал
CODE
208 if (deact_lat > odpl->deactivate_lat) {
209 odpl->deactivate_lat_worst = deact_lat;
210 if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
211 odpl->deactivate_lat = deact_lat;
212 } else
213 pr_warning("omap_device: %s.%d: deactivate "
214 "latency %d higher than exptected. "
215 "(%llu > %d)\n",
216 od->pdev.name, od->pdev.id,
217 od->pm_lat_level, deact_lat,
218 odpl->deactivate_lat);
219 }
Tarbal
Отгадать не получится. Надо дебагировать.
Grommerin
Здравствуйте. Уже месяц бьюсь над такой-же проблемой.
Контроллер Freescale на плате iMX6 Marsboard.
При скорости 1Mbit и 18% загрузке шины (~2.3к сообщений в секунду) потери пакетов составляют стабильно 2,83-2,87%.
Попробовал изменить can_bittiming_const в драйвере, потери уменьшились до 0,03% но все еще присутствуют.
Код
static struct can_bittiming_const flexcan_bittiming_const = {
    .name = DRV_NAME,
-    .tseg1_min = 4,
+      .tseg1_min = 2,
-    .tseg1_max = 16,
+    .tseg1_max = 8,
    .tseg2_min = 2,
    .tseg2_max = 8,
    .sjw_max = 4,
    .brp_min = 1,
    .brp_max = 256,
    .brp_inc = 1,
};

Попытался изменить настройки ядра, но ничего путного не вышло т.к. я с Linux до этого никогда так плотно не работал. Только параметр Preemption Model существенно изменил результаты. По умолчанию стоит "Preemptible Kernel (Low-Latensy Desktop)" и приходит огромное множество прерываний. При установке значения в "No Forsed Preemption (Server)" количество прерываний резко падает (по ощущениям именно в этот момент начинает нормально работать NAPI), но потери достигают 97%.

Пробовал добавлять в драйвер информационные сообщения что бы увидеть порядок вызова функций. Получилось приблизительно следующее:
CODE

Call flexcan_irq
Call flexcan_poll
Call flexcan_poll_state, quota = 8
Call flexcan_read_frame
Call flexcan_read_fifo
Call flexcan_read_frame
Call flexcan_read_fifo
Call flexcan_read_frame
Call flexcan_read_fifo
Call flexcan_read_frame
Call flexcan_read_fifo
Call flexcan_read_frame
Call flexcan_read_fifo
Call flexcan_read_frame
Call flexcan_read_fifo
Call flexcan_read_frame
Call flexcan_read_fifo
Call flexcan_read_frame
Call flexcan_read_fifo
Call flexcan_irq
Call flexcan_poll
Call flexcan_poll_state, quota = 8
Call flexcan_read_frame
Call flexcan_read_fifo
И так далее...

В общем буфер заполняется и получается Rx_Overflow.

Программа, которая считает пакеты получилась как тут, даже проще: просто инкремент по принятию и раз в 10 секунд выдача в консоль.
CODE

#include "main.h"
#include "types.h"

#define SAVE_TIMER_TIME 10

static void Save_Timer(void);

unsigned int TransMessageCount = 0;

int main(int argc, char **argv)
{
const char* INTERFACE = NAME_CAN;

signal(SIGALRM, (void (*)(int)) Save_Timer);

signed int CanSocket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (CanSocket < 0) {
perror("READ: Can't open CAN socket");
}
alarm(SAVE_TIMER_TIME);

ifreq Ifr;
strncpy(Ifr.ifr_name, INTERFACE, sizeof(Ifr.ifr_name));
if (ioctl(CanSocket, SIOCGIFINDEX, &Ifr)) {
perror("READ: Error in IOCTL func");
}

sockaddr_can Addr;
Addr.can_family = PF_CAN;
Addr.can_ifindex = Ifr.ifr_ifindex;
if (bind(CanSocket, (struct sockaddr*)&Addr, sizeof(Addr)) < 0) {
perror("READ: Error in BIND func");
}

static unsigned int TransMessBufLength = 0;
static int ReadBytes;
static can_frame Frame;

while(1) {
ReadBytes = recv(CanSocket, &Frame, sizeof(struct can_frame), 0);
if(ReadBytes > 0) {
TransMessageCount++;
}
}
close(CanSocket);
return 0;
}

static void Save_Timer(void)
{
cout <<"Read "<< TransMessageCount <<" messages\n";
alarm(SAVE_TIMER_TIME);
return;
}

И если даже такая простая программа не успевает, то что же будет с реальным многопоточным приложением...

В общем я застрял на потерях и не знаю в каком направлении мне двигаться дальше. Прошу у вас помощи или совета.
ZASADA
Цитата(Grommerin @ Nov 3 2014, 15:02) *
Здравствуйте. Уже месяц бьюсь над такой-же проблемой.
Контроллер Freescale на плате iMX6 Marsboard.
При скорости 1Mbit и 18% загрузке шины (~2.3к сообщений в секунду) потери пакетов составляют стабильно 2,83-2,87%.

вы неправильно считаете загрузку шины. в силу специфики арбитража при наличии нескольких устройств на шине CAN пакеты размазаны по времени не равномерно, а идут непрерывными склеенными пачками. и те стандартные драйверы что я видел способны легко терять следующий пакет пока обрабатывают предыдущий.
Grommerin
Цитата(ZASADA @ Nov 4 2014, 13:39) *
вы неправильно считаете загрузку шины. в силу специфики арбитража при наличии нескольких устройств на шине CAN пакеты размазаны по времени не равномерно, а идут непрерывными склеенными пачками. и те стандартные драйверы что я видел способны легко терять следующий пакет пока обрабатывают предыдущий.

Вы правы, я не правильно высказался. 2.3к пакетов в секунду мне показывает программа мониторинга шины, она сама считает загрузку. Только вот время между пакетами с точностью 100мс выдает((

Может вы сможете посоветовать в каком направлении мне смотреть для того что бы драйвер смог разбирать сообщения максимально быстро? В данный момент я пытаюсь прикрутить к нему циклический буфер, но пока ничего не получается.
А еще получается так, чо при одной и той же конфигурации устройств на шине, при перезагрузке моей платы я могу наблюдать 2,8% потерь, а могу и 0,3%. Но чаще 2,8%.
_3m
Чтобы не начинать похожую тему напишу сюда.

Разыскиваю материалы с анализом производительности драйвера Can4linux
Нагуглил исследования производительности драйверов SocketCan и LinCAN а вот исследований Can4linux не нашел.
Сейчас мы используем SocketCan хочется перейти на что-то более производительное.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.