Здравствуйте. Уже месяц бьюсь над такой-же проблемой.
Контроллер 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%.
Пробовал добавлять в драйвер информационные сообщения что бы увидеть порядок вызова функций. Получилось приблизительно следующее:
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 секунд выдача в консоль.
#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;
}
И если даже такая простая программа не успевает, то что же будет с реальным многопоточным приложением...
В общем я застрял на потерях и не знаю в каком направлении мне двигаться дальше. Прошу у вас помощи или совета.