Проект

Общее

Профиль

Протокол (Версия 22)

Начиная с версии 2.2 в ПО устройств поменялась версия бинарного протокола взаимодействия с устройствами. Как следствие, поменялись структуры данных, с помощью которых шло взаимодействие, и коды некоторых команд.
Также некоторые команды и параметры к ним помечены как deprecated – помечены для удаления в версии протокола 30.

Взаимодействие приложения и устройств CAN-Hacker происходит по бинарному протоколу. Каждое пересылаемое сообщение начинается с заголовка:

typedef struct {
    uint8_t command;
    uint8_t sequence;
    uint8_t flags;
    uint8_t dSize;
} __attribute__((packed)) CommandHeader;

Однако для сообщений, используемых для работы с шинами данных, заголовок имеет немного другой вид:
typedef struct {
    uint8_t command;
    uint8_t sequence;
    uint16_t flags;
    uint16_t dSize;
} __attribute__((packed)) MsgCommandHeader;

В поле command отсылается команда для устройства. Диапазон команд от 0x01 до 0x7F.
Если устройство отвечает подтверждением выполнения команды, то в поле command выставляется старший бит для присланной команды. В поле sequence помещается порядковый номер запроса, поля flags и dSize сброшены в 0x00.
Если результатом выполнения команды является некий ответ, то в поле command будет выставлен номер команды из запроса. В поле sequence помещается порядковый номер запроса, поля flags и dSize будут заполнены исходя из формата ответа.
Поле sequence можно использовать для контроля обрабатываемых команд. Следует учесть, что для нумерации сообщений используется 2 раздельных счётчика команд. Первый используется для обработки команд от приложения к устройству, второй для контроля команд от устройства к приложению (например, команды с данными шины или с её состоянием: COMMAND_MESSAGE (0x40) и COMMAND_BUS_ERROR (0x48)).
Флаги в поле flags выставляются в зависимости от посылаемой команды.
В случае, если команда не поддерживается, то устройство присылает ответ, где в качестве команды будет значение 0xFF, в поле sequence порядковый номер запроса, а поля flags и dSize сброшены в 0x00.

Поддерживаемые команды

Синхронизация (COMMAND_SYNC 0xA5)

Информация об устройстве и управление

Нормально взаимодействие с устройством можно после отправки команды синхронизации (COMMAND_SYNC 0xA5) устройства.

Загрузка сертификата лицензии (COMMAND_DEVICE_CERTIFICATE 0x07)
Запрос информации об устройстве (COMMAND_DEVICE_INFO 0x06) – данная команда используется вместо удаляемых.

Запрос идентификатора устройства (COMMAND_DEVICE_HARDWARE_ID 0x05 deprecated)
Запрос кода устройства (COMMAND_DEVICE_HARDWARE_CODE 0x01 deprecated)
Запрос внутренней версии ПО устройства (COMMAND_DEVICE_FIRMWARE 0x02 deprecated)
Запрос серийного номера устройства (COMMAND_DEVICE_SERIAL 0x03 deprecated)

Установка режима работы устройства (COMMAND_DEVICE_MODE 0x04 deprecated)

Начать работу с устройством (COMMAND_DEVICE_OPEN 0x08)
Завершить работу с устройством (COMMAND_DEVICE_CLOSE 0x09)
Включение сбора статистики (COMMAND_DEVICE_STAT 0x0A)

Управление каналами

Работать с каналами взаимодействия с шиной возможно после отправки устройству команды начала работы (COMMAND_DEVICE_OPEN 0x08).
Нумерация каналов зависит от выбранного режима работы устройства.
Номер канала задаётся в поле flags заголовка отправляемой команды. Поддерживается работа до 7 каналов.

enum FLAG_CHANNELS {
    FLAG_CHANNEL_1 = 0x20,
    FLAG_CHANNEL_2 = 0x40,
    FLAG_CHANNEL_3 = 0x60,
    FLAG_CHANNEL_4 = 0x80,
    FLAG_CHANNEL_5 = 0xA0,
    FLAG_CHANNEL_6 = 0xC0,
    FLAG_CHANNEL_7 = 0xE0
};

Настройка канала (COMMAND_CHANNEL_CONFIG 0x11 deprecated)
Изменение настроек канала (COMMAND_CHANNEL_OPTION 0x14)
Открытие канала (COMMAND_CHANNEL_OPEN 0x18)
Закрытие канала (COMMAND_CHANNEL_CLOSE 0x19)
Сброс канала (COMMAND_CHANNEL_RESET 0x1F)

Управление аппаратными фильтрами

Настройка фильтров возможна только после открытия канала соединения с шиной. При закрытии канала, фильтры сбрасываются.
Следует учесть, что в зависимости от типа устройства, настройка фильтров может отличаться.

Установить фильтр (COMMAND_FILTER_SET 0x21)
Сбросить фильтр (COMMAND_FILTER_CLEAR 0x22)

Управление пробросом сообщений между каналами

После открытия каналов связи с шинами, можно активировать проброс сообщений между однотипными каналами.

Включить проброс сообщений между каналами (COMMAND_GATEWAY_ON 0x31)
Выключить проброс сообщений между каналами (COMMAND_GATEWAY_OFF 0x32)
Выставить фильтр проброса сообщений между каналами (COMMAND_GATEWAY_FILTER_SET 0x33)
Сбросить фильтр проброса сообщений между каналами (COMMAND_GATEWAY_FILTER_CLEAR 0x34)
Сбросить все фильтры проброса сообщений между каналами (COMMAND_GATEWAY_ALL_CLEAR 0x35)

Взаимодействие с данными в шинах данных

После открытия канала шины данных, устройство начнёт приём данных из шины и отправку сообщений в шину.

Отправка данных в шину

Отправить сообщение в шину (COMMAND_MESSAGE 0x40)

Выставить ответ в шину (COMMAND_SLAVE_RESPONSE_SET 0x4A) для шины LIN
Выставить режим формирования ответа в шину (COMMAND_SLAVE_RESPONSE_MODE 0x4B) для шины LIN deprecated

Приём данных из шины

Получение сообщения из шины (COMMAND_MESSAGE 0x40)
Получение статуса шины (COMMAND_BUS_ERROR 0x48)

Список поддерживаемых команд

Синхронизация (COMMAND_SYNC 0xA5)

Единственная команда, которая не подпадает под стандарт. Используется для инициализации устройства в первоначальное состояние. Происходит закрытие каналов связи с шинами данных, сброс счётчиков и буферов данных. Работа с устройством всегда начинается с отправки данной команды.
Обратите внимание, что данная команда является константой и всегда посылается в одном и том же виде.

Пример

⇒ A5 00 A5 00
⇐ 5A 00 5A 00

Загрузка сертификата лицензии (COMMAND_DEVICE_CERTIFICATE 0x07)

Внутренняя команда сертификации и проверки лицензии на ПО.
Структура данных, которыми обмениваются устройство и ПО вариативна в зависимости от версии прошивки и ПО.

Запрос информации об устройстве (COMMAND_DEVICE_INFO 0x06)

Вместо формирования нескольких запросов для получения информации об устройстве можно отправить единую команду, по которой будет отправлена полная информация о версии прошивки, аппаратного обеспечения, серийном номере и прочее.
Результатом запроса будет массив из uint32_t элементов.

// Если установлен старший бит, то в 0x00FF0000U выставляется количество элементов с дополнительной информацией.
#define DI_MULTIWORD                    0x80000000U

// Информация о типе устройства. Хранится в младшем байте. Возможные значения представлены в HWIdentifiers.
#define DI_HARDWARE_ID                  0x01000000U
// Версия прошивки. Используется с флагом DI_MULTIWORD. Версия прошивки сохраняется в дополнительных элементах 
// в виде ASCII строки, которая ограничивается 0x0 или длиной массива, выделенного под этот параметр.
#define DI_FIRMWARE_VERSION             0x02000000U
// Серийный номер устройства. Используется с флагом DI_MULTIWORD. Серийный номер представлен в бинарном виде.
#define DI_DEVICE_SERIAL                0x03000000U
// Битовая маска поддерживаемых дополнительных функций устройства. Описание ниже.
#define DI_FEATURES                     0x11000000U
// Карта поддерживаемых каналов и их типов. Может использоваться с флагом DI_MULTIWORD. Тогда описание каланов
// располагается в дополнительных элементах. Младший байт отвечает за первый канал, старший за максимальный.
// Без флага DI_MULTIWORD используется 3 младших байта. Описание ниже.
#define DI_CHANNEL_MAP                  0x12000000U
// Доступные опции по каналам.
#define DI_CHANNEL_FEATURES             0x13000000U
// Настройки доступных фильтров по каналам.
#define DI_FILTER                       0x14000000U
// Настройки шлюза по каналам.
#define DI_GATEWAY                      0x15000000U
// Информация, на какой частоте работает CAN/CAN-FD модуль.
#define DI_CHANNEL_FREQUENCY            0x16000000U
// Информация о размере буфера для поддержки протокола ISO-TP.
#define DI_ISOTP                        0x21000000U
// Информация о размере буфера для трейсера.
#define DI_TX_BUFFER                    0x22000000U
// Информация о количестве заданий на периодическую отправку в шину.
#define DI_TX_TASK                      0x23000000U

/**************************************************************************************************/
// DI_HARDWARE_ID - Идентификатор устройства
enum HWIdentifiers {
    HW_CH30     = 0xFF, /* Old identifier for CAN-Hacker on F105 mcu with dual CAN channels and single LIN channel */
    HW_ODB_OLD  = 0x02, /* Old identifier for CAN-Hacker in ODB interface with single CAN channel and single LIN channel */
    HW_CH32     = 0x01, /* CAN-Hacker 3.2 on F105 mcu with dual CAN channels and single LIN channel */
    HW_ODB      = 0x04, /* CAN-Hacker in ODB interface on F105 mcu with single CAN channel and single LIN channel */
    HW_CHP      = 0x03, /* CAN-Hacker CH-P on F105 mcu with dual CAN channels and single LIN channel */
    HW_CH33     = 0x11, /* CAN-Hacker 3.3 on F407 mcu with dual CAN channels and single LIN channel */
    HW_CHPM03   = 0x13, /* CAN-Hacker CH-P on F407 mcu with dual CAN channels and single LIN channel */
    HW_ODB_FD   = 0x14, /* CAN-Hacker in ODB interface on G431 mcu with single CANFD channel and single LIN channel */
    HW_FDL2_M02 = 0x06  /* CAN-Hacker CH-P on G473 mcu with dual CANFD channels and single LIN channel */
    HW_FDL2_M05 = 0x16  /* CAN-Hacker CH-P on G473 mcu with dual CANFD channels and single LIN channel */
};
// Пример: 0x01000001 
// Представление в памяти: 01 00 00 01
// Описание: Идентификатор устройства 0x01, что соответствует HW_CH32.

/**************************************************************************************************/
// DI_FIRMWARE_VERSION - Версия используемой прошивки
// Пример 1: 0x82020000 0x2E322E32 0x00392E30
// Представление в памяти: 00 00 02 82 32 2E 32 2E 30 2E 39 00
// Описание: Содержит версию прошивки 2.2.0.9
// Пример 2: 0x82020000 0x2E322E32 0x30312E30
// Представление в памяти: 00 00 02 82 32 2E 32 2E 30 2E 31 30
// Описание: Содержит версию прошивки 2.2.0.10

/**************************************************************************************************/
// DI_DEVICE_SERIAL - Серийный номер устройства
// Пример: 0x83020000 0x00000000 0x01000000
// Представление в памяти: 00 00 02 83 00 00 00 00 00 00 00 01
// Описание: Серийный номер устройства 00 00 00 00 00 00 00 01

/**************************************************************************************************/
// DI_FEATURES - Флаги доступных функций устройства

// Поддерживается шлюз между каналами. Если данный флаг установлен, то дополнительно будет информация
// о настройках шлюза в DI_GATEWAY.
#define DI_FEATURE_GATEWAY              0x00000001U

// Устройство поддерживает возможность отправки и приёма сообщений в формате ISO-TP (ISO 15765-2).
#define DI_FEATURE_ISOTP                0x00000002U

// Поддерживается буфер передачи данных из трейсера для выдерживания таймингов.
// Если данный флаг установлен, то дополнительно будет информация о размере буфера в DI_TX_BUFFER.
#define DI_FEATURE_TX_BUFFER            0x00000004U

// Поддерживается периодическая отправку данных в шину с заданными интервалами.
// Если данный флаг установлен, то дополнительно будет информация о количестве заданий, которое может 
// обработать устройство в DI_TX_TASK.
#define DI_FEATURE_TX_TASK              0x00000008U

// Пример: 0x11000009
// Представление в памяти: 09 00 00 11
// Описание: Доступны функции шлюза и периодическая отправка на CAN шине.

/**************************************************************************************************/
// DI_CHANNEL_MAP - Карта каналов устройства
enum ChannelTypeEnum {
    CTE_None   = 0x00, /* Канал не используется и дальше ничего нет */
    CTE_CAN    = 0x01,
    CTE_CANFD  = 0x02,
    CTE_LIN    = 0x10
};
// Пример: 0x12100101
// Представление в памяти: 01 01 10 12
// Описание: 3 канала: 1-CAN, 2-CAN и 3-LIN.

/**************************************************************************************************/
// DI_CHANNEL_FEATURES - Доступные опции для канала. Для каждого канала своя запись.

// Маска канала, для которого пришло описание опций. Каналы нумеруются с 1.
#define DI_CHANNEL_CHANNEL_MASK         0x00FF0000U
#define DI_CHANNEL_CHANNEL_SHIFT        16

// На канале есть контроль Arbitration Lost
#define DI_CHANNEL_FEATURE_ALC          0x00000001U
// На канале есть возможность управлять подключением терминирующего резистора для CAN
#define DI_CHANNEL_FEATURE_TERMINATOR   0x00000002U
// На канале есть возможность управлять подтяжкой линии данных для LIN
#define DI_CHANNEL_FEATURE_PULLUP       0x00000004U
// На канале поддерживается определение скорости шины классического CAN
#define DI_CHANNEL_FEATURE_CSD          0x00000008U
// Для LIN шины можно установить задёржку определения IDLE
#define DI_CHANNEL_FEATURE_IDLE         0x00000010U
// На канале поддерживается определение скорости шины CANFD
#define DI_CHANNEL_FEATURE_DSD          0x00000020U
// На канале возможно выставление формата CANFD фреймов в стиле NonISO
#define DI_CHANNEL_FEATURE_NONISO       0x00000040U

// Пример: 0x13010002
// Представление в памяти: 02 00 01 13
// Описание: Для первого канала доступно управление подключением терминирующим резистором.

/**************************************************************************************************/
// DI_FILTER - Настройки фильтров. Для каждого канала может быть несколько посылок.

// Маска канала, для которого пришло описание фильтра. Каналы нумеруются с 1.
#define DI_FILTER_CHANNEL_MASK          0x00FF0000U
#define DI_FILTER_CHANNEL_SHIFT         16

// Маска типа фильтра.
#define DI_FILTER_TYPE_MASK             0x0000FF00U
#define DI_FILTER_TYPE_SHIFT            8
// Фильтр 8 бит
#define DI_FILTER_TYPE_8BIT             0x00000001U
// Фильтр 11 бит
#define DI_FILTER_TYPE_11BIT            0x00000002U
// Фильтр 29 бит
#define DI_FILTER_TYPE_29BIT            0x00000004U

// Маска количества фильтров.
#define DI_FILTER_SIZE_MASK             0x000000FFU
#define DI_FILTER_SIZE_SHIFT            0

// Пример: 0x1401060E
// Представление в памяти: 0E 06 01 14
// Описание: Фильтр для канала 1 в количестве 14 штук, которые являются 11- и 29- битными.
// Пример: 0x1401021С 0x14010408
// Представление в памяти: 1С 02 01 14 08 04 01 14
// Описание: Фильтры для канала 1, где с 0 по 27 являются 11-битрыми, а с 28 по 35 являются 29-битными.

/**************************************************************************************************/
// DI_GATEWAY - Описание возможных пробросов сообщений между каналами и количество фильтров.

// Маска исходного канала (нумерация c 1)
#define DI_GATEWAY_SRC_MASK             0x00FF0000U
#define DI_GATEWAY_SRC_SHIFT            16

// Маска канала назначения (нумерация c 1)
#define DI_GATEWAY_DST_MASK             0x0000FF00U
#define DI_GATEWAY_DST_SHIFT            8

// Маска количества фильтров шлюза
#define DI_GATEWAY_FILTER_MASK          0x000000FFU
#define DI_GATEWAY_FILTER_SHIFT         0

// Пример: 0x15010210
// Представление в памяти: 10 02 01 15
// Описание: Возможен проброс сообщений из канала 1 в канал 2 и установкой 16 фильтров.

/**************************************************************************************************/
// DI_CHANNEL_FREQUENCY - Частота, на которой работает модуль для работы с CAN/CAN-FD, и которую
// необходимо учитывать для расчёта параметров задания скорости шины.
// Пример: 0x15010078
// Представление в памяти: 78 00 01 15
// Описание: Частота работы модуля CAN/CAN-FD на первом канале 120МГц.

/**************************************************************************************************/
// DI_TX_BUFFER - Размер буфера отправки сообщений в шину для трейсера.
// Размер буфера указывается в количестве сообщений, которые будут отправляться с заданными интервалами.
// Пример: 0x22000010
// Представление в памяти: 10 00 00 22
// Описание: Буфер рассчитан на 16 сообщений.

/**************************************************************************************************/
// DI_TX_TASK - Количество ячеек памяти, в которые можно поместить задания на периодическую отправку сообщений.
// Пример: 0x23000010
// Представление в памяти: 10 00 00 23
// Описание: Буфер рассчитан на 16 сообщений.

Запрос

Поле Значение
command 0x06
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Ответ

Поле Значение
header.command 0x06
header.sequence порядковый номер запроса
header.flags 0x00
header.dSize кратное 4 количество байт
data[] данные с информацией об устройстве

Пример

⇒ 06 xx 00 00
⇐ 06 xx 00 38 01 00 00 01 00 00 02 82 32 2E 32 2E 30 2E 39 00 00 00 02 83 00 00 00 00 00 00 00 00 01 00 00 11 01 01 10 12 0E 06 01 14 0E 06 02 14 08 01 03 14 20 02 01 15 20 01 02 15

Запрос идентификатора устройства (COMMAND_DEVICE_HARDWARE_ID 0x05) deprecated

Возвращается идентификатор используемого устройства. Идентификатор зависит от аппаратной составляющей устройства.
В ответе используется структура:

enum HWIdentifiers {
    HW_CH30     = 0xFF, /* Old identifier for CAN-Hacker on F105 mcu with dual CAN channels and single LIN channel */
    HW_ODB_OLD  = 0x02, /* Old identifier for CAN-Hacker in ODB interface with single CAN channel and single LIN channel */
    HW_CH32     = 0x01, /* CAN-Hacker 3.2 on F105 mcu with dual CAN channels and single LIN channel */
    HW_ODB      = 0x04, /* CAN-Hacker in ODB interface on F105 mcu with single CAN channel and single LIN channel */
    HW_CHP      = 0x03, /* CAN-Hacker CH-P on F105 mcu with dual CAN channels and single LIN channel */
    HW_CH33     = 0x11, /* CAN-Hacker 3.3 on F407 mcu with dual CAN channels and single LIN channel */
    HW_CHPM03   = 0x13, /* CAN-Hacker CH-P on F407 mcu with dual CAN channels and single LIN channel */
    HW_ODB_FD   = 0x14, /* CAN-Hacker in ODB interface on G431 mcu with single CAN channel and single LIN channel */
    HW_FDL2_M02 = 0x06, /* CAN-Hacker CH-P on G473 mcu with dual CAN channels and single LIN channel */
    HW_FDL2_M05 = 0x16  /* CAN-Hacker CH-P on G473 mcu with dual CAN channels and single LIN channel */
};

typedef struct {
    CommandHeader header;
    uint8_t hwId;
} __attribute__((packed)) DeviceIdentifier;

Все устройства делятся на группы CH-105/CH-407/CH-4FD.
CH-105 – В своей основе имеют контроллер F105.
CH-407 – В своей основе имеют контроллер F407.
CH-4FD – В своей основе имеют контроллер G4xx.

Запрос

Поле Значение
command 0x05
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Ответ

Поле Значение
header.command 0x05
header.sequence порядковый номер запроса
header.flags 0x00
header.dSize 0x01
hwId 1 байт типа устройства

Пример

⇒ 05 xx 00 00
⇐ 05 xx 00 01 03

Запрос кода устройства (COMMAND_DEVICE_HARDWARE_CODE 0x01) deprecated

Возвращается тип используемого устройства. Например "CH-3.x", "CH-ODB" или "CH-P".

Запрос

Поле Значение
command 0x01
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Ответ

Поле Значение
command 0x01
sequence порядковый номер запроса
flags 0x00
dSize количество байт данных
data[] ответ

Пример
Получение кода устройства CH-P

⇒ 01 xx 00 00
⇐ 01 xx 00 04 43 48 2D 50

Запрос внутренней версии ПО устройства (COMMAND_DEVICE_FIRMWARE 0x02) deprecated

Возвращается в виде текста версия ПО записанного на устройство. Например "0.2.1".

Запрос

Поле Значение
command 0x02
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Ответ

Поле Значение
command 0x02
sequence порядковый номер запроса
flags 0x00
dSize количество байт данных
data[] ответ

Пример

⇒ 02 xx 00 00
⇐ 02 xx 00 05 30 2E 32 2E 31

Запрос серийного номера устройства (COMMAND_DEVICE_SERIAL 0x03) deprecated

Возвращается серийный номер устройства.
В ответе используется структура

typedef struct {
    CommandHeader header;
    uint8_t[8] serial;
} __attribute__((packed)) DeviceSerialNumber;

Запрос

Поле Значение
command 0x03
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Ответ

Поле Значение
header.command 0x03
header.sequence порядковый номер запроса
header.flags 0x00
header.dSize 0x08
serial 8 байт серийного номера

Пример
Получение серийного номера 000000000000002E

⇒ 03 xx 00 00
⇐ 03 xx 00 08 00 00 00 00 00 00 00 2E

Установка режима работы устройства (COMMAND_DEVICE_MODE 0x04) deprecated

Перед тем как начать работу с устройством, необходимо выставить его режим работы. Этот режим задаётся через задание значения в поле flags заголовка запроса.
Допускается использовать следующие значения:

enum FLAG_DEVICE_MODES {
    FLAG_DEVICE_MODE_FULL = 0x00,
    FLAG_DEVICE_MODE_CAN  = 0x01,
    FLAG_DEVICE_MODE_LIN  = 0x02
};

Следует учесть, что при выставлении режима работы FLAG_DEVICE_MODE_CAN, то остаются доступны для работы только каналы отвечающие за работу с CAN. Каналы для работы с LIN не доступны. При выставлении режима работы FLAG_DEVICE_MODE_LIN остаются доступны каналы работы только с LIN и их нумерация начинается с 1.

Запрос

Поле Значение
command 0x04
sequence порядковый номер запроса
flags режим работы устройства
dSize 0x00

Ответ

Поле Значение
command 0x84
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример

⇒ 04 xx 01 00
⇐ 84 xx 00 00

Начать работу с устройством (COMMAND_DEVICE_OPEN 0x08)

Настройки устройства теперь передаются вместе с командой открытия сеанса связи с устройством. Настройки передаются по аналогии с получением информации об устройстве.
Для обратной совместимости с программным обеспечением, использующим наши устройства, временно оставлен механизм старой инициализации устройства. Инициализация устройства с использованием старого механизма настройки приводит к обработке старой структуры данных для отправки данных в шину.
После посылки данной команды, можно формировать команды для настройки каналов взаимодействия с шинами данных.

// Какие каналы доступны для работы
#define DC_MODE                         0x01000000U

/**************************************************************************************************/
// DC_MODE - Какие каналы доступны для работы
enum FLAG_DEVICE_MODES {
    FLAG_DEVICE_MODE_FULL = 0x00,
    FLAG_DEVICE_MODE_CAN  = 0x01,
    FLAG_DEVICE_MODE_LIN  = 0x02
};
// Пример: 0x01000000 
// Представление в памяти: 00 00 00 01
// Описание: Устройство будет использовать все доступные каналы

Запрос

Поле Значение
header.command 0x08
header.sequence порядковый номер запроса
header.flags 0x00
header.dSize кратное 4 количество байт
data[] настройки устройства

Ответ

Поле Значение
command 0x88
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример

Отправка запроса на начало работы с устройством с предварительной настройка на работу с CAN-каналами

⇒ 08 xx 00 04 01 00 00 01
⇐ 88 xx 00 00

Завершить работу с устройством (COMMAND_DEVICE_CLOSE 0x09)

Посылка данной команды автоматически закрывает все каналы работы с шинами данных и сбрасывает все счётчики.

Запрос

Поле Значение
command 0x09
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Ответ

Поле Значение
command 0x89
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример

⇒ 09 xx 00 00
⇐ 89 xx 00 00

Включение сбора статистики (COMMAND_DEVICE_STAT 0xA)

Сбор статистики по загрузке устройства, утилизации внутренних буферов позволяет определить, что является причиной потери данных при приёме/передачи данных. Для этого выводится загрузка процессора, приблизительный процент утилизации CAN-шин (не учитываются служебные биты), а также утилизация буфера приёма данных по USB, утилизация буферов на отправку в CAN-шины и буфер обработки данных.

Управление включением и выключением сбора статистики происходит с использованием выставления флага команде:

enum DEVICE_STAT {
    DEVICE_STAT_OFF  = 0x00,
    EDVICE_STAT_ON   = 0x01
};

После отправки команды на сбор статистики от устройства с интервалами раз в 1 секунду будет приходить статистика в виде набора структур. Данный набор и его последовательность зависят от используемого устройства. Первая структура будет CommandHeader, у которой в поле command будет значение 0x0A (COMMAND_DEVICE_STAT), sequence порядковый номер посылки, dSize будет содержать длину всех передаваемых данных. Ниже представлены возможные структуры, которые будет передавать устройство:

enum DEVICE_STAT_TYPE {
    DEVICE_STAT_CPU_IDLE          = 0x01,
    DEVICE_STAT_PROCESSING_BUFFER = 0x02,
    DEVICE_STAT_CAN_BUFFER        = 0x04,
    DEVICE_STAT_CAN1_LOAD_N       = 0x11,
    DEVICE_STAT_CAN1_LOAD_D       = 0x21,
    DEVICE_STAT_CAN1_MSG_COUNTER  = 0x51,
    DEVICE_STAT_CAN2_LOAD_N       = 0x12,
    DEVICE_STAT_CAN2_LOAD_D       = 0x22,
    DEVICE_STAT_CAN2_MSG_COUNTER  = 0x52
};

typedef struct {              // Загрузка процессора = (1 - Value / MaxValue) * 100
    uint32_t DataType;        // DEVICE_STAT_CPU_IDLE          
    uint32_t MaxValue;        // Максимальное значение IDLE
    uint32_t Value;           // Текущее значение IDLE
} __attribute__((packed)) StatIdle;

typedef struct {              // Утилизация буферов
    uint32_t DataType;        // DEVICE_STAT_PROCESSING_BUFFER, DEVICE_STAT_CAN_BUFFER
    uint32_t QueueSize;       // Общий размер буфера в записях
    uint32_t Utilization;     // Сколько записей в буфере
    uint32_t Lost;            // Сколько записей не было помещено в буфер из-за его переполнения
} __attribute__((packed)) StatBufferLoad;

typedef struct {              // Сколько бит передано в шину, без учёта служебных битов, с момента последней передачи статистики
    uint32_t DataType;        // DEVICE_STAT_CAN1_LOAD_N, DEVICE_STAT_CAN1_LOAD_D, DEVICE_STAT_CAN2_LOAD_N, DEVICE_STAT_CAN2_LOAD_D
    uint32_t Value;
} __attribute__((packed)) StatChannelLoad;

typedef struct {              // Статистика по количеству принятых, отправленных сообщений. Количеству сообщений, которые так и не попали в шину.
    uint32_t DataType;        // DEVICE_STAT_CAN1_MSG_COUNTER, DEVICE_STAT_CAN2_MSG_COUNTER
    uint32_t Received;        // Количество приняты сообщений
    uint32_t ReceiveLost;     // Количество принятых сообщений но не обработанных из-за переполнения буферов
    uint32_t Transmitted;     // Количество отправленных сообщений
    uint32_t TransmitALS;     // Количество сообщений проигравших арбитраж
    uint32_t TransmitRetry;   // Количество попыток перепослать сообщения
    uint32_t TransmitFailed;  // Количество сообщений, которые не были отправлены
} __attribute__((packed)) StatChannelCounter;

Запрос

Поле Значение
command 0x0A
sequence порядковый номер запроса
flags Значение из DEVICE_STAT
dSize 0x00

Ответ

Поле Значение
command 0x8A
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Включение сбора статистики

⇒ 0A xx 01 00
⇐ 8A xx 00 00

Пример статистики, отправляемой CH-P.FDL2

⇐ 0A xx 00 6C 01 00 00 00 00 F4 01 00 CA 85 01 00 02 00 00 00 08 00 00 00 01 00 00 00 00 00 00 00 04 00 00 00 80 00 00 00 02 00 00 00 00 00 00 00 11 00 00 00 5E CD 02 00 21 00 00 00 00 00 00 00 12 00 00 00 5E CD 02 00 22 00 00 00 00 00 00 00

Здесь:
  • StatIdle ( DataType = DEVICE_STAT_CPU_IDLE, MaxValue = 0x0001F400, Value = 0x000185CA ) = Load: 22
  • StatBufferLoad ( DataType = DEVICE_STAT_PROCESSING_BUFFER, QueueSize = 8, Utilization = 1, Lost = 0 )
  • StatBufferLoad ( DataType = DEVICE_STAT_CAN_BUFFER, QueueSize = 128, Utilization = 2, Lost = 0 )
  • StatChannelLoad ( DataType = DEVICE_STAT_CAN1_LOAD_N, Value = 0x0002CD5E )
  • StatChannelLoad ( DataType = DEVICE_STAT_CAN1_LOAD_D, Value = 0 )
  • StatChannelLoad ( DataType = DEVICE_STAT_CAN2_LOAD_N, Value = 0x0002CD5E )
  • StatChannelLoad ( DataType = DEVICE_STAT_CAN2_LOAD_D, Value = 0 )

Настройка канала (COMMAND_CHANNEL_CONFIG 0x11) deprecated

Перед началом работы с каналом для взаимодействия с шиной данных, его необходимо настроить. В зависимости от типа канала доступен разный набор опций.
Общий список возможных опций для настройки:

enum FLAG_CHANNEL_CONFIGS {
    FLAG_CONFIG_BUS_SPEED      = 0x00, // deprecated
    FLAG_CONFIG_BUS_SPEED_FD   = 0x01, // deprecated
    FLAG_CONFIG_BUS_SPEED_M    = 0x02,
    FLAG_CONFIG_BUS_SPEED_FD_M = 0x03,
    FLAG_CONFIG_TERMINATOR     = 0x05,
    FLAG_CONFIG_PULL_UP        = 0x06,
    FLAG_CONFIG_CRC_MODE       = 0x07,
    FLAG_CONFIG_IDLE_DELAY     = 0x08,
    FLAG_CONFIG_MODE           = 0x09,
    FLAG_CONFIG_CAN_FRAME      = 0x0A
};

При отправке команды настройки канала в поле flags необходимо поместить одно из значений перечисления FLAG_CHANNELS и одно из значений FLAG_CHANNEL_CONFIGS.

Для настройки канала, ответственного за работу с шиной CAN, доступны следующие настройки: Для настройки канала, ответственного за работу с шиной LIN, доступны следующие настройки:

Задание скорости взаимодействия с шиной CAN (FLAG_CONFIG_BUS_SPEED 0x00) deprecated

Данная настройка помечена как устаревшая (deprecated).

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

typedef struct {
    CommandHeader header;
    uint8_t speed;
} __attribute__((packed)) ChannelConfigureSpeed;

Здесь в поле speed заносится индекс скорости. На данный момент используется две таблицы скоростей.

Для устройств, которые могу работать с шиной CANFD, используется следующие индексы:

enum nominalCanBitrate {
    NOMINAL_BITRATE_10K = 0,
    NOMINAL_BITRATE_20K,
    NOMINAL_BITRATE_33_3K,
    NOMINAL_BITRATE_50K,
    NOMINAL_BITRATE_62_5K,
    NOMINAL_BITRATE_83_3K,
    NOMINAL_BITRATE_95_2K,
    NOMINAL_BITRATE_100K,
    NOMINAL_BITRATE_125K,
    NOMINAL_BITRATE_250K,
    NOMINAL_BITRATE_400K,
    NOMINAL_BITRATE_500K,
    NOMINAL_BITRATE_800K,
    NOMINAL_BITRATE_1000K,
};

Для взаимодействия с классической CAN шиной используются следующие индексы:
enum canBitrate {
    CAN_BITRATE_10K = 0,
    CAN_BITRATE_20K,
    CAN_BITRATE_33_3K,
    CAN_BITRATE_50K,
    CAN_BITRATE_62_5K,
    CAN_BITRATE_83_3K,
    CAN_BITRATE_95K,
    CAN_BITRATE_100K,
    CAN_BITRATE_125K,
    CAN_BITRATE_250K,
    CAN_BITRATE_400K,
    CAN_BITRATE_500K,
    CAN_BITRATE_800K,
    CAN_BITRATE_1000K
};

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_BUS_SPEED
header.dSize 0x01
speed значение из canBitrate или nominalCanBitrate, в зависимости от типа устройства

Ответ
Если запрос успешно обработан и значение индекса скорости в поле speed задано из допустимого диапазона значений.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Настройка CAN канала 2 на скорость 20Кбит.

⇒ 11 xx 40 01 01
⇐ 91 xx 00 00

Настройка CAN канала 2 с заданием неверного индекса скорости.

⇒ 11 xx 40 01 10
⇐ FF xx 00 00

Задание скорости передачи данных на шине CANFD (FLAG_CONFIG_BUS_SPEED_FD 0x01) deprecated

Данная настройка помечена как устаревшая (deprecated).

Для настройки скорости передачи данных канала устройства, подключенного к шине CANFD, используется структура:

typedef struct {
    CommandHeader header;
    uint8_t speed;
} __attribute__((packed)) ChannelConfigureSpeed;

Здесь в поле speed заносится индекс предзаданной скорости.

enum dataCanBitrate {
    DATA_BITRATE_500K = 0,
    DATA_BITRATE_1000K,
    DATA_BITRATE_2000K,
    DATA_BITRATE_4000K,
    DATA_BITRATE_5000K
};

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_BUS_SPEED_FD
header.dSize 0x01
speed значение из dataCanBitrate

Ответ
Если запрос успешно обработан и значение индекса скорости в поле speed задано из допустимого диапазона значений.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Настройка канала 2 на скорость данных 1000Кбит.

⇒ 11 xx 41 01 01
⇐ 91 xx 00 00

Настройка канала 2 с заданием неверного индекса скорости.

⇒ 11 xx 41 01 10
⇐ FF xx 00 00

Ручное задание скорости взаимодействия с шиной CAN (FLAG_CONFIG_BUS_SPEED_M 0x02) deprecated

Для ручного задания скорости канала устройства используется структура:

typedef struct {
    uint16_t Prescaler;
    uint16_t tqSeg1;
    uint16_t tqSeg2;
    uint16_t SyncJW;
} __attribute__((packed)) BusCustomBaudRate;

typedef struct {
    CommandHeader header;
    BusCustomBaudRate speed;
} __attribute__((packed)) ChannelConfigureCustomSpeed;

Для устройств, в названии которых есть идентификатор FD, расчёт ведётся исходя из частоты 120МГц, для остальных устройств из линейки CAN-Hacker расчёт ведётся исходя из скорости 36МГц.

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_BUS_SPEED_M
header.dSize 0x08
speed.Prescaler 2 байта
speed.tqSeg1 2 байта
speed.tqSeg2 2 байта
speed.SyncJW 2 байта

Ответ
Если запрос успешно обработан и значения полей структуры в поле speed заданы из диапазона допустимых величин.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Настройка канала 1 на скорость 200Кбит с частотой CAN в 36МГц ( Prescaler = 10, tqSeg1 = 15, tqSeg2 = 2, SyncJW = 1 ).

⇒ 11 xx 22 08 0A 00 0F 00 02 00 01 00
⇐ 91 xx 00 00

Настройки канала 1 с заданием одного из полей неправильным значением ( например, SyncJW = 16384\0x4000 ).

⇒ 11 xx 22 08 0A 00 0F 00 02 00 00 40
⇐ FF xx 00 00

Ручное задание скорости передачи данных на шине CANFD (FLAG_CONFIG_BUS_SPEED_FD_M 0x03) deprecated

Для ручного задания скорости передачи данных канала устройства, подключенного к шине CANFD, используется структура:

typedef struct {
    uint16_t Prescaler;
    uint16_t tqSeg1;
    uint16_t tqSeg2;
    uint16_t SyncJW;
} __attribute__((packed)) BusCustomBaudRate;

typedef struct {
    CommandHeader header;
    BusCustomBaudRate speed;
} __attribute__((packed)) ChannelConfigureCustomSpeed;

Расчёт ведётся исходя из частоты 120МГц.

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_BUS_SPEED_M
header.dSize 0x08
speed.Prescaler 2 байта
speed.tqSeg1 2 байта
speed.tqSeg2 2 байта
speed.SyncJW 2 байта

Ответ
Если запрос успешно обработан и значения полей структуры в поле speed заданы из диапазона допустимых величин.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Настройка канала 1 на скорость передачи данных в 2000Кбит с частотой CAN в 120МГц ( Prescaler = 6, tqSeg1 = 7, tqSeg2 = 2, SyncJW = 1 ).

⇒ 11 xx 23 08 06 00 07 00 02 00 01 00
⇐ 91 xx 00 00

Подключить терминирующий резистор (FLAG_CONFIG_TERMINATOR 0x05) deprecated

Некоторые устройства позволяют задействовать терминирующий резистор на 120Ом между линиями CAN-H и CAN-L. В таком случае используется данная настройка со следующей структурой обмена данных:

enum TERMINATOR_STATES {
    CAN_TERMINATOR_OFF  = 0x00,
    CAN_TERMINATOR_ON   = 0x01
};

typedef struct {
    CommandHeader header;
    uint8_t state;
} __attribute__((packed)) ChannelConfigureTerminator;

Данная настройка доступна для устройств с идентификаторами HW_CHP (0x03), HW_CHPM03 (0x13) и HW_FDL2 (0x06). Если устройство не поддерживает данную настройку, то ответ будет содержать 0xFF в поле с номером команды.

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_TERMINATOR
header.dSize 0x01
state значение из TERMINATOR_STATES

Ответ
Если запрос успешно обработан и значение состояния терминатора задано из допустимого диапазона значений.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Подключение терминатора для канала 2.

⇒ 11 xx 45 01 01
⇐ 91 xx 00 00

Задание состояния терминатора для канала 2 с неправильным значением.

⇒ 11 xx 45 01 10
⇐ FF xx 00 00

Режим взаимодействия с шиной (FLAG_CONFIG_MODE 0x09) deprecated

Можно указать режим работы с CAN шиной: активный режим (Normal), когда доступен и приём и передача данных, или пассивный режим (Listen only), когда устройство только слушает шину данных. Для некоторых устройств доступен режим петли, когда канал не подключается к шине, а отправленные данные сразу попадают на вход.
Для настройки данного параметра используется следующая структура:

enum CHANNEL_MODES {
    MODE_NORMAL   = 0x00,
    MODE_LISTEN   = 0x01,
    MODE_LOOPBACK = 0x02
};

typedef struct {
    CommandHeader header;
    uint8_t mode;
} __attribute__((packed)) ChannelConfigureMode;

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_MODE
header.dSize 0x01
mode значение из CHANNEL_MODES

Ответ
Если запрос успешно обработан и значение режима работы канала задано из допустимого диапазона значений.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Задание режима работы канала 1 в режиме только прослушивания шины

⇒ 11 xx 29 01 01
⇐ 91 xx 00 00

Задание режима работы канала 1 с неправильным значением.

⇒ 11 xx 29 01 05
⇐ FF xx 00 00

Задание скорости взаимодействия с шиной (FLAG_CONFIG_BUS_SPEED 0x00) deprecated

Данная настройка помечена как устаревшая (deprecated).

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

typedef struct {
    CommandHeader header;
    uint8_t speed;
} __attribute__((packed)) ChannelConfigureSpeed;

Здесь в поле speed заносится индекс предзаданной скорости.
Доступны следующие значения:
enum LIN_BITRATE {
    LIN_BITRATE_2400 = 0,
    LIN_BITRATE_9600,
    LIN_BITRATE_10400,
    LIN_BITRATE_14400,
    LIN_BITRATE_15600,
    LIN_BITRATE_19200,
    LIN_BITRATE_20000,
    LIN_BITRATE_38400
};

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_BUS_SPEED
header.dSize 0x01
speed значение из LIN_BITRATE

Ответ
Если запрос успешно обработан и значение индекса скорости в поле speed задано из допустимого диапазона значений.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Настройка канала 3 на скорость 19200 бит.

⇒ 11 xx 60 01 05
⇐ 91 xx 00 00

Настройка канала 3 с заданием неверного индекса скорости.

⇒ 11 xx 60 01 10
⇐ FF xx 00 00

Ручное задание скорости взаимодействия с шиной LIN (FLAG_CONFIG_BUS_SPEED_M 0x02) deprecated

Для ручного задания скорости канала устройства используется структура:

typedef struct {
    uint16_t Prescaler;
    uint16_t tqSeg1;
    uint16_t tqSeg2;
    uint16_t SyncJW;
} __attribute__((packed)) BusCustomBaudRate;

typedef struct {
    CommandHeader header;
    BusCustomBaudRate speed;
} __attribute__((packed)) ChannelConfigureCustomSpeed;

ПРи задании пользовательской скорости учитывается значение поля Prescaler, в который и передаётся значение требуемой скорости. Остальные поля должны быть равны 0.

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_BUS_SPEED_M
header.dSize 0x08
speed.Prescaler 2 байта
speed.tqSeg1 2 байта
speed.tqSeg2 2 байта
speed.SyncJW 2 байта

Ответ
Если запрос успешно обработан и значения полей структуры в поле speed заданы из диапазона допустимых величин.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Настройка LIN канала 1 на скорость 19200бит.

⇒ 11 xx 22 08 00 4B 00 00 00 00 00 00
⇐ 91 xx 00 00

Подтяжка шины данных (FLAG_CONFIG_PULL_UP 0x06) deprecated

Некоторые устройства позволяют подтягивать шину данных LIN к +12В. В таком случае используется данная настройка со следующей структурой обмена данных:

enum PULL_UP_STATES {
    LIN_PULL_UP_OFF  = 0x00,
    LIN_PULL_UP_ON   = 0x01
};

typedef struct {
    CommandHeader header;
    uint8_t state;
} __attribute__((packed)) ChannelConfigurePullUp;

Данная настройка доступна для устройств с идентификаторами HW_CHP (0x03), HW_CHPM03 (0x13) и HW_FDL2 (0x06). Если устройство не поддерживает данную настройку, то ответ будет содержать 0xFF в поле с номером команды.

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_PULL_UP
header.dSize 0x01
state значение из PULL_UP_STATES

Ответ
Если запрос успешно обработан и значение подтяжки задано из допустимого диапазона значений.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Подтяжка шины данных к +12В для канала 3.

⇒ 11 xx 66 01 01
⇐ 91 xx 00 00

Задание подтяжки шины данных для канала 3 с неправильным значением.

⇒ 11 xx 66 01 10
⇐ FF xx 00 00

Задание режима расчёта контрольной суммы (FLAG_CONFIG_CRC_MODE 0x07) deprecated

Для каналов, отвечающих за работу с шиной LIN можно задать тип контрольной суммы, используемой для отправки данных в шину. Для данной настройки используется структура:

enum CRC_MODES {
    LIN_CRC_MODE_CLASSIC   = 0x00,
    LIN_CRC_MODE_ENCHANCED = 0x01
};

typedef struct {
    CommandHeader header;
    uint8_t mode;
} __attribute__((packed)) ChannelConfigureCRCMode;

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_CRC_MODE
header.dSize 0x01
mode значение из CRC_MODES

Ответ
Если запрос успешно обработан и значение вида контрольной суммы задано из допустимого диапазона значений.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Задание расчёта классической контрольной суммы для канала 2.

⇒ 11 xx 47 01 00
⇐ 91 xx 00 00

Задание вида расчёта контрольной суммы для канала 2 с неправильным значением.

⇒ 11 xx 47 01 10
⇐ FF xx 00 00

Задержка обработки сигнала IDLE (FLAG_CONFIG_IDLE_DELAY 0x08) deprecated

Иногда случается, что при мониторинге взаимодействия Master и Slave устройства последнее отвечает с задержкой, большей чем предусматривает стандарт. Поэтому мы предусмотрели возможность установить задержку по обработке сигнала IDLE, возникающего на шине. Для настройки данного параметра используется структура:

enum LIN_IDLE_DELAY {
    LIN_IDLE_DELAY_None = 0,
    LIN_IDLE_DELAY_100us,
    LIN_IDLE_DELAY_200us,
    LIN_IDLE_DELAY_250us,
    LIN_IDLE_DELAY_500us,
    LIN_IDLE_DELAY_750us,
    LIN_IDLE_DELAY_1000us,
    LIN_IDLE_DELAY_1500us,
    LIN_IDLE_DELAY_2000us
};
typedef struct {
    CommandHeader header;
    uint8_t delay;
} __attribute__((packed)) ChannelConfigureIdleDelay;

Здесь в поле delay заносится значение индекса задержки.

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x + FLAG_CONFIG_IDLE_DELAY
header.dSize 0x01
delay значение из LIN_IDLE_DELAY

Ответ
Если запрос успешно обработан и значение индекса задержки в поле delay задано из допустимого диапазона значений.

Поле Значение
command 0x91
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Настройка задержки обработки IDLE в канале 3 на 1000 микросекунд.

⇒ 11 xx 68 01 06
⇐ 91 xx 00 00

Настройка канала 3 с заданием неверного индекса задержки обработки IDLE.

⇒ 11 xx 68 01 10
⇐ FF xx 00 00

Изменение настроек канала (COMMAND_CHANNEL_OPTION 0x14)

Некоторые настройки канала можно выставлять как до открытия соединения, так и после. Для этого введена данная команда. Каждая опция может выставляться отдельно или же скопом. Описание схоже с получением информации об устройстве.
Пакет принимает следующий вид:

typedef struct {
    CommandHeader header;
    uint32_t options[];
} __attribute__((packed)) ChannelOptions;

// Включить или выключить терминатор
#define CHANNEL_OPT_CAN_TERMINATOR      0x01000000U

// Включить или выключить отслеживание проигрыша арбитража
#define CHANNEL_OPT_CAN_ALS_CONTROL     0x02000000U

// Включить ии выключить подтяжку линии LIN к +12В
#define CHANNEL_OPT_LIN_PULLUP          0x11000000U

// Включить или выключить расширенный расчёт CRC
#define CHANNEL_OPT_LIN_ENHANCED_CRC    0x12000000U

// Перевести устройство в режим ведомомго устройства
#define CHANNEL_OPT_LIN_SLAVE_MODE      0x13000000U

Все эти опции принимают 1 или 0 в младшем байте опции.

Запрос

Поле Значение
header.command 0x11
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x
header.dSize длина кратная 4 байтам
options набор включаемых или отключаемых опций

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

Поле Значение
command 0x94
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Включение терминирующего резистора и контроля арбитража на втором канале CAN.

⇒ 11 xx 40 08 01 00 00 01 01 00 00 02
⇐ 91 xx 00 00

Открытие канала (COMMAND_CHANNEL_OPEN 0x18)

Доступна настройка канала в момент его открытия. Настройки передаются по аналогии с получением информации об устройстве.
Для обратной совместимости с программным обеспечением, использующим наши устройства, временно оставлен старой механизм настройки каналов.
После посылки данной команды начнётся обмен данными с шиной.

// Используемые структуры

typedef struct {
    uint16_t Prescaler;
    uint16_t tqSeg1;
    uint16_t tqSeg2;
    uint16_t SyncJW;
} __attribute__((packed)) BusCustomBaudRate;

// Если установлен старший бит, то в 0x00FF0000U выставляется количество элементов с дополнительной информацией.
#define CC_MULTIWORD           0x80000000U

// Выставление номинальной скорости канала
#define CC_BUS_SPEED_N         0x01000000U
// Выставление скорости канала для данных. Применимо для CAN-FD
#define CC_BUS_SPEED_D         0x02000000U
// Режим работы CAN/CAN-FD канала
#define CC_CAN_MODE            0x11000000U
// Режим отправки данных в CAN-FD шину
#define CC_CAN_FRAME           0x12000000U
// Автоматически переотправлять сообщения, которые не ушли в шину. 
// Отслеживание идёт на уровне процессора, что может привести к зависанию аппаратного модуля CAN, если не шине не будет принимающих узлов
// не в режиме слушателя.
#define CC_CAN_RETRANSMIT      0x13000000U
// Настройка формата отправляемых сообщений: ISO/NonISO. Доступно в прошивке с версей 2.2.4 или новее.
#define CC_CAN_FRAME_FORMAT    0x14000000U
// Зедержка перевода LIN шины в состояния IDLE.
#define CC_LIN_IDLE_DELAY      0x21000000U

/**************************************************************************************************/
// CC_BUS_SPEED_N - Задание номинальной скорости CAN
// Данная настройка может принимать индекс заранее предопределённой скорости шины и настройки скорости шины исходя из типа используемого устройства
// (36МГц для устройств с классическим CAN / 120МГц для устройств, поддерживающих CAN-FD).
// Для использования индекса скорости флаг CC_MULTIWORD не выставляется и в младшем байте задаётся индекс скорости из следующего перечисления:
enum nominalCanBitrate {
    NOMINAL_BITRATE_10K = 0,
    NOMINAL_BITRATE_20K,
    NOMINAL_BITRATE_33_3K,
    NOMINAL_BITRATE_50K,
    NOMINAL_BITRATE_62_5K,
    NOMINAL_BITRATE_83_3K,
    NOMINAL_BITRATE_95_2K,
    NOMINAL_BITRATE_100K,
    NOMINAL_BITRATE_125K,
    NOMINAL_BITRATE_250K,
    NOMINAL_BITRATE_400K,
    NOMINAL_BITRATE_500K,
    NOMINAL_BITRATE_800K,
    NOMINAL_BITRATE_1000K,
    NOMINAL_BITRATE_DETECT = 0xFF // Если канал поддерживает механизм определения скорости шины
};
// При выставлении флага DI_MULTIWORD в следующем байте за старшим ожидается указани длины данных в 32-битных словах.
// При этом в следующих словах ожидается структура BusCustomBaudRate.
// Пример: 0x0100000B
// Представление в памяти: 0B 00 00 01
// Описание: Задать предопределённую скорость в 500кб/с.
// Пример: 0x81020000 0x000F0004 0x00010002
// Представление в памяти: 00 00 02 81 04 00 0F 00 02 00 01 00 
// Описание: Задать скорость в 500кб/с для устройства с классическим CAN. 
// Здесь Prescaler = 4 / tqSeg1 = 15 / tqSeg2 = 2 / SyncJW = 1

/**************************************************************************************************/
// CC_BUS_SPEED_D - Задание скорости данных для CAN-FD
// Данная настройка может принимать индекс заранее предопределённой скорости шины и настройки скорости шины исходя из частоты 120МГц.
// Для использования индекса скорости флаг CC_MULTIWORD не выставляется и в младшем байте задаётся индекс скорости из следующего перечисления:
enum dataCanBitrate {
    DATA_BITRATE_500K = 0,
    DATA_BITRATE_1000K,
    DATA_BITRATE_2000K,
    DATA_BITRATE_4000K,
    DATA_BITRATE_5000K
};
// При выставлении флага DI_MULTIWORD в следующем байте за старшим ожидается указани длины данных в 32-битных словах.
// При этом в следующих словах ожидается структура BusCustomBaudRate.
// Пример: 0x02000002
// Представление в памяти: 02 00 00 02
// Описание: Задать предопределённую скорость в 2000кб/с для данных.
// Пример: 0x82020000 0x00070006 0x00010002
// Представление в памяти: 00 00 02 82 06 00 07 00 02 00 01 00 
// Описание: Задать скорость в 500кб/с для устройства с классическим CAN. 
// Здесь Prescaler = 6 / tqSeg1 = 7 / tqSeg2 = 2 / SyncJW = 1

/**************************************************************************************************/
// CC_CAN_MODE - режим работы канала
// Активный режим (Normal), когда доступен и приём и передача данных, или пассивный режим (Listen only), 
// когда устройство только слушает шину данных. Значение режима передаётся в младшем байте.
enum CHANNEL_MODES {
    MODE_NORMAL   = 0x00,
    MODE_LISTEN   = 0x01,
    MODE_LOOPBACK = 0x02
};
// Пример: 0x11000001
// Представление в памяти: 01 00 00 11
// Описание: Канал настроен в режиме только прослушивания шины.

/**************************************************************************************************/
// CC_CAN_FRAME - режим отправки данных в шину.
// Для устройств, поддерживающих работу с CAN-FD можно указать режим отправки данных в шину. 
// Значение режима передаётся в младшем байте.
enum CHANNEL_CAN_FRAME {
    CAN_FRAME_CLASSIC    = 0x00,
    CAN_FRAME_FDF_NO_BRS = 0x01,
    CAN_FRAME_FDF_BRS    = 0x02
};
// Пример: 0x12000002
// Представление в памяти: 02 00 00 12
// Описание: Канал настроен в режиме передачи данных с переключением скорости.

/**************************************************************************************************/
// CC_CAN_RETRANSMIT - перепосылка данных
// Можно включить механизм автоматической, на уровне "железа", перепосылки сообщения в шину, если не 
// пришло подтверждения получения сообщения другим устройством на шине. 
// Не рекомендуется использовать, тк это может заблокировать отправку сообщений в шину.
// Включается/отключается настройка выставлением младшего бита в младшем байте.
// Пример: 0x13000001
// Представление в памяти: 01 00 00 13
// Описание: Включить автоматическую перепосылку сообщений в шину.

/**************************************************************************************************/
// CC_CAN_FRAME_FORMAT - формат передаваемых данных в шину
// Начиная с прошивки 2.2.4 есть возможность включения передачи данных для CAN-FD в формате Bosch
// Specification v1.0 (NonISO);
// Включается/отключается настройка выставлением младшего бита в младшем байте.
// Пример: 0x14000001
// Представление в памяти: 01 00 00 14
// Описание: Включить передачу данных в шину в формате NonISO.

/**************************************************************************************************/
// CC_BUS_SPEED_N - Задание номинальной скорости LIN
// Для LIN шины скорость задаётся в двух младших байтах
// Пример: 0x01004B00
// Представление в памяти: 00 4B 00 01
// Описание: Задание скорости LIN шины в 19200 б/с

/**************************************************************************************************/
// CC_LIN_IDLE_DELAY - задержка перевода LIN шины в состояние IDLE
// В младшем байте передаётся индекс предопределённого значения из списка
enum LIN_IDLE_DELAY {
    LIN_IDLE_DELAY_None = 0,
    LIN_IDLE_DELAY_100us,
    LIN_IDLE_DELAY_200us,
    LIN_IDLE_DELAY_250us,
    LIN_IDLE_DELAY_500us,
    LIN_IDLE_DELAY_750us,
    LIN_IDLE_DELAY_1000us,
    LIN_IDLE_DELAY_1500us,
    LIN_IDLE_DELAY_2000us
};
// Пример: 0x21000003
// Представление в памяти: 03 00 00 21
// Описание: Перевод шины LIN в состояние IDLE через 250 мкс.

Запрос

Поле Значение
command 0x18
sequence порядковый номер запроса
flags FLAG_CHANNEL_x
header.dSize кратное 4 количество байт
data[] настройки канала

Ответ

Поле Значение
command 0x98
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Открытие канала 1 с CAN-FD и BRS на скорости 500/2000.

⇒ 18 xx 20 20 00 00 00 11 02 00 00 12 00 00 02 81 0F 00 0C 00 03 00 01 00 00 00 02 82 06 00 07 00 02 00 01 00
⇐ 98 xx 00 00

Открытие канала 1 с CAN-FD и BRS на скорости 500/2000 с предопределёнными индексами скоростей.

⇒ 18 xx 20 20 00 00 00 11 02 00 00 12 0B 00 00 01 02 00 00 02
⇐ 98 xx 00 00

Открытие канала 2 с классическим CAN и скорость 500 кб/с на устройстве, поддерживающем CAN-FD.

⇒ 18 xx 40 14 00 00 00 11 00 00 00 12 00 00 02 81 0F 00 0C 00 03 00 01 00
⇐ 98 xx 00 00

Попытка открытия канала 5, который не предусмотрен в устройстве, с классическим CAN на скорости 500кб/с.

⇒ 18 xx A0 08 01 00 00 11 0B 00 00 01
⇐ FF xx 00 00

Закрытие канала (COMMAND_CHANNEL_OPEN 0x19)

Закрытие канала сбрасывает аппаратные фильтры, назначенные для закрываемого канала.

Запрос

Поле Значение
command 0x19
sequence порядковый номер запроса
flags FLAG_CHANNEL_x
dSize 0x00

Ответ

Поле Значение
command 0x99
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Закрытие канала 1.

⇒ 19 xx 20 00
⇐ 99 xx 00 00

Попытка закрытия канала 5, который не предусмотрен в устройстве.

⇒ 18 xx A0 00
⇐ FF xx 00 00

Сброс канала (COMMAND_CHANNEL_RESET 0x1F)

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

Запрос

Поле Значение
command 0x1F
sequence порядковый номер запроса
flags FLAG_CHANNEL_x
dSize 0x00

Ответ

Поле Значение
command 0x9F
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Сброс канала 1.

⇒ 1F xx 20 00
⇐ 9F xx 00 00

Установить фильтр (COMMAND_FILTER_SET 0x21)

В зависимости от типа устройства реализуются разные механизмы по настройке фильтров.
Для устройств группы CH-105/CH-407 (2 CAN + 1 LIN) доступно: CAN – 14 фильтров (11/29 бит); LIN – 8 фильтров (8 бит).
Для устройств группы CH-105/CH-407 (CAN + LIN) доступно: CAN – 28 фильтров (11/29 бит); LIN – 8 фильтров (8 бит).
Для устройств группы CH-4FD (2 CAN + 1 LIN) доступно: CAN – 28 фильтров 11 бит + 8 фильтров 29 бит; LIN – 8 фильтров (8 бит).

Для установки фильтра используется структура:

enum FLAG_FILTER_TYPE {
    FLAG_FILTER_TYPE_29BIT   = 0x01
};

typedef struct {
    uint32_t number;
    uint32_t type;
    uint32_t id;
    uint32_t mask;
} __attribute__((packed)) FilterStruct;

typedef struct {
    CommandHeader header;
    FilterStruct filter;
} __attribute__((packed)) FilterSet;

Здесь в поле filter.number передаётся порядковый номер фильтра для канала. Нумерация идёт от 0. Канал задаётся в поле header.flag. В поле filter.type задаётся тип фильтра.

Запрос

Поле Значение
header.command 0x21
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x
header.dSize 0x10
filter.number порядковый номер фильтра для канала
filter.type тип фильтра из FLAG_FILTER_TYPE
filter.id идентификатор, по которому идёт фильтрация
filter.mask маска для отбрасывания битов, не участвующих в фильтрации

Ответ
Если запрос успешно обработан и номер фильтра задан из допустимого диапазона значений.

Поле Значение
command 0xA1
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Настройка фильтра 2 для второго канала для сообщения 11 бит для фильтрации сообщений с номерами 0x01* (0x010/0x7F0).

⇒ 21 xx 40 10 01 00 00 00 00 00 00 00 10 00 00 00 F0 07 00 00
⇐ A1 xx 00 00

Настройка канала 2 с заданием неверного индекса фильтра.

⇒ 21 xx 40 10 33 00 00 00 00 00 00 00 10 00 00 00 F0 07 00 00
⇐ FF xx 00 00

Сбросить фильтр (COMMAND_FILTER_CLEAR 0x22)

Как только на канал будут сброшены все фильтры, то канал работает на пропуск всех сообщений с шины.

Для сброса фильтра используется структура:

typedef struct {
    CommandHeader header;
    uint32_t number;
} __attribute__((packed)) FilterClear;

Здесь в поле number передаётся порядковый номер фильтра для канала. Нумерация идёт от 0. Канал фильтра задаётся в поле header.flag.

Запрос

Поле Значение
header.command 0x22
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x
header.dSize 0x04
number порядковый номер фильтра для канала

Ответ
Если запрос успешно обработан и номер фильтра задан из допустимого диапазона значений.

Поле Значение
command 0xA2
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Сброс фильтра 2 для второго канала.

⇒ 22 xx 40 04 01 00 00 00
⇐ A2 xx 00 00

Сброс фильтра канала 2 с заданием неверного индекса фильтра.

⇒ 22 xx 40 04 33 00 00 00
⇐ FF xx 00 00

Включить проброс сообщений между каналами (COMMAND_GATEWAY_ON 0x31)

Включение проброса сообщений между CAN и CANFD каналами устройства. Данную команду можно выполнить только после открытия двух каналов. При включении проброса между каналами мы можем указать между какими каналами осуществлять проброс и правило фильтрации по умолчанию (пропускать все сообщения кроме указанных в фильтре или блокировать все сообщения кроме указанных фильтре).
По сравнению с первой версией протокола здесь поменялись флаги, отвечающие за настройку проброса сообщений:

enum FLAG_GW_SRC_CHANNELS {
    FLAG_GW_SRC_CHANNEL_1 = 0x02,
    FLAG_GW_SRC_CHANNEL_2 = 0x04,
    FLAG_GW_SRC_CHANNEL_3 = 0x06,
    FLAG_GW_SRC_CHANNEL_4 = 0x08,
    FLAG_GW_SRC_CHANNEL_5 = 0x0A,
    FLAG_GW_SRC_CHANNEL_6 = 0x0C,
    FLAG_GW_SRC_CHANNEL_7 = 0x0E
};

enum FLAG_GW_DST_CHANNELS {
    FLAG_GW_DST_CHANNEL_1 = 0x20,
    FLAG_GW_DST_CHANNEL_2 = 0x40,
    FLAG_GW_DST_CHANNEL_3 = 0x60,
    FLAG_GW_DST_CHANNEL_4 = 0x80,
    FLAG_GW_DST_CHANNEL_5 = 0xA0,
    FLAG_GW_DST_CHANNEL_6 = 0xC0,
    FLAG_GW_DST_CHANNEL_7 = 0xE0
};

#define FLAG_GATEWAY_DEFAULT_ACCEPT = 0x01; // Если установить во флагах, то по умолчанию пробрасываем все сообщения.

Проброс можно включить между CAN и CANFD каналами. В итоге, если сообщение пробрасывается из CANFD в CAN, то длина сообщения обрезается под размер сообщения классического CAN. При пробросе сообщений из CAN в CANFD сообщение остаётся неизменным только к флагам отправки в CANFD добавляются флаги его настройки: FDF и BRS, если CANFD настроен с переключением скоростей.

Запрос

Поле Значение
command 0x31
sequence порядковый номер запроса
flags FLAG_GW_DST_CHANNEL_x — номер канала, в который будет происходить проброс сообщений; FLAG_GW_SRC_CHANNEL_x — номер канала, из которого будут обрабатываться сообщения; FLAG_GATEWAY_DEFAULT_ACCEPT
dSize 0x00

Ответ

Поле Значение
command 0xB1
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Включение проброса сообщений из канала 1 в канал 2.

⇒ 31 xx 43 00
⇐ B1 xx 00 00

Попытка включения проброса сообщений из несуществующего канала.

⇒ 31 xx A1 00
⇐ FF xx 00 00

Выключить проброс сообщений между каналами (COMMAND_GATEWAY_OFF 0x32)

Выключение проброса сообщений между CAN и CANFD каналами устройства.

Запрос

Поле Значение
command 0x32
sequence порядковый номер запроса
flags FLAG_GW_DST_CHANNEL_x + FLAG_GW_CSRC_HANNEL_x — номера каналов, между которыми отключить проброс сообщений
dSize 0x00

Ответ

Поле Значение
command 0xB1
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Выключение проброса сообщений из канала 1 в канал 2.

⇒ 32 xx 24 00
⇐ B2 xx 00 00

Попытка выключения проброса сообщений из несуществующего канала.

⇒ 32 xx A0 00
⇐ FF xx 00 00

Выставить фильтр проброса сообщений между каналами (COMMAND_GATEWAY_FILTER_SET 0x33)

В зависимости от настроек проброса сообщений между каналами выставляемые фильтры либо блокируют сообщения, либо пропускают. Для настройки фильтров используются те же структуры, что и для аппаратных фильтров: FilterSet и FilterStruct.
На данный момент можно задать фильтрацию по Id и маске. На каждое направление проброса можно задать по 32 записи с фильтрами сообщений.

Запрос

Поле Значение
header.command 0x33
header.sequence порядковый номер запроса
header.flags FLAG_GW_DST_CHANNEL_x + FLAG_GW_SRC_CHANNEL_x
header.dSize 0x10
filter.number порядковый номер фильтра для пары DST channel + SRC channel
filter.type тип фильтра из FLAG_FILTER_TYPE
filter.id идентификатор, по которому идёт фильтрация
filter.mask маска для отбрасывания битов, не участвующих в фильтрации

Сбросить фильтр проброса сообщений между каналами (COMMAND_GATEWAY_FILTER_CLEAR 0x34)

Структура сброса фильтра аналогична сбросу аппаратного фильтра.

Запрос

Поле Значение
header.command 0x34
header.sequence порядковый номер запроса
header.flags FLAG_GW_DST_CHANNEL_x + FLAG_GW_SRC_CHANNEL_x
header.dSize 0x04
number порядковый номер фильтра для канала

Сбросить все фильтры проброса сообщений между каналами (COMMAND_GATEWAY_ALL_CLEAR 0x35)

Вместо сброса фильтров проброса сообщений между каналами по одному, можно их сбросить сразу все, заполнив соответствующим образом структуру CommandHeader.

Запрос

Поле Значение
command 0x35
sequence порядковый номер запроса
flags FLAG_GW_DST_CHANNEL_x + FLAG_GW_SRC_CHANNEL_x
dSize 0x00

Отправить сообщение в шину (COMMAND_MESSAGE 0x40)

По сравнению с первой версией протокола данная команда претерпела ряд изменений в передаваемых данных устройству для передачи в шину данных. Теперь отправка сообщений происходит с использованием следующей структуры:

enum FLAG_MESSAGE_CHANNELS {
    FLAG_MESSAGE_CHANNEL_1 = 0x2000,
    FLAG_MESSAGE_CHANNEL_2 = 0x4000,
    FLAG_MESSAGE_CHANNEL_3 = 0x6000,
    FLAG_MESSAGE_CHANNEL_4 = 0x8000,
    FLAG_MESSAGE_CHANNEL_5 = 0xA000,
    FLAG_MESSAGE_CHANNEL_6 = 0xC000,
    FLAG_MESSAGE_CHANNEL_7 = 0xE000
};

#define FLAG_MESSAGE_CONFIRM_REQUIRED   0x0001U

// 29-bit message identifier
#define FLAG_MESSAGE_EXTID              0x00000001U
// Remote frame
#define FLAG_MESSAGE_RTR                0x00000002U
// CAN-FD frame
#define FLAG_MESSAGE_FDF                0x00000004U
// CAN-FD bit rate switch
#define FLAG_MESSAGE_BRS                0x00000008U
// CAN-FD Error status indicator
#define FLAG_MESSAGE_ESI                0x00000010U
// Block TX
#define FLAG_MESSAGE_BLOCK_TX           0x30000000U

typedef struct {
    uint32_t flags;                             // 4 bytes
    uint32_t time;                              // 4 bytes
    uint32_t msgID;                             // 4 bytes
    uint32_t dlc;                               // 4 bytes
    uint8_t  data[64];
} __attribute__((packed)) ToBusMessage;

typedef struct {
    MsgCommandHeader header;
    ToBusMessage message;
} __attribute__((packed)) SendMessage;

Если в поле message.dlc указывается длина передаваемых данных меньше 64 байт, то поле data может соответствовать количеству данных, указанных в message.dlc. Тогда header.dSize уменьшается на величину реально передаваемых данных.

Следует учесть, что по сравнению с первой версией протокола в header.flags указывается только номер канала из FLAG_MESSAGE_CHANNEL_x, через который будет происходить передача данных.
Для настройки формата передаваемых данных теперь используется поле message.flags. Следует учесть, что если для CAN шины в message.flags не выставить флаг FLAG_MESSAGE_BLOCK_TX, то устройство после отправки сообщения в шину вернёт его с соответствующим флагом.

Для обратной совместимости также временно поддерживается старая структура отправки сообщений в шину.

Запрос

Поле Значение
header.command 0x40
header.sequence порядковый номер запроса
header.flags FLAG_MESSAGE_CHANNEL_x
header.dSize 0x10 - 0x50
message.flags FLAG_MESSAGE_xxxx
message.time всегда 0
message.msgID идентификатор отправляемого сообщения
message.dlc размер передаваемых данных в шину
message.data данные, передаваемые в шину

Ответ
Если выставлен флаг FLAG_MESSAGE_CONFIRM_REQUIRED в поле header.flags и запрос успешно обработан.

Поле Значение
command 0xC0
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Передача 4 байт данных в шину с 29 битным идентификатором сообщения 0x1FF00000.

⇒ 40 xx 00 20 14 00 01 00 00 30 00 00 00 00 00 00 F0 1F 04 00 00 00 00 00 07 F0

Передача RTR запроса в шину с 11 битным идентификатором сообщения 0x2FF.

⇒ 40 xx 00 20 10 00 02 00 00 30 00 00 00 00 FF 02 00 00 04 00 00 00

Выставить ответ в шину (COMMAND_SLAVE_RESPONSE_SET 0x4A)

Данная команда используется для выставления Slave ответа в LIN шине. Данная команда использует следующую структуру данных:

typedef struct {
    uint32_t msgID;
    uint8_t dlc;
    uint8_t data[8];
} __attribute__((packed)) ToBusMessage;

typedef struct {
    CommandHeader header;
    ToBusMessage slave;
} __attribute__((packed)) SlaveResponse;

Если в поле slave.dlc указывается длина передаваемых данных меньше 8 байт, то поле data может соответствовать количеству данных, указанных в slave.dlc. Тогда header.dSize уменьшается на величину реально передаваемых данных.
Здесь указывается для какого сообщения необходимо выставить Slave ответ. Идентификатор сообщения может быть как с выставленными битами защиты, так и со сброшенными.

Запрос

Поле Значение
header.command 0x4A
header.sequence порядковый номер запроса
header.flags FLAG_CHANNEL_x
header.dSize длина передаваемых данных
slave.msgID идентификатор отслеживаемого сообщения
slave.dlc размер передаваемых данных в шину
slave.data данные, передаваемые в шину

Ответ

Поле Значение
command 0xCA
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Если запрос не обработан.

Поле Значение
command 0xFF
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Необходимо при получении сообщения (биты защиты сброшены) передать 4 байта данных.

⇒ 4A xx 20 09 00 00 00 01 04 00 00 07 F0
⇐ СA xx 00 00

Выставить режим формирования ответа в шину (COMMAND_SLAVE_RESPONSE_MODE 0x4B)

Выставление режима формирования ответа в LIN-шину переводит устройство в целом в режим SLAVE. В итоге из панели передачи данных вы не сможете отправлять пакеты в LIN-шину. Режим работы задаётся выставлением в поле flags заголовка запроса соответствующего значения.
Возможные значения:

enum FLAG_LIN_SLAVE_MODES {
    FLAG_LIN_SLAVE_MODE_OFF = 0x00,
    FLAG_LIN_SLAVE_MODE_ON  = 0x01
};

Запрос

Поле Значение
command 0x4B
sequence порядковый номер запроса
flags FLAG_CHANNEL_x + FLAG_LIN_SLAVE_MODES
dSize 0x00

Ответ

Поле Значение
command 0xCB
sequence порядковый номер запроса
flags 0x00
dSize 0x00

Пример
Включение SLAVE режима для LIN-шины.

⇒ 4B xx 21 00
⇐ CB xx 00 00

Попытка выключения SLAVE режима на несуществующем LIN-канале.

⇒ 4B xx A0 00
⇐ FF xx 00 00

Получение сообщения из шины (COMMAND_MESSAGE 0x40)

Получение данных из шины происходит с использованием следующих структур:

enum FLAG_MESSAGE_CHANNELS {
    FLAG_MESSAGE_CHANNEL_1 = 0x2000,
    FLAG_MESSAGE_CHANNEL_2 = 0x4000,
    FLAG_MESSAGE_CHANNEL_3 = 0x6000,
    FLAG_MESSAGE_CHANNEL_4 = 0x8000,
    FLAG_MESSAGE_CHANNEL_5 = 0xA000,
    FLAG_MESSAGE_CHANNEL_6 = 0xC000,
    FLAG_MESSAGE_CHANNEL_7 = 0xE000
};

// 29-bit message identifier
#define FLAG_MESSAGE_EXTID              0x00000001U
// Remote frame
#define FLAG_MESSAGE_RTR                0x00000002U
// CAN-FD frame
#define FLAG_MESSAGE_FDF                0x00000004U
// CAN-FD bit rate switch
#define FLAG_MESSAGE_BRS                0x00000008U
// CAN-FD Error status indicator
#define FLAG_MESSAGE_ESI                0x00000010U
// LIN Master request
#define FLAG_MESSAGE_MR                 0x00000100U
// LIN Slave response
#define FLAG_MESSAGE_SR                 0x00000200U
// Classic CRC for LIN
#define FLAG_MESSAGE_CC                 0x00001000U
// Enhanced CRC for LIN
#define FLAG_MESSAGE_EC                 0x00002000U
// Error frame
#define FLAG_MESSAGE_EF                 0x01000000U
// RX
#define FLAG_MESSAGE_RX                 0x10000000U
// TX
#define FLAG_MESSAGE_TX                 0x20000000U

typedef struct {
    uint32_t flags;   // флаги сообщения
    uint32_t time;    // время получения сообщения из шины в микросекундах по внутренним часам устройства
    uint32_t crc;     // предполагаемая контрольная сумма сообщения. используется для LIN. в остальных случаях не определено.
    uint32_t msgID;
    uint32_t dlc;
    uint8_t data[64];
} __attribute__((packed)) BusMessage;

typedef struct {
    MsgCommandHeader header;
    BusMessage message;
} __attribute__((packed)) RcvMessage;

Если в поле message.dlc указывается длина передаваемых данных меньше 64 байт, то поле data может соответствовать количеству данных, указанных в message.dlc. Тогда header.dSize уменьшается на величину реально передаваемых данных.

Для обратной совместимости также временно поддерживается старая структура приёма сообщений из шины.

Получение статуса шины (COMMAND_BUS_ERROR 0x48)

Данная команда от устройства возвращает статус шины в случае возникновения ошибки. Если в последствии ошибка на шине уходит, то приходит команда со статусом ошибки 0.
Команда со статусом шины может принимать следующие значения:

// Для прошивок 2.2.х.х
#define ERROR_LIN_PARITY                0x00000001U
#define ERROR_LIN_FRAME                 0x00000002U

#define ERROR_CAN_STUFF                 0x00000001U
#define ERROR_CAN_FORMAT                0x00000002U
#define ERROR_CAN_ACK                   0x00000004U
#define ERROR_CAN_CRC                   0x00000008U
#define ERROR_CAN_TRANSMIT1             0x00000010U
#define ERROR_CAN_TRANSMIT0             0x00000020U
#define ERROR_BUS_OFF                   0x00000040U
#define ERROR_PASSIVE                   0x00000080U
#define ERROR_WARNING                   0x00000100U
#define ERROR_OVERFLOW                  0x00000200U
#define ERROR_DATA_STUFF                0x00010000U
#define ERROR_DATA_FORMAT               0x00020000U
#define ERROR_DATA_ACK                  0x00040000U
#define ERROR_DATA_CRC                  0x00080000U
#define ERROR_DATA_TRANSMIT1            0x00100000U
#define ERROR_DATA_TRANSMIT0            0x00200000U

// Для прошивок 2.3.х.х и новее
#define ERROR_LIN_PARITY                0x00000001U
#define ERROR_LIN_FRAME                 0x00000002U

#define ERROR_CAN_STUFF                 0x00000001U
#define ERROR_CAN_FORMAT                0x00000002U
#define ERROR_CAN_ACK                   0x00000003U
#define ERROR_CAN_CRC                   0x00000004U
#define ERROR_CAN_TRANSMIT1             0x00000005U
#define ERROR_CAN_TRANSMIT0             0x00000006U
#define ERROR_BUS_OFF                   0x00000040U
#define ERROR_PASSIVE                   0x00000080U
#define ERROR_WARNING                   0x00000100U
#define ERROR_OVERFLOW                  0x00000200U
#define ERROR_DATA_STUFF                0x00010000U
#define ERROR_DATA_FORMAT               0x00020000U
#define ERROR_DATA_ACK                  0x00030000U
#define ERROR_DATA_CRC                  0x00040000U
#define ERROR_DATA_TRANSMIT1            0x00050000U
#define ERROR_DATA_TRANSMIT0            0x00060000U

typedef struct {
    CommandHeader header;
    uint32_t error;
} __attribute__((packed)) BusError;

В поле header.flags будет указан номер канала, для которого пришло данное сообщение.