---
description: Использование FDCAN для общения между STM32 и Raspberry PI
---

# Коммуникации - FDCAN

{% hint style="warning" %}
В рамках этого раздела не будет разбираться подключение к raspberry pi по **ssh**, написание программ на raspberry (через VSCode или иначе). Предполагается, что читатель знает как это делать.

Также, не будет обсуждаться обычный (classic) CAN. Он является "подмножеством" FDCAN и при необходимости перейти на него, уже зная FDCAN, не сложно.
{% endhint %}

## FDCAN

Протокол коммуникации FDCAN позволяет связать множество устройств в одну сеть. В сети нет фиксированного "_мастера_" или роутера, назначающего адреса устройств. Все сообщения отправляются "_широковещательно_" (broadcast) и видны каждому узлу сети. Фильтрацию сообщений можно настроить на приемники по id сообщения - какого вида сообщения принимать, а какие отбрасывать. Это быстрый, одноранговый (а значит устойчивый к отказу некоторых узлов) и надежный (при корректной настройке) протокол.

### Меры предосторожности

При использовании FDCAN важно одинаково настроить время передачи одного бита (`bit timing`) и длину всех сегментов сообщения на каждом устройстве в сети. Если одно из устройств переиодически (или, в худшем случае, постоянно) посылает в сеть сообщения с неверными таймингами, это может привети к нестабильности отправки/ получения сообщений или вообще "распаду" всей сети.

Во-первых, такое устройство может "перехватить" всю сеть, игнорируя попытки других узлов отправлять сообщения (т.к. не может нормально читать их биты). Во-вторых, если некорректные сообщения посылаются регулярно, это переполнит счетчик ошибок других узлов и переведет к их "выходу" из сети. Одним словом, некорректные тайминги - ахилесова пята и одновременно самая запутанная часть работы с FDCAN. Но после того как удалось один раз настроить все правильно, дальнейшая работа значительно облегчается.

## Настройка

### Raspberry Pi

Для использования FDCAN на raspberry pi, нам понадобится rpi с _can-shield_, подключенным к соответствующим пинам на контроллере (`CAN H, CAN L`). Выглядит это так (вариантов подключения масса, это самый общий пример):

<figure><img src="https://3551773033-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBjLyfPc4FcQUfXFi5fQr%2Fuploads%2FFJPTafG3x1bEw1JRyVjb%2F2023-10-13%2015.52.51.jpg?alt=media&#x26;token=b6f7a001-9171-49d1-8c40-00c603e0b58d" alt=""><figcaption><p>Соединение rpi и vbcore</p></figcaption></figure>

Обратите внимание, что переключатели над `CAN0, CAN1` в положении `ON`.

Далее, нам необходимо настроить ОС на работу с новой переферией:

1. Откройте `config.txt`: `sudo nano /boot/config.txt`
2. Добавьте слеедующие строки в конец файла:

```
dtparam=spi=on
dtoverlay=spi1-3cs
dtoverlay=mcp251xfd,spi0-0,interrupt=25
dtoverlay=mcp251xfd,spi0-1,interrupt=24
```

4. Сохраните файл: `Ctrl+O, Ctrl+X`
5. `sudo reboot now`

Теперь raspberry pi готова работать с шилдом. Однако, нам все еще надо настроить _сетевые интерфейсы_ `can0, can1`. Для этого, каждый раз после перезапуска rpi, нам надо выполнять следующие команды (или можете сделать systemd unit для них по аналогии с [explorer\_units/board](https://github.com/voltbro/explorer_units/tree/master/board), но если вы не знаете что такое systemd, то просто выполняйте их вручную):

<pre class="language-bash"><code class="lang-bash"><strong>ip link set can0 up txqueuelen 65535 type can bitrate 500000 dbitrate 4000000 restart-ms 1000 berr-reporting on fd on
</strong>
ip link set can1 up txqueuelen 65535 type can bitrate 500000 dbitrate 4000000 restart-ms 1000 berr-reporting on fd on
</code></pre>

Тут мы настраиваем оба интерфейса на битрейт 500кбит/4мбит. Это половина от максимального, но больше нам и не нужно.

Далее, необходимо установить пакет `can-utils`: `sudo apt install can-utils`.

Самый просто способ проверить, что теперь все работает, это подключить на шилде `CAN0 L, H <-> CAN1 L, H` и открыть два терминала на rpi. В одном - `candump can0`. Это будет печатать все приходящие сообщения. В другом - `cangen -mv can1`. Это будет генерировать случайный сообщения. Если отправленные/пришедшие сообщения совпадают, то все прошло удачно.

### STM32

Для активации FDCAN на STM32, нам необходимо включить соответствующий блок переферии:

<figure><img src="https://3551773033-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBjLyfPc4FcQUfXFi5fQr%2Fuploads%2FtufhxWsnHB0pR65NQEY3%2F%D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA%20%D1%8D%D0%BA%D1%80%D0%B0%D0%BD%D0%B0%202023-10-13%20%D0%B2%2015.52.33.png?alt=media&#x26;token=1943bfe6-a532-45c0-a34c-e558cb9337e2" alt=""><figcaption><p>Настройка ioc</p></figcaption></figure>

Тут уже даны все правильные параметры таймингов. Для целей обучения достаточно просто переписать их, не вникая, откуда они взялись.

<details>

<summary>Для страждущих - как узнать тайминги самому</summary>

Тут **не будет&#x20;**_**объяснения**_ за что отвечает каждый сегмент (`seg`), что такое data и nominal битрейты и т.д., это читайте в **стандарте FDCAN**. Однакое даже без этого понимания есть читерский способ как узнать нужные тайминги.

Для этого, вернемся к команде настройки сетевых интерфейсов (разберем только `can0`):

<pre class="language-bash"><code class="lang-bash"><strong>ip link set can0 up txqueuelen 65535 type can bitrate 500000 dbitrate 4000000 restart-ms 1000 berr-reporting on fd on
</strong></code></pre>

Тут есть два битрейта - 500000 и 4000000. Их можно поменять, проще всего их оба умножать/делить на одно и то же число. Рассмотрим однако данный битрейт. После найстроки, мы можем посмотреть параметры интерфейса:

<pre class="language-bash"><code class="lang-bash"><strong>>>> sudo ip -details link show can0
</strong><strong>
</strong>3: can0: &#x3C;NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UP mode DEFAULT group default qlen 65535
    link/can  promiscuity 0 minmtu 0 maxmtu 0 
    can &#x3C;BERR-REPORTING,FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 1000 
	  bitrate 500000 sample-point 0.875 
	  tq 25 prop-seg 34 phase-seg1 35 phase-seg2 10 sjw 1
	  mcp251xfd: tseg1 2..256 tseg2 1..128 sjw 1..128 brp 1..256 brp-inc 1
	  dbitrate 4000000 dsample-point 0.700 
	  dtq 25 dprop-seg 3 dphase-seg1 3 dphase-seg2 3 dsjw 1
	  mcp251xfd: dtseg1 1..32 dtseg2 1..16 dsjw 1..16 dbrp 1..256 dbrp-inc 1
	  clock 40000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 
</code></pre>

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

* dprop-seg + dphase-seg1 = data time seg1
* dphase-seg2 = data time seg2
* dsjw \* dphase-seg1 = data sync jump width

- prop-seg + phase-seg1 = nominal time seg1
- phase-seg2 = nominal time seg2
- sjw \* phase-seg1 = nominal sync jump width

tq - по сути, "период" fdcan в наносекундах. Частоту fdcan на стороне stm можно найти в `clock configuration` справа внизу. Соответственно, с помощью `clock divider` и `nominal prescaler` надо добиться, чтобы частота была равна 1/tq. Для dtq и `data prescaler` - аналогично.

</details>

***

## Программирование

## RPI <-> RPI

TODO

## RPI <-> STM32

TODO
