LINUX.ORG.RU

Драйвер cPCI-7841

 , , ,


0

1

Такая ситуация. Есть плата CAN интерфейс CompactPCI - cPCI-7841 (Adlink) Под неё производитель предлагает драйвера для ядра 2.6.25 У меня в системе стоит много сложных плат и они работают с более поздним ядром (3.0-3.5) поэтому проще притянуть cPCI-7841 к более поздней версии. Сам я драйвера под linux не писал и работал только с Qt, а производитель поддержку фактически не осуществляет. Приходится самому окунаться в проблему. Я попытался скомпилировать предоставленные ими драйвер и библиотеку под ядро 3.5.

В результате я получил:

make -C /lib/modules/3.5.0-17-generic/build SUBDIRS=/home/cPCI-7841/drvsrc modules
make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17-generic'
CC [M] /home/cPCI-7841/drvsrc/7841.o
/home/cPCI-7841/drvsrc/7841.c:442:2: error: unknown field 'ioctl' specified in initializer
/home/cPCI-7841/drvsrc/7841.c:442:2: warning: initialization from incompatible pointer type [enabled by default]
/home/cPCI-7841/drvsrc/7841.c:442:2: warning: (near initialization for 'fops.owner') [enabled by default]
make[2]: *** [/home/cPCI-7841/drvsrc/7841.o] Error 1
make[1]: *** [_module_/home/cPCI-7841/drvsrc] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17-generic'
make: *** [default] Error 2

В строке 442 файла 7841.c я заменил ioctl на unlocked_ioctl. Появилась другая ошибка:

make -C /lib/modules/3.5.0-17-generic/build SUBDIRS=/home/cPCI-7841/drvsrc modules
make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17-generic'
CC [M] /home/cPCI-7841/drvsrc/isrdpc.o
/home/cPCI-7841/drvsrc/isrdpc.c: In function 'adl_kill_fasync':
/home/cPCI-7841/drvsrc/isrdpc.c:265:25: error: 'POLL_IN' undeclared (first use in this function)
/home/cPCI-7841/drvsrc/isrdpc.c:265:25: note: each undeclared identifier is reported only once for each function it appears in
make[2]: *** [/home/cPCI-7841/drvsrc/isrdpc.o] Error 1
make[1]: *** [_module_/home/cPCI-7841/drvsrc] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17-generic'
make: *** [default] Error 2

Для борьбы с этой ошибкой по совету добавил #include <linux/sched.h> в файл isrdpc.c В результате все собралось без ошибок. Достаточно ли этих изменений для нормальной работы драйвера?

Дальше я по инструкции инсталлировал библиотеку и устройство:

cpci@cpci-dsp ~/cPCI-7841/driver $ sudo ./7841_inst.pl 1
[sudo] password for cpci:
make character device node '/dev/PCI7841W0' for PCI7841
cpci@cpci-dsp ~/cPCI-7841/lib $ sudo cp libpci_7841.so /usr/lib/

При компиляции кода, тестирующего плату получаю следующее:

cpci@cpci-dsp ~/cPCI-7841/sample $ make clean
rm -f *.o *~ test7841
cpci@cpci-dsp ~/cPCI-7841/sample $ make
gcc -c -Wall -Wstrict-prototypes -I../include test7841.c
gcc -c -Wall -Wstrict-prototypes -I../include conio.c
gcc -o test7841 -lpci_7841 test7841.o conio.o
test7841.o: In function `main':
test7841.c: (.text+0x21): undefined reference to `CanOpenDriver'
test7841.c: (.text+0x5a): undefined reference to `CanOpenDriver'
test7841.c: (.text+0x8b): undefined reference to `CanClearRxBuffer'
test7841.c: (.text+0x97): undefined reference to `CanClearTxBuffer'
test7841.c: (.text+0xa3): undefined reference to `CanClearRxBuffer'
test7841.c: (.text+0xaf): undefined reference to `CanClearTxBuffer'
test7841.c: (.text+0xe4): undefined reference to `CanConfigPort'
test7841.c: (.text+0xf9): undefined reference to `CanConfigPort'
test7841.c: (.text+0x1e7): undefined reference to `CanSendMsg'
test7841.c: (.text+0x20b): undefined reference to `CanSendMsg'
test7841.c: (.text+0x230): undefined reference to `CanGetRcvCnt'
test7841.c: (.text+0x241): undefined reference to `CanGetRcvCnt'
test7841.c: (.text+0x291): undefined reference to `CanRcvMsg'
test7841.c: (.text+0x2dd): undefined reference to `CanRcvMsg'
test7841.c: (.text+0x576): undefined reference to `CanCloseDriver'
test7841.c: (.text+0x583): undefined reference to `CanCloseDriver'
collect2: error: ld returned 1 exit status
make: *** [test7841] Error 1

Линковщик не смог связать функции. То есть по каким то причинам не инсталлировался драйвер при работе 7841_inst.pl или ошибка в другом?



Последнее исправление: chernenko (всего исправлений: 1)

Достаточно ли этих изменений для нормальной работы драйвера?

А хрен его знает

ttnl ★★★★★
()

модуль драйвера собрался, загружай его modprobe/insmod, через dmesg смотри его вывод...

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

SandySandy
()
Последнее исправление: SandySandy (всего исправлений: 3)

а после


sudo cp libpci_7841.so /usr/lib/


«sudo ldconfig» делать не нужно?

// я сам наверняка не знаю, предполагаю просто...

metawishmaster ★★★★★
()

надо can модуль подгрузить, т.е. самого стека

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

как раз вот этот скрипт его загружает и копирует библиотеку в usr/lib

cpci@cpci-dsp ~/cPCI-7841/driver $ sudo ./7841_inst.pl 1 [sudo] password for cpci: make character device node '/dev/PCI7841W0' for PCI7841

После этого делаю dmesg

..........
[   15.351043] sja1000 CAN netdevice driver
[   15.353241] sja1000_plx_pci 0000:04:09.0: >Detected «Adlink PCI-7841/cPCI-7841» card at slot #9
[   15.355281] microcode: CPU0 sig=0x1067a, pf=0x80, revision=0xa04
[   15.361494] sja1000_plx_pci 0000:04:09.0: >Channel #1 at 0x0001a800, irq 17 registered as can0
[   15.371599] sja1000_plx_pci 0000:04:09.0: >Channel #2 at 0x0001a880, irq 17 registered as can1
..........
[ 151.904361] 7841-0 device found with Addr0:[ac00] addr1:[a800] IRQ:[17]
[ 151.904405] Drv[7841]: Registering the character device: p7841 successful

cpci@cpci-dsp ~/cPCI-7841/lib $ nm libpci_7841.so

выводит эти функции

00001e20 T CanClearOverrun
00001e90 T CanClearRxBuffer
00001f40 T CanClearTxBuffer
00001320 T CanCloseDriver
000015a0 T CanConfigPort
00002210 T CanDetectBaudrate
00001bb0 T CanDisableReceive
00001b60 T CanEnableReceive
00001fc0 T CanGetArbitrationLostBit
00001ff0 T CanGetErrorCode
00002020 T CanGetErrorWarningLimit
000021f0 T CanGetIntStatusReg
00001a90 T CanGetLedStatus
000014a0 T CanGetPortStatus
00001db0 T CanGetRcvCnt
00001040 T CanGetReceiveEvent
000020f0 T CanGetRxErrorCount
00002120 T CanGetTxErrorCount

Я явно, наверное не учел какую то мелочь. Загрузил p7841.ko в ядро и скопировал libpci_7841.so в usr/lib

chernenko
() автор топика
Ответ на: комментарий от chernenko

сама библиотека в кеше присутствует

cpci@cpci-dsp /usr/lib $ ldconfig -p | grep cpci7841
libpci_7841.so (libc6) => /usr/lib/cpci7841/libpci_7841.so

chernenko
() автор топика
Ответ на: комментарий от SandySandy

Написал в Qt проект

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = cpci7841-test
TEMPLATE = app

SOURCES += main.cpp\
mainwindow.cpp

HEADERS += mainwindow.h\
pci_7841.h

FORMS += mainwindow.ui

unix:!macx:!symbian: LIBS += -L/usr/lib/cpci7841/ -lpci_7841

INCLUDEPATH += $$PWD/../cPCI-7841/include
DEPENDPATH += $$PWD/../cPCI-7841/include

Если не использовать библиотечные функции, то проект собирается. При этом в списке зависимостей библиотеки нет. Если в проект включить библиотечные функции, то возникает ошибка и соответственно ldd не выполнить. Какой-то затык. Наверное надо начинать перелапачивать библиотеку драйвера и его мейк. Что то не вызывают они у меня доверия судя по тому как они написаны и сформированы. Иначе я не понимаю в чем моя ошибка.

chernenko
() автор топика
Ответ на: комментарий от chernenko

Наверное надо начинать перелапачивать библиотеку драйвера и его мейк.

Драйвер это модуль ядра? непоможет, это просто kernel space он у тебя загрузился. Проверь зависимости либы так же через ldd, а архитектура у тебя 32 бит?

SandySandy
()
Ответ на: комментарий от chernenko

Наличие p7841.ko совершенно не требуется для линковки тестовой программы. У тебя проблемма в библиотеке libpci_7841. Линковщику она не нравится (толи не той архитектуры сама либа(32/64), толи в h-файле нет строк extern «C» и не сопадают имена функций для С++)

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

Да, вы правы! Я понимаю, что достаточно *.so. Буду внимательно ревьюировать их код библиотеки и makefile.Достаточно небрежно написана. Думал, что у такого производителя должно работать все из коробки.

chernenko
() автор топика
Ответ на: комментарий от chernenko

Если компилишь g++ - проверь h-файл на наличия чего-то подобного:

#ifdef  __cplusplus
# define MODBUS_BEGIN_DECLS  extern "C" {
# define MODBUS_END_DECLS    }
#else
# define MODBUS_BEGIN_DECLS
# define MODBUS_END_DECLS
#endif

MODBUS_BEGIN_DECLS
Несколько раз натыкался на такую засаду - h-файл не был расчитан на язык С++

sigurd ★★★★★
()

Погрепай исходники на предмет CanOpenDriver.

Ты забыл какую-то библиотеку или исходник.

anonymous
()
Ответ на: комментарий от sigurd

да, сделав ревью их исходников наткнулся на это. Теперь более печальная ситуация :(

[ 6183.609385] 7841-0 device found with Addr0:[ac00] addr1:[a800] IRQ:[17]
[ 6183.609425] Drv[7841]: Registering the character device: p7841 successful
[ 6209.432681] BUG: unable to handle kernel paging request at 800c538a
[ 6209.432735] IP: [<f8938534>] p7841_ioctl+0x14/0x470 [p7841]
[ 6209.432776] *pdpt = 000000002e9e7001 *pde = 0000000000000000
[ 6209.432816] Oops: 0000 [#1] SMP
[ 6209.432844] Modules linked in: p7841(O) bnep rfcomm parport_pc bluetooth ppdev binfmt_misc coretemp kvm_intel kvm gpio_ich snd_hda_intel snd_hda_codec snd_hwdep snd_pcm psmouse snd_seq_midi snd_rawmidi microcode joydev snd_seq_midi_event lpc_ich serio_raw snd_seq plx_pci sja1000 can_dev snd_timer snd_seq_device mac_hid snd i915 soundcore shpchp snd_page_alloc drm_kms_helper drm i2c_algo_bit video lp parport hid_generic usbhid hid e1000e usb_storage
[ 6209.433210]
[ 6209.433224] Pid: 4556, comm: cpci7841test Tainted: G O 3.5.0-17-generic #28-Ubuntu To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M.
[ 6209.433324] EIP: 0060:[<f8938534>] EFLAGS: 00010292 CPU: 1
[ 6209.433361] EIP is at p7841_ioctl+0x14/0x470 [p7841]
[ 6209.433394] EAX: edc3bf00 EBX: edc3bf00 ECX: bffff684 EDX: 800c5316
[ 6209.433432] ESI: f8938520 EDI: ef328a30 EBP: efafdf14 ESP: efafdef8
[ 6209.433471] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 6209.433506] CR0: 8005003b CR2: 800c538a CR3: 2ff6e000 CR4: 000407f0
[ 6209.433544] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 6209.433583] DR6: ffff0ff0 DR7: 00000400
[ 6209.433608] Process cpci7841test (pid: 4556, ti=efafc000 task=ee480000 task.ti=efafc000)
[ 6209.433659] Stack:
[ 6209.433674] 00000000 f6c75680 ef328a30 00000101 edc3bf00 f8938520 ef328a30 efafdf90
[ 6209.433745] c115e8fa ee3e41e0 edc3bf08 ef328a30 00000020 00000000 00000000 ee480000
[ 6209.433816] ee480000 00000000 efafdf78 c1059ddd ee480000 edc3bf01 0000003d 00000001
[ 6209.433887] Call Trace:
[ 6209.433906] [<f8938520>] ? RevMsg+0xe0/0xe0 [p7841]
[ 6209.433943] [<c115e8fa>] do_vfs_ioctl+0x7a/0x5a0
[ 6209.433976] [<c1059ddd>] ? do_sigaction+0x10d/0x1a0
[ 6209.434011] [<c105a16c>] ? sys_rt_sigaction+0x5c/0x90
[ 6209.434046] [<c115ee88>] sys_ioctl+0x68/0x80
[ 6209.434077] [<c15cff5f>] sysenter_do_call+0x12/0x28
[ 6209.434109] Code: 44 8b 0c 00 00 00 00 31 c0 eb b9 8d b6 00 00 00 00 8d bf 00 00 00 00 55 89 e5 83 ec 1c 89 5d f4 89 75 f8 89 7d fc 66 66 66 66 90 <8b> 5a 74 81 f9 13 53 0c 40 89 c7 89 d6 0f 84 49 01 00 00 0f 86
[ 6209.434395] EIP: [<f8938534>] p7841_ioctl+0x14/0x470 [p7841] SS:ESP 0068:efafdef8
[ 6209.434450] CR2: 00000000800c538a
[ 6209.472226] ---[ end trace c13ad222a3103402 ]---

chernenko
() автор топика
Ответ на: комментарий от chernenko

это вызывает любое обращение к ioctl

struct file_operations fops = 
{
	unlocked_ioctl: p7841_ioctl,   /*ioctl */
	open: p7841_open,
	release: p7841_release  /* a.k.a. close */
};
в оригинале был ioctl вместо unlocked_ioctl с которым модуль не компилировался. open вроде как без ошибки.

chernenko
() автор топика
Ответ на: комментарий от chernenko

Опять переключился на эту задачу. После ревью и правки кода могу читать и писать регистры устройства, но стабильной работы и передачи данных по CAN ещё не добился. Так как модули не писал, то надеюсь на подсказки,так как предыдущие все сообщения мне безмерно были полезны.

Первый вопрос. В оригинале использовалась:

int p7841_ioctl( struct inode *inode,  
		 struct file *file,
		 unsigned int ioctl_num,
    		 unsigned long ioctl_param);
заменил на:
int p7841_ioctl( struct file *file,
		 unsigned int ioctl_num,
    		 unsigned long ioctl_param);
Но в самой функции есть вызов
x = copy_from_user( ( void * ) &Enable_Flag,
                    ( const void* ) ioctl_param,
                    sizeof(U16) );
if( Enable_Flag == 0 )
{
    //fasync_helper((int) inode, file, 0, &(ppci_info->async_queue1));
    break;
}
else
{
    //if ( (fasync_helper((int) inode, file, 1,
    //     &(ppci_info->async_queue1))) == -ENOMEM )
    return -1;
}
так как inode в функцию не передается, то временно закомментировал эту часть до прихода понимания что с этим делать.

Второй вопрос. В 7841_init есть регистрация прерывания

irq_result = request_irq( pci_Info [ i ]->irqNo,
                          p7841_interrupt_handler,
                          IRQF_SHARED,
                          "pci7841",
                           pci_Info [ i ] );
Первая загрузка и выгрузка модуля происходит нормально. Но последующая загрузка приводит к ошибке:
[ 8107.673294] Drv[7841]: device_number = 1
[ 8107.673307] BUG: unable to handle kernel paging request at f894b088
[ 8107.673363] IP: [<c12d35b6>] strcmp+0x16/0x30
[ 8107.673401] *pdpt = 0000000001971001 *pde = 00000000371bc067 *pte = 0000000000000000 
[ 8107.673459] Oops: 0000 [#1] SMP 
[ 8107.673492] Modules linked in: p7841(O+) bnep rfcomm bluetooth parport_pc ppdev binfmt_misc plx_pci sja1000 can_dev gpio_ich coretemp kvm_intel kvm snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq joydev microcode snd_timer snd_seq_device lpc_ich snd psmouse serio_raw shpchp i915 drm_kms_helper mac_hid drm soundcore snd_page_alloc i2c_algo_bit video lp parport hid_generic usbhid hid e1000e usb_storage [last unloaded: p7841]
[ 8107.673888] 
[ 8107.673901] Pid: 16965, comm: insmod Tainted: G           O 3.5.0-17-generic #28-Ubuntu To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M.
[ 8107.673994] EIP: 0060:[<c12d35b6>] EFLAGS: 00010086 CPU: 1
[ 8107.674031] EIP is at strcmp+0x16/0x30
[ 8107.674056] EAX: f8951170 EBX: f164fb80 ECX: 00000032 EDX: f894b088
[ 8107.674095] ESI: f895114f EDI: f894b088 EBP: f21f9e2c ESP: f21f9e24
[ 8107.674134]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 8107.674168] CR0: 8005003b CR2: f894b088 CR3: 33472000 CR4: 000407f0
[ 8107.674206] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 8107.674245] DR6: ffff0ff0 DR7: 00000400
[ 8107.674270] Process insmod (pid: 16965, ti=f21f8000 task=f0dd0cb0 task.ti=f21f8000)
[ 8107.674316] Stack:
[ 8107.674331]  f4e5a3c0 f2d8ba00 f21f9ee0 c10c9853 0000002c f21f9e40 c15c8f5d f21f9e74
[ 8107.674403]  00000282 f4e5a410 000a460e 00000000 f21f9e98 00001fab 00000000 00000000
[ 8107.674474]  c19a2ae0 f21f9e70 c1037af8 f599a9e0 f164fb80 f4c02380 f21f9ef4 00000286
[ 8107.674545] Call Trace:
[ 8107.674566]  [<c10c9853>] register_handler_proc+0xa3/0x140
[ 8107.674604]  [<c15c8f5d>] ? _raw_spin_trylock+0xd/0x20
[ 8107.674641]  [<c1037af8>] ? default_spin_lock_flags+0x8/0x10
[ 8107.674681]  [<c1046266>] ? console_unlock+0x2c6/0x480
[ 8107.674716]  [<c10c63ec>] ? request_threaded_irq+0x6c/0x130
[ 8107.674752]  [<c1037af8>] ? default_spin_lock_flags+0x8/0x10
[ 8107.674790]  [<c10c6153>] __setup_irq+0x203/0x430
[ 8107.674822]  [<c113e0c3>] ? kmem_cache_alloc_trace+0x103/0x110
[ 8107.674864]  [<f8950dc0>] ? W7841_IsrProgram+0x410/0x410 [p7841]
[ 8107.674904]  [<c10c6426>] request_threaded_irq+0xa6/0x130
[ 8107.674939]  [<f894fa80>] ? p7841_ioctl+0x510/0x510 [p7841]
[ 8107.674976]  [<f894fb3a>] p7841_init+0xba/0x1d0 [p7841]
[ 8107.675010]  [<c1003112>] do_one_initcall+0x112/0x160
[ 8107.675047]  [<c109f862>] ? set_section_ro_nx+0x62/0x80
[ 8107.675081]  [<c10a2a87>] sys_init_module+0xa7/0x210
[ 8107.675116]  [<c114cbe3>] ? sys_close+0x73/0xc0
[ 8107.675147]  [<c15cff5f>] sysenter_do_call+0x12/0x28
[ 8107.675180] Code: f4 8b 7d fc 89 ec 5d c3 8d b6 00 00 00 00 8d bc 27 00 00 00 00 55 89 e5 83 ec 08 89 75 f8 89 7d fc 66 66 66 66 90 89 c6 89 d7 ac <ae> 75 08 84 c0 75 f8 31 c0 eb 04 19 c0 0c 01 8b 75 f8 8b 7d fc 
[ 8107.675467] EIP: [<c12d35b6>] strcmp+0x16/0x30 SS:ESP 0068:f21f9e24
[ 8107.675515] CR2: 00000000f894b088
[ 8107.789120] ---[ end trace 4a43362d5af442b4 ]---

Если регистрация прерывания не проводить, то модуль загружается и выгружается сколько угодно раз и регистры через IOCTL пишутся и читаются.

chernenko
() автор топика
Ответ на: комментарий от chernenko

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

chernenko
() автор топика
Ответ на: комментарий от chernenko

Для тех кто ещё будет возиться с этой платой в будущем. Всё ок. CPCI-7841 работает на ядре 3.5.0 после всех правок.

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