# 应用与实践

### Can-festival 使用

概述

- CanFestival是一个开源（LGPL和GPL）CANopen框架。遵循ANSI-C，支持多平台。Canfestival是一个通信库，它的作用是掌握通信并把通信功能全部包揽过来
- Canfestival最主要的思想有两个，一个是字典思想，所有的参数和配置都是存在字典里面的。Canfestival能够运行于多种类型的平台

可根据手册进行 can-festival 源码移植与开发，其中包含有 xenomai 的编译方法，可快速移植并测试实时程序

### 使用 can-festival 与 rtcan 驱动在 sx21 上的测试说明

1. 移植 can-festival 源码
2. 重新编译 kernel ，并选择支持 rtcan 驱动
3. 编写 can-festival 实时程序，并选择驱动为 rtcan 设备
4. 测试 jitter

#### 程序源码以及 can-festival 协议层驱动说明

在 Linux 系统中， CAN 总线接口设备作为网络设备被系统进行统一管理，所以使用标准 posix socket 接口操作 can 设备，在编译实时程序时只需在链接时添加 xenomai 库即可完成 posix rt 程序编译 在使用 rtcan 驱动时，通过 Alchemy 接口操作 rtcan 设备即可

详细规则如下

    // ...
    // 通过 RTCAN_SOCKET 宏控制驱动普通 can 设备以及 rtcan 设备
    #define RTCAN_SOCKET

    #ifdef RTCAN_SOCKET
    #include "rtdm/rtcan.h"
    #define CAN_IFNAME     "rtcan%s"
    #define CAN_SOCKET     rt_dev_socket
    #define CAN_CLOSE      rt_dev_close
    #define CAN_RECV       rt_dev_recv
    #define CAN_SEND       rt_dev_send
    #define CAN_BIND       rt_dev_bind
    #define CAN_IOCTL      rt_dev_ioctl
    #define CAN_SETSOCKOPT rt_dev_setsockopt
    #define CAN_ERRNO(err) (-err)
    #else
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/ioctl.h>
    #include "linux/can.h"
    #include "linux/can/raw.h"
    #include "net/if.h"
    #ifndef PF_CAN
    #define PF_CAN 29
    #endif

    // ...

在链接时需添加如下链接库即可

Warning

- canfestival_can_socket 为 can-festival 协议层驱动源文件生成的动态库名
- 当使用 Alchemy 接口时，需要额外链接 alchemy 库

    target_link_libraries(canfestival_can_socket PUBLIC
        -Wl,--no-as-needed -Wl,@${XENO_LIBS_DIR}/cobalt.wrappers
        -Wl,@${XENO_LIBS_DIR}/modechk.wrappers ${XENO_LIBS_DIR}/xenomai/bootstrap.o
        -Wl,--wrap=main
        -Wl,--dynamic-list=${XENO_LIBS_DIR}/dynlist.ld
        alchemy copperplate
        cobalt modechk
    )

以 linux 系统为例, 安装方式如下

Warning 其他部分则需要调整 can-festival 源码中 times-xxx 的实现部分

- 通用 unix 接口（标准 posix 接口） can-festival 协议层驱动源文件使用 drivers/timers_unix
- alchemy 接口 can-festival 协议层驱动源文件使用 drivers/timers_xeno

目录结构

    ├── drivers
    │   ├── can_socket
    │   │   ├── can_socket.c
    │   │   └── CMakeLists.txt
    │   ├── timers_unix
    │   │   ├── Makefile
    │   │   ├── Makefile.in
    │   │   ├── timers_unix.c
    │   ├── timers_xeno
    │   │   ├── Makefile
    │   │   ├── Makefile.in
    │   │   └── timers_xeno.c
    │   └── unix
    │       ├── libcanfestival_unix.a
    │       ├── Makefile
    │       ├── Makefile.in
    │       ├── unix.c

用户需根据目标产物更换不用协议层驱动

    set(
        SRC_LISTS
        example/TestMasterMicroMod/TestMasterMicroMod.c
        example/TestMasterMicroMod/TestMaster.c
        # ...
        # ...
        src/timer.c
        # drivers/timers_unix/timers_unix.c # 编译标准 posix 接口的协议层驱动实现
        drivers/timers_xeno/timers_xeno.c # 编译 Alchemy 接口的协议层驱动实现
        drivers/unix/unix.c
    )

    add_executable(${CMAKE_PROJECT_NAME} ${SRC_LISTS})