|
Документ взят из кэша поисковой машины. Адрес
оригинального документа
: http://rtm-cs.sinp.msu.ru/new/can/candrv_2.html
Дата изменения: Tue Dec 22 12:22:08 1998 Дата индексирования: Mon Oct 1 19:54:12 2012 Кодировка: koi8-r |
_/_/_/_/_/ _/_/_/_/ _/_/_/ _/_/
_/_/ _/_/ _/_/ _/_/_/_/ _/_/
_/_/ _/_/ _/_/ _/_/ _/_/ _/_/
_/_/ _/_/_/_/_/_/ _/_/ _/_/_/_/
_/_/_/_/_/_/ _/_/ _/_/ _/_/ _/_/_/ driver.
Руководство программиста.
Данное руководство предназначено для тех кто желает научиться писать
программы пользовательского уровня с использованием драйвера candrv в
операционной системе Linux. Руководство расчитано на подготовленного
программиста, имеющего некоторый опыт написания программ для U*IX систем.
Основное внимание уделяется разбору приемов взаимодействия прикладной
программы с драйвером, в то время как вопросы взаимодействия программ с
U*IX системой опускаются.
1. Первое знакомство с candrv.
Итак, напишем нашу первую программу для взаимодействия с CAN bus.
#include
#include
#include
#include
#include
#define NUM_4_SEND 1000
int main(void)
{
int d;
long count = 0;
can_msg frame;
frame.len = 1;
frame.id = 1;
frame.flags = 0;
frame.data[0] = 5;
d = open("/dev/can0", O_RDWR);
if(d<0){
printf("open /dev/can0 failed\n");
exit(1);
ioctl(d, CAN_SET_BAUDRATE, BAUD_1M);
for(; count < NUM_4_SEND; count++){
if(!write(d, &frame, 1))
printf("Can't write frame!!!! #%d\n", count);
}
if(close(fd))
printf("Error while closing file\n");
else
printf("Everything is OK!\n");
return 0;
}
Разберем по шагам то, что написано выше. Прежде всего мы определили переменную
с именем frame, которая имеет тип can_msg. Данные драйверу candrv передаются
именно в форме таких структур. Определен тип данных can_msg следующим образом:
typedef struct {
byte data[8];
unsigned int id;
byte len;
byte flags;
}can_msg;
Это определение находится в заголовочном файле candrv.h, который мы и включаем
в начале нашего первого примера наряду с другими стандартными заголовками.
Разберемся со значением отдельных полей типа данных can_msg. Поле data может
содержать в себе до 8 байт полезной информации. Поле id является идентификато-
ром CAN пакета. Поле len содержит фактическое число байт в массиве data. Поле
flags может иметь несколько значений для определения смысла которых загляните
в файл candrv.h.
Как Вы уже наверное поняли, взаимодействие с драйвером происходит через
специальный файл устройства. В нашем примере это файл /dev/can0. Для того
чтобы понять какому устройству отвечает тот или иной файл устройства can,
Вы должны ознакомиться с документом "CAN driver - Руководство пользователя".
Следующее необходимое действие - это открытие файла /dev/can0. Делается это
при помощи системного вызова open(). Далее у Нас может возникнуть потребность
в настройке каких - либо характеристик драйвера. В нашем примере мы устанав-
ливаем Baudrate CAN контроллера с помощью системного вызова ioctl(). Все
возможные комманды и их аргументы приведены в Приложении 2.
Теперь когда файл /dev/can0 открыт без ошибок мы можем производить операции
записи или чтения в этот файл, что и демонстрирует вызов функции write() с
соответствующими аргументами. А именно: с первым аргументом передается дескриптор
файла /dev/can0, со вторым указатель на непрерывную область памяти, где нахо-
дятся структуры can_msg, с третьим параметром передается количество структур
can_msg, в массиве, адресуемом вторым аргументом.
В финале мы закрываем файл /dev/can0.
Итак мы разобрали первый пример - прогпамму, которая посылает 1000 пакетов
по сети CAN bus, по одному пакету за обращение к драйверу. Это наихудшая
политика отсылки сообщений. Лучие динамические характеристики candrv покажет,
если Вы будете посылать сразу несколько пакетов(оптимально FIFO_SIZE/2).
Напишем программу, которая позволит принимать сообщения из CAN сети.
#include
#include
#include
#include
#include
#include
#define STDDEV "/dev/can0"
int main(int argc, char **argv)
{
int d = 0;
int i = 0;
unsigned long pockets_received = 0;
int count = 0;
int readed = 0;
fd_set fds;
can_msg frame;
printf("Receive server. (C) 1998 by D.Komissarov\n\n");
if((d = open(STDDEV, O_RDWR)) < 0){
printf("cpingr: open of %s failed\n", device);
exit(1);
}
ioctl(d, CAN_SET_BAUDRATE, baud);
while(1){
FD_ZERO(&fds);
FD_SET(d, &fds);
select(d + 1, &fds, NULL, NULL, NULL);
if(FD_ISSET(d, &fds)) {
if(readed=read(d, &frame, 1)){
pockets_received+=readed;
printf("Already received %d pockets\n", pockets_received);
}
}
}
}
Второй пример показывает как можно организовать прием сообщений при помощи
системного вызова select(). Программа, показанная выше, читает данные из файла
/dev/can0 и подсчитывает количество полученых пакетов. Вызов select() позволяет
программе ждать прибытия очередного сообщения в состоянии "сна", что позитивно
сказывается на производительности системы в целом.
Таким образом, последовательность системных вызовов при работе с candrv,
примерно следующая:
open()
||
\||/
\/
ioctl() (если нужно)
||
\||/
\/
read(), write()
||
\||/
\/
close()
Стоит заметить, что большинство комманд, посредством вызовов ioctl(),
должны предшествовсть любому из вызовов read()/write(). Это связано с тем,
что большинство команд либо по своей сути могут нарушить работу драйвера
(команда CAN_RESET_DRIVER), либо блокируют на некоторое время прерывания
(команда CAN_SET_BAUDRATE), что может привести к нежелательной потере
пакетов и несвоевременной их отсылке.
Для облегчения создания протокола верхнего уровня (в виде надстройки
над candrv в пространстве пользователя), была введена возможность трансли-
ровать прерывания от CAN чипа пользовательскому процессу с целью его опо-
вещения. По умолчанию посылка сигналов отключена. Для включения зтой воз-
можности служат команды CAN_SWITCH_***_SIG, которые описаны в Приложении 2.
Сигналы, посылаемые candrv, соответствуют следующим событиям:
Табл. 1
+------------------+------------------+-----------------------+
| Событие | Сигнал ОС Linux | Команда вкл./выкл. |
+------------------+------------------+-----------------------+
| INT. ERROR | SIGUSR1 | CAN_SWITCH_ERROR_SIG |
+------------------+------------------+-----------------------+
| INT. WAKE_UP | SIGUSR2 | CAN_SWITCH_WAKE_UP_SIG|
+------------------+------------------+-----------------------+
| INT. BUS_OFF | SIGHUP | CAN_SWITCH_BUS_OFF_SIG|
+------------------+------------------+-----------------------+
Приложение1 (Baudrates)
candrv поддерживает следующие скорости передачи по сети CAN bus:
BAUD_1M - устанавливает baudrate CAN чипа равным 1 Mbit/sec.
BAUD_800K
BAUD_666K
BAUD_500K
BAUD_400K
BAUD_250K
BAUD_200K
BAUD_125K
BAUD_100K
BAUD_50K - устанавливает baudrate CAN чипа равным 50 Kbit/sec.
Приложение 2 (команды для ioctl()).
candrv воспринимает следующие команды посредством вызова функции ioctl():
Табл. 2
+------------------------+-------------------+-----------------------------+
| Код команды | Аргумент команды | Действие команды |
+------------------------+-------------------+-----------------------------+
| CAN_SET_BAUDRATE | BAUD_XXX - один из| Устанавливает скорость обме-|
| | Приложения 1. | на CAN чипа. |
+------------------------+-------------------+-----------------------------+
| CAN_SET_OUTCTL | | Устанавливает регистр Output|
| | BYTE value | Control CAN чипа в значение |
| | | value. |
+------------------------+-------------------+-----------------------------+
| CAN_SET_AMASK | | Устанавливает регистр Accep-|
| | BYTE value | tance Mask CAN чипа в значе-|
| | | ние value. |
+------------------------+-------------------+-----------------------------+
| CAN_SET_ACODE | | Устанавливает регистр Accep-|
| | BYTE value | tance Code CAN чипа в значе-|
| | | ние value. |
+------------------------+-------------------+-----------------------------+
| CAN_RESET_DRIVER | 0 | Очищает внутренние буферы |
| | | драйвера. Реинициализирует |
| | | чип в состояние по умолчанию|
+------------------------+-------------------+-----------------------------+
| CAN_PRINT_STATUS | 0 | Выводит на консоль дамп ре- |
| | | гистров CAN чипа. |
+------------------------+-------------------+-----------------------------+
| CAN_RELEASE_RC_BUFFER | 0 | Освобождает место в RXFIFO |
| | | чипа. (отладочная команда) |
+------------------------+-------------------+-----------------------------+
| CAN_TRANSMIT_REQUEST | 0 | Устанавливает бит Transmit |
| | | Request CAN чипа |
+------------------------+-------------------+-----------------------------+
| CAN_SET_SOFT_FILTER | 16bit value | Устанавливает маску прграмм-|
| | значимы 13bit | ного 13bit фильтра сообщений|
+------------------------+-------------------+-----------------------------+
| CAN_STOP_CHIP | 0 | Устанавливает бит Reset Req-|
| | | uest CAN чипа |
+------------------------+-------------------+-----------------------------+
| CAN_START_CHIP | 0 | Снимает бит Reset Request |
| | | CAN чипа |
+------------------------+-------------------+-----------------------------+
| CAN_SWITCH_ERROR_SIG | 0 - выключить | Вкл./Выкл. посылку сигнала |
| | 1 - включить | см. Табл. 1 |
+------------------------+-------------------+-----------------------------+
| CAN_SWITCH_WAKE_UP_SIG | 0 - выключить | Вкл./Выкл. посылку сигнала |
| | 1 - включить | см. Табл. 1 |
+------------------------+-------------------+-----------------------------+
| CAN_SWITCH_BUS_OFF_SIG | 0 - выключить | Вкл./Выкл. посылку сигнала |
| | 1 - включить | см. Табл. 1 |
+------------------------+-------------------+-----------------------------+
Denis Komissarov. 1998.
This site is optimized for Netscape 4.0
Last modified 10 Dec 1998