Документ взят из кэша поисковой машины. Адрес оригинального документа : 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
candrv programmers manual
              _/_/_/_/_/    _/_/_/_/       _/_/_/      _/_/
            _/_/          _/_/  _/_/     _/_/_/_/    _/_/
          _/_/          _/_/   _/_/    _/_/  _/_/  _/_/
	_/_/	      _/_/_/_/_/_/   _/_/    _/_/_/_/
      _/_/_/_/_/_/  _/_/     _/_/  _/_/      _/_/_/  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
© 1998 RTM-CS Lab, Moscow, Russia