Документ взят из кэша поисковой машины. Адрес
оригинального документа
: 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Разберем по шагам то, что написано выше. Прежде всего мы определили переменную с именем 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 #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; } #includeВторой пример показывает как можно организовать прием сообщений при помощи системного вызова 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.#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); } } } }
This site is optimized for Netscape 4.0
Last modified 10 Dec 1998